Bug 1633270 - view application/octet-stream PDFs in PDF.JS and add a pref to turn this off, r=jaws
☠☠ backed out by 7a039ce49922 ☠ ☠
authorGijs Kruitbosch <gijskruitbosch@gmail.com>
Sat, 16 May 2020 00:51:37 +0000
changeset 594224 77d5aff05a0e0e4bd87fb75a4256845f83da76cc
parent 594223 cb53eac110d197f0b514c3df268dbae573b1439e
child 594225 7a039ce4992268e293abc61a441a4aa06aaeda3c
push id13186
push userffxbld-merge
push dateMon, 01 Jun 2020 09:52:46 +0000
treeherdermozilla-beta@3e7c70a1e4a1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjaws
bugs1633270
milestone78.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1633270 - view application/octet-stream PDFs in PDF.JS and add a pref to turn this off, r=jaws Differential Revision: https://phabricator.services.mozilla.com/D75582
browser/app/profile/firefox.js
browser/extensions/pdfjs/components.conf
browser/extensions/pdfjs/content/PdfStreamConverter.jsm
browser/extensions/pdfjs/test/browser.ini
browser/extensions/pdfjs/test/browser_pdfjs_octet_stream.js
browser/extensions/pdfjs/test/file_pdfjs_object_stream.pdf
browser/extensions/pdfjs/test/file_pdfjs_object_stream.pdf^headers^
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1367,16 +1367,19 @@ pref("pdfjs.disabled", false);
 // Used by pdf.js to know the first time firefox is run with it installed so it
 // can become the default pdf viewer.
 pref("pdfjs.firstRun", true);
 // The values of preferredAction and alwaysAskBeforeHandling before pdf.js
 // became the default.
 pref("pdfjs.previousHandler.preferredAction", 0);
 pref("pdfjs.previousHandler.alwaysAskBeforeHandling", false);
 
+// Try to convert PDFs sent as octet-stream
+pref("pdfjs.handleOctetStream", true);
+
 // Is the sidebar positioned ahead of the content browser
 pref("sidebar.position_start", true);
 
 pref("security.identitypopup.recordEventTelemetry", true);
 pref("security.protectionspopup.recordEventTelemetry", true);
 pref("security.app_menu.recordEventTelemetry", true);
 
 // Block insecure active content on https pages
--- a/browser/extensions/pdfjs/components.conf
+++ b/browser/extensions/pdfjs/components.conf
@@ -5,13 +5,15 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 Classes = [
     {
         'cid': '{d0c5195d-e798-49d4-b1d3-9324328b2291}',
         'contract_ids': [
             '@mozilla.org/streamconv;1?from=application/pdf&to=*/*',
             '@mozilla.org/streamconv;1?from=application/pdf&to=text/html',
+            '@mozilla.org/streamconv;1?from=application/octet-stream&to=*/*',
+            '@mozilla.org/streamconv;1?from=application/octet-stream&to=text/html',
         ],
         'jsm': 'resource:///modules/pdfjs.js',
         'constructor': 'StreamConverterFactory',
     },
 ]
