Commit 0f2b360a authored by Pier Angelo Vendrame's avatar Pier Angelo Vendrame 🎃 Committed by morgan
Browse files

BB 42220: Allow for more file types to be forced-inline.

Firefox allows to open some files in the browser without any
confirmation, but this will result in a disk leak, because the file will
be downloaded to the temporary directory first (and not deleted, in some
cases).
A preference allows PDFs to be opened without being downloaded to disk.
So, we introduce a similar one to do the same for all the files that are
set to be opened automatically in the browser, except svg and html files
to prevent XSS hazards (see BB 43211).
parent fb4fc951
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -1446,6 +1446,12 @@
  value: false
  mirror: always

# tor-browser#42220
- name: browser.download.ignore_content_disposition
  type: bool
  value: true
  mirror: always

# See bug 1811830
- name: browser.download.force_save_internally_handled_attachments
  type: bool
+65 −27
Original line number Diff line number Diff line
@@ -314,25 +314,62 @@ nsresult nsDocumentOpenInfo::DispatchContent(nsIRequest* request) {
    forceExternalHandling = false;
  }

  if (forceExternalHandling &&
      (mozilla::StaticPrefs::browser_download_open_pdf_attachments_inline() ||
       mozilla::StaticPrefs::browser_download_ignore_content_disposition())) {
    // Check if this is a PDF which should be opened internally. We also handle
    // octet-streams that look like they might be PDFs based on their extension.
  if (forceExternalHandling &&
      mozilla::StaticPrefs::browser_download_open_pdf_attachments_inline() &&
      IsContentPDF(aChannel, mContentType)) {
    // For a PDF, check if the preference is set that forces attachments to be
    // opened inline. If so, treat it as a non-attachment by clearing
    // 'forceExternalHandling' again. This allows it open a PDF directly
    // instead of downloading it first. It may still end up being handled by
    // a helper app depending anyway on the later checks.
    bool isPDF = IsContentPDF(aChannel, mContentType);
    nsAutoCString ext;
    if (!isPDF &&
        (mContentType.LowerCaseEqualsASCII(APPLICATION_OCTET_STREAM) ||
         mContentType.IsEmpty())) {
      nsAutoString flname;
      aChannel->GetContentDispositionFilename(flname);
      if (!flname.IsEmpty()) {
        int32_t extStart = flname.RFindChar(u'.');
        if (extStart != kNotFound) {
          CopyUTF16toUTF8(Substring(flname, extStart + 1), ext);
        }
      }
      if (ext.IsEmpty()) {
        nsCOMPtr<nsIURI> uri;
        aChannel->GetURI(getter_AddRefs(uri));
        nsCOMPtr<nsIURL> url(do_QueryInterface(uri));
        if (url) {
          url->GetFileExtension(ext);
        }
      }
    }

    // One of the preferences to forces attachments to be opened inline is set.
    // If so, treat it as a non-attachment by clearing 'forceExternalHandling'
    // again. This allows it open a file directly instead of downloading it
    // first. It may still end up being handled by a helper app depending anyway
    // on the later checks.
    if (isPDF ||
        (mozilla::StaticPrefs::browser_download_ignore_content_disposition() &&
         // we want to exclude html and svg files, which could execute
         // scripts (tor-browser#43211)
         kNotFound == mContentType.LowerCaseFindASCII("html") &&
         kNotFound == ext.LowerCaseFindASCII("htm") &&
         kNotFound == mContentType.LowerCaseFindASCII("/svg+") &&
         !ext.EqualsIgnoreCase("svg"))) {
      nsCOMPtr<nsILoadInfo> loadInfo;
      aChannel->GetLoadInfo(getter_AddRefs(loadInfo));

      nsCOMPtr<nsIMIMEInfo> mimeInfo;

    nsCOMPtr<nsIMIMEService> mimeSvc(do_GetService(NS_MIMESERVICE_CONTRACTID));
      nsCOMPtr<nsIMIMEService> mimeSvc(
          do_GetService(NS_MIMESERVICE_CONTRACTID));
      NS_ENSURE_TRUE(mimeSvc, NS_ERROR_FAILURE);
    mimeSvc->GetFromTypeAndExtension(nsLiteralCString(APPLICATION_PDF), ""_ns,
      if (isPDF) {
        mimeSvc->GetFromTypeAndExtension(nsLiteralCString(APPLICATION_PDF),
                                         ""_ns, getter_AddRefs(mimeInfo));
      } else {
        mimeSvc->GetFromTypeAndExtension(mContentType, ext,
                                         getter_AddRefs(mimeInfo));
      }

      if (mimeInfo) {
        int32_t action = nsIMIMEInfo::saveToDisk;
@@ -344,6 +381,7 @@ nsresult nsDocumentOpenInfo::DispatchContent(nsIRequest* request) {
            alwaysAsk || action != nsIMIMEInfo::handleInternally;
      }
    }
  }

  if (!forceExternalHandling) {
    //