--- a/browser/extensions/pdfjs/content/PdfStreamConverter.jsm
+++ b/browser/extensions/pdfjs/content/PdfStreamConverter.jsm
@@ -1104,23 +1104,42 @@ PdfStreamConverter.prototype = {
     mime.preferredAction = Ci.nsIHandlerInfo.handleInternally;
     mime.alwaysAskBeforeHandling = false;
     Svc.handlers.store(mime);
     return true;
   },
 
   getConvertedType(aFromType, aChannel) {
     const HTML = "text/html";
+    let channelURI = aChannel?.URI;
+    // We can be invoked for application/octet-stream; check if we want the
+    // channel first:
+    if (aFromType != "application/pdf") {
+      let isPDF = channelURI?.QueryInterface(Ci.nsIURL).fileExtension == "pdf";
+      let typeIsOctetStream = aFromType == "application/octet-stream";
+      if (
+        !isPDF ||
+        !typeIsOctetStream ||
+        !getBoolPref(PREF_PREFIX + ".handleOctetStream", false)
+      ) {
+        throw new Components.Exception(
+          "Ignore PDF.js for this download.",
+          Cr.NS_ERROR_FAILURE
+        );
+      }
+      // fall through, this appears to be a pdf.
+    }
+
     if (this._validateAndMaybeUpdatePDFPrefs()) {
       return HTML;
     }
     // Hm, so normally, no pdfjs. However... if this is a file: channel loaded
     // with system principal, load it anyway:
-    if (aChannel && aChannel.URI.schemeIs("file")) {
-      let triggeringPrincipal = aChannel?.loadInfo?.triggeringPrincipal;
+    if (channelURI?.schemeIs("file")) {
+      let triggeringPrincipal = aChannel.loadInfo?.triggeringPrincipal;
       if (triggeringPrincipal?.isSystemPrincipal) {
         return HTML;
       }
     }
 
     throw new Components.Exception("Can't use PDF.js", Cr.NS_ERROR_FAILURE);
   },
 
--- a/browser/extensions/pdfjs/test/browser.ini
+++ b/browser/extensions/pdfjs/test/browser.ini
@@ -1,13 +1,17 @@
 [DEFAULT]
 support-files =
   file_pdfjs_test.pdf
   head.js
 
 [browser_pdfjs_force_opening_files.js]
 [browser_pdfjs_main.js]
 [browser_pdfjs_navigation.js]
+[browser_pdfjs_octet_stream.js]
+support-files =
+  file_pdfjs_object_stream.pdf
+  file_pdfjs_object_stream.pdf^headers^
 [browser_pdfjs_savedialog.js]
 skip-if = verify
 [browser_pdfjs_views.js]
 [browser_pdfjs_zoom.js]
 skip-if = (verify && debug && (os == 'win'))
new file mode 100644
--- /dev/null
+++ b/browser/extensions/pdfjs/test/browser_pdfjs_octet_stream.js
@@ -0,0 +1,45 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const TESTROOT = getRootDirectory(gTestPath).replace(
+  "chrome://mochitests/content/",
+  "http://mochi.test:8888/"
+);
+
+/**
+ * Check that if we open a PDF with octet-stream mimetype, it can load
+ * PDF.js .
+ */
+add_task(async function test_octet_stream_opens_pdfjs() {
+  await SpecialPowers.pushPrefEnv({ set: [["pdfjs.handleOctetStream", true]] });
+  // Get a ref to the pdf we want to open.
+  let pdfURL = TESTROOT + "file_pdfjs_object_stream.pdf";
+
+  let mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
+  let handlerInfo = mimeService.getFromTypeAndExtension(
+    "application/pdf",
+    "pdf"
+  );
+
+  // Make sure pdf.js is the default handler.
+  is(
+    handlerInfo.alwaysAskBeforeHandling,
+    false,
+    "pdf handler defaults to always-ask is false"
+  );
+  is(
+    handlerInfo.preferredAction,
+    Ci.nsIHandlerInfo.handleInternally,
+    "pdf handler defaults to internal"
+  );
+
+  await BrowserTestUtils.withNewTab(
+    { gBrowser, url: "about:blank" },
+    async function(newTabBrowser) {
+      await waitForPdfJS(newTabBrowser, pdfURL);
+      is(newTabBrowser.currentURI.spec, pdfURL, "Should load pdfjs");
+    }
+  );
+});
copy from docshell/test/browser/file_bug852909.pdf
copy to browser/extensions/pdfjs/test/file_pdfjs_object_stream.pdf
new file mode 100644
--- /dev/null
+++ b/browser/extensions/pdfjs/test/file_pdfjs_object_stream.pdf^headers^
@@ -0,0 +1,2 @@
+Content-Type: application/octet-stream
+