summaryrefslogtreecommitdiffstats
path: root/toolkit/components/pdfjs/test
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--toolkit/components/pdfjs/test/.eslintrc.js5
-rw-r--r--toolkit/components/pdfjs/test/browser.ini35
-rw-r--r--toolkit/components/pdfjs/test/browser_pdfjs_fill_login.js108
-rw-r--r--toolkit/components/pdfjs/test/browser_pdfjs_find.js23
-rw-r--r--toolkit/components/pdfjs/test/browser_pdfjs_force_opening_files.js68
-rw-r--r--toolkit/components/pdfjs/test/browser_pdfjs_form.js85
-rw-r--r--toolkit/components/pdfjs/test/browser_pdfjs_main.js72
-rw-r--r--toolkit/components/pdfjs/test/browser_pdfjs_navigation.js320
-rw-r--r--toolkit/components/pdfjs/test/browser_pdfjs_not_default.js26
-rw-r--r--toolkit/components/pdfjs/test/browser_pdfjs_notification_close_on_navigation.js43
-rw-r--r--toolkit/components/pdfjs/test/browser_pdfjs_octet_stream.js81
-rw-r--r--toolkit/components/pdfjs/test/browser_pdfjs_saveas.js135
-rw-r--r--toolkit/components/pdfjs/test/browser_pdfjs_savedialog.js43
-rw-r--r--toolkit/components/pdfjs/test/browser_pdfjs_views.js108
-rw-r--r--toolkit/components/pdfjs/test/browser_pdfjs_zoom.js272
-rw-r--r--toolkit/components/pdfjs/test/file_pdfjs_form.pdfbin0 -> 8586 bytes
-rw-r--r--toolkit/components/pdfjs/test/file_pdfjs_object_stream.pdfbin0 -> 1568 bytes
-rw-r--r--toolkit/components/pdfjs/test/file_pdfjs_object_stream.pdf^headers^2
-rw-r--r--toolkit/components/pdfjs/test/file_pdfjs_test.pdfbin0 -> 150611 bytes
-rw-r--r--toolkit/components/pdfjs/test/head.js71
20 files changed, 1497 insertions, 0 deletions
diff --git a/toolkit/components/pdfjs/test/.eslintrc.js b/toolkit/components/pdfjs/test/.eslintrc.js
new file mode 100644
index 0000000000..1779fd7f1c
--- /dev/null
+++ b/toolkit/components/pdfjs/test/.eslintrc.js
@@ -0,0 +1,5 @@
+"use strict";
+
+module.exports = {
+ extends: ["plugin:mozilla/browser-test"],
+};
diff --git a/toolkit/components/pdfjs/test/browser.ini b/toolkit/components/pdfjs/test/browser.ini
new file mode 100644
index 0000000000..1edf4699cc
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser.ini
@@ -0,0 +1,35 @@
+[DEFAULT]
+support-files =
+ file_pdfjs_test.pdf
+ head.js
+
+[browser_pdfjs_fill_login.js]
+support-files =
+ file_pdfjs_form.pdf
+[browser_pdfjs_find.js]
+support-files =
+ file_pdfjs_object_stream.pdf
+ file_pdfjs_object_stream.pdf^headers^
+[browser_pdfjs_force_opening_files.js]
+[browser_pdfjs_form.js]
+support-files =
+ file_pdfjs_form.pdf
+[browser_pdfjs_main.js]
+[browser_pdfjs_navigation.js]
+[browser_pdfjs_not_default.js]
+support-files =
+ file_pdfjs_object_stream.pdf
+ file_pdfjs_object_stream.pdf^headers^
+[browser_pdfjs_notification_close_on_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_saveas.js]
+support-files =
+ !/toolkit/content/tests/browser/common/mockTransfer.js
+[browser_pdfjs_views.js]
+[browser_pdfjs_zoom.js]
+skip-if = (verify && debug && (os == 'win'))
diff --git a/toolkit/components/pdfjs/test/browser_pdfjs_fill_login.js b/toolkit/components/pdfjs/test/browser_pdfjs_fill_login.js
new file mode 100644
index 0000000000..8d9c022705
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser_pdfjs_fill_login.js
@@ -0,0 +1,108 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const RELATIVE_DIR = "toolkit/components/pdfjs/test/";
+const TESTROOT = "http://example.com/browser/" + RELATIVE_DIR;
+
+// This is a modified version from browser_contextmenuFillLogins.js.
+async function openContextMenuForSelector(browser, selector) {
+ const doc = browser.ownerDocument;
+ const CONTEXT_MENU = doc.getElementById("contentAreaContextMenu");
+
+ let contextMenuShownPromise = BrowserTestUtils.waitForEvent(
+ CONTEXT_MENU,
+ "popupshown"
+ );
+
+ let inputCoords = await SpecialPowers.spawn(
+ browser,
+ [selector],
+ async selector => {
+ let input = content.document.querySelector(selector);
+ input.focus();
+ let inputRect = input.getBoundingClientRect();
+
+ // listen for the contextmenu event so we can assert on receiving it
+ // and examine the target
+ content.contextmenuPromise = new Promise(resolve => {
+ content.document.body.addEventListener(
+ "contextmenu",
+ event => {
+ info(
+ `Received event on target: ${event.target.nodeName}, type: ${event.target.type}`
+ );
+ content.console.log("got contextmenu event: ", event);
+ resolve(event);
+ },
+ { once: true }
+ );
+ });
+
+ let coords = {
+ x: inputRect.x + inputRect.width / 2,
+ y: inputRect.y + inputRect.height / 2,
+ };
+ return coords;
+ }
+ );
+
+ // add the offsets of the <browser> in the chrome window
+ let browserOffsets = browser.getBoundingClientRect();
+ let offsetX = browserOffsets.x + inputCoords.x;
+ let offsetY = browserOffsets.y + inputCoords.y;
+
+ // Synthesize a right mouse click over the input element, we have to trigger
+ // both events because formfill code relies on this event happening before the contextmenu
+ // (which it does for real user input) in order to not show the password autocomplete.
+ let eventDetails = { type: "mousedown", button: 2 };
+ await EventUtils.synthesizeMouseAtPoint(offsetX, offsetY, eventDetails);
+
+ // Synthesize a contextmenu event to actually open the context menu.
+ eventDetails = { type: "contextmenu", button: 2 };
+ await EventUtils.synthesizeMouseAtPoint(offsetX, offsetY, eventDetails);
+
+ await SpecialPowers.spawn(browser, [], async () => {
+ await content.contextmenuPromise;
+ });
+
+ info("waiting for contextMenuShownPromise");
+
+ await contextMenuShownPromise;
+ return CONTEXT_MENU;
+}
+
+/**
+ * Ensure the fill login context menu is not shown for PDF.js forms.
+ */
+add_task(async function test_filllogin() {
+ await SpecialPowers.pushPrefEnv({
+ set: [["pdfjs.renderInteractiveForms", true]],
+ });
+
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async function(browser) {
+ await waitForPdfJSAnnotationLayer(
+ browser,
+ TESTROOT + "file_pdfjs_form.pdf"
+ );
+
+ let contextMenu = await openContextMenuForSelector(
+ browser,
+ "#viewerContainer input"
+ );
+ let fillItem = contextMenu.querySelector("#fill-login");
+ ok(fillItem, "fill menu item exists");
+ ok(fillItem && EventUtils.isHidden(fillItem), "fill menu item is hidden");
+
+ let promiseHidden = BrowserTestUtils.waitForEvent(
+ contextMenu,
+ "popuphidden"
+ );
+ info("Calling hidePopup on contextMenu");
+ contextMenu.hidePopup();
+ info("waiting for promiseHidden");
+ await promiseHidden;
+ }
+ );
+});
diff --git a/toolkit/components/pdfjs/test/browser_pdfjs_find.js b/toolkit/components/pdfjs/test/browser_pdfjs_find.js
new file mode 100644
index 0000000000..27502a2d26
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser_pdfjs_find.js
@@ -0,0 +1,23 @@
+/* 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/"
+);
+
+// Get a ref to the pdf we want to open.
+const PDF_URL = TESTROOT + "file_pdfjs_object_stream.pdf";
+
+add_task(async function test_find_octet_stream_pdf() {
+ await BrowserTestUtils.withNewTab(PDF_URL, async browser => {
+ let findEls = ["cmd_find", "cmd_findAgain", "cmd_findPrevious"].map(id =>
+ document.getElementById(id)
+ );
+ for (let el of findEls) {
+ ok(!el.hasAttribute("disabled"), `${el.id} should be enabled`);
+ }
+ });
+});
diff --git a/toolkit/components/pdfjs/test/browser_pdfjs_force_opening_files.js b/toolkit/components/pdfjs/test/browser_pdfjs_force_opening_files.js
new file mode 100644
index 0000000000..722a884e8b
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser_pdfjs_force_opening_files.js
@@ -0,0 +1,68 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+add_task(async function test_file_opening() {
+ // Get a ref to the pdf we want to open.
+ let dirFileObj = getChromeDir(getResolvedURI(gTestPath));
+ dirFileObj.append("file_pdfjs_test.pdf");
+
+ // Change the defaults.
+ var oldAction = changeMimeHandler(Ci.nsIHandlerInfo.useSystemDefault, true);
+
+ // Test: "Open with" dialog should not come up, despite pdf.js not being
+ // the default - because files from disk should always use pdfjs, unless
+ // it is forcibly disabled.
+ let openedWindow = false;
+ let windowOpenedPromise = new Promise((resolve, reject) => {
+ addWindowListener(
+ "chrome://mozapps/content/downloads/unknownContentType.xhtml",
+ () => {
+ openedWindow = true;
+ resolve();
+ }
+ );
+ });
+
+ // Open the tab with a system principal:
+ var tab = BrowserTestUtils.addTab(gBrowser, dirFileObj.path);
+
+ let pdfjsLoadedPromise = TestUtils.waitForCondition(() => {
+ let { contentPrincipal } = tab.linkedBrowser;
+ return (contentPrincipal?.URI?.spec || "").endsWith("viewer.html");
+ });
+ await Promise.race([pdfjsLoadedPromise, windowOpenedPromise]);
+ ok(!openedWindow, "Shouldn't open an unknownContentType window!");
+
+ registerCleanupFunction(function() {
+ if (listenerCleanup) {
+ listenerCleanup();
+ }
+ changeMimeHandler(oldAction[0], oldAction[1]);
+ gBrowser.removeTab(tab);
+ });
+});
+
+let listenerCleanup;
+function addWindowListener(aURL, aCallback) {
+ let listener = {
+ onOpenWindow(aXULWindow) {
+ info("window opened, waiting for focus");
+ listenerCleanup();
+ listenerCleanup = null;
+
+ var domwindow = aXULWindow.docShell.domWindow;
+ waitForFocus(function() {
+ is(
+ domwindow.document.location.href,
+ aURL,
+ "should have seen the right window open"
+ );
+ domwindow.close();
+ aCallback();
+ }, domwindow);
+ },
+ onCloseWindow(aXULWindow) {},
+ };
+ Services.wm.addListener(listener);
+ listenerCleanup = () => Services.wm.removeListener(listener);
+}
diff --git a/toolkit/components/pdfjs/test/browser_pdfjs_form.js b/toolkit/components/pdfjs/test/browser_pdfjs_form.js
new file mode 100644
index 0000000000..f424a1ebdb
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser_pdfjs_form.js
@@ -0,0 +1,85 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const RELATIVE_DIR = "toolkit/components/pdfjs/test/";
+const TESTROOT = "http://example.com/browser/" + RELATIVE_DIR;
+
+async function checkFormState(formsEnabled) {
+ ok(
+ content.document.querySelector("div#viewer"),
+ "document content has viewer UI"
+ );
+
+ let formInput = content.document.querySelector("#viewerContainer input");
+
+ if (formsEnabled) {
+ ok(formInput, "Form input available");
+ } else {
+ ok(!formInput, "Form input not available");
+ }
+ let viewer = content.wrappedJSObject.PDFViewerApplication;
+ await viewer.close();
+}
+
+add_task(async function test_defaults() {
+ // Ensure the default preference is set to the expected value.
+ let defaultBranch = Services.prefs.getDefaultBranch("pdfjs.");
+ let prefType = defaultBranch.getPrefType("renderInteractiveForms");
+ let renderForms = Services.prefs.getBoolPref("pdfjs.renderInteractiveForms");
+
+ is(
+ prefType,
+ Ci.nsIPrefBranch.PREF_BOOL,
+ "The form pref is defined by default"
+ );
+
+ ok(renderForms, "Forms are enabled");
+
+ // Test that the forms state matches the pref.
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async function(browser) {
+ await waitForPdfJSAnnotationLayer(
+ browser,
+ TESTROOT + "file_pdfjs_form.pdf"
+ );
+
+ await SpecialPowers.spawn(browser, [true], checkFormState);
+ }
+ );
+});
+
+// Test disabling forms with pref.
+add_task(async function test_disabling() {
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async function(browser) {
+ // First, make sure they are enabled.
+ await SpecialPowers.pushPrefEnv({
+ set: [["pdfjs.renderInteractiveForms", true]],
+ });
+ await waitForPdfJSAnnotationLayer(
+ browser,
+ TESTROOT + "file_pdfjs_form.pdf"
+ );
+ await SpecialPowers.spawn(
+ browser,
+ [true /* formsEnabled */],
+ checkFormState
+ );
+ // Now disable the forms.
+ await SpecialPowers.pushPrefEnv({
+ set: [["pdfjs.renderInteractiveForms", false]],
+ });
+ await waitForPdfJSAnnotationLayer(
+ browser,
+ TESTROOT + "file_pdfjs_form.pdf"
+ );
+ await SpecialPowers.spawn(
+ browser,
+ [false /* formsEnabled */],
+ checkFormState
+ );
+ }
+ );
+});
diff --git a/toolkit/components/pdfjs/test/browser_pdfjs_main.js b/toolkit/components/pdfjs/test/browser_pdfjs_main.js
new file mode 100644
index 0000000000..dda1615c0b
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser_pdfjs_main.js
@@ -0,0 +1,72 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const RELATIVE_DIR = "toolkit/components/pdfjs/test/";
+const TESTROOT = "http://example.com/browser/" + RELATIVE_DIR;
+
+add_task(async function test() {
+ 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"
+ );
+
+ info("Pref action: " + handlerInfo.preferredAction);
+
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async function(newTabBrowser) {
+ await waitForPdfJS(newTabBrowser, TESTROOT + "file_pdfjs_test.pdf");
+
+ await SpecialPowers.spawn(newTabBrowser, [], async function() {
+ // Overall sanity tests
+ Assert.ok(
+ content.document.querySelector("div#viewer"),
+ "document content has viewer UI"
+ );
+
+ // Sidebar: open
+ var sidebar = content.document.querySelector("button#sidebarToggle"),
+ outerContainer = content.document.querySelector("div#outerContainer");
+
+ sidebar.click();
+ Assert.ok(
+ outerContainer.classList.contains("sidebarOpen"),
+ "sidebar opens on click"
+ );
+
+ // Sidebar: close
+ sidebar.click();
+ Assert.ok(
+ !outerContainer.classList.contains("sidebarOpen"),
+ "sidebar closes on click"
+ );
+
+ // Verify that initial page is 1
+ var pgNumber = content.document.querySelector("input#pageNumber").value;
+ Assert.equal(parseInt(pgNumber, 10), 1, "initial page is 1");
+
+ // Bookmark button
+ var viewBookmark = content.document.querySelector("a#viewBookmark");
+ viewBookmark.click();
+
+ Assert.ok(!!viewBookmark.href.length, "viewBookmark button has href");
+
+ var viewer = content.wrappedJSObject.PDFViewerApplication;
+ await viewer.close();
+ });
+ }
+ );
+});
diff --git a/toolkit/components/pdfjs/test/browser_pdfjs_navigation.js b/toolkit/components/pdfjs/test/browser_pdfjs_navigation.js
new file mode 100644
index 0000000000..7e106e745e
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser_pdfjs_navigation.js
@@ -0,0 +1,320 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+/* eslint-disable mozilla/no-arbitrary-setTimeout */
+
+requestLongerTimeout(2);
+
+const RELATIVE_DIR = "toolkit/components/pdfjs/test/";
+const TESTROOT = "http://example.com/browser/" + RELATIVE_DIR;
+
+const PDF_OUTLINE_ITEMS = 17;
+const TESTS = [
+ {
+ action: {
+ selector: "button#next",
+ event: "click",
+ },
+ expectedPage: 2,
+ message: "navigated to next page using NEXT button",
+ },
+ {
+ action: {
+ selector: "button#previous",
+ event: "click",
+ },
+ expectedPage: 1,
+ message: "navigated to previous page using PREV button",
+ },
+ {
+ action: {
+ selector: "button#next",
+ event: "click",
+ },
+ expectedPage: 2,
+ message: "navigated to next page using NEXT button",
+ },
+ {
+ action: {
+ selector: "input#pageNumber",
+ value: 1,
+ event: "change",
+ },
+ expectedPage: 1,
+ message: "navigated to first page using pagenumber",
+ },
+ {
+ action: {
+ selector: "#thumbnailView a:nth-child(4)",
+ event: "click",
+ },
+ expectedPage: 4,
+ message: "navigated to 4th page using thumbnail view",
+ },
+ {
+ action: {
+ selector: "#thumbnailView a:nth-child(2)",
+ event: "click",
+ },
+ expectedPage: 2,
+ message: "navigated to 2nd page using thumbnail view",
+ },
+ {
+ action: {
+ selector: "#viewer",
+ event: "keydown",
+ keyCode: 36,
+ },
+ expectedPage: 1,
+ message: "navigated to 1st page using 'home' key",
+ },
+ {
+ action: {
+ selector: "#viewer",
+ event: "keydown",
+ keyCode: 34,
+ },
+ expectedPage: 2,
+ message: "navigated to 2nd page using 'Page Down' key",
+ },
+ {
+ action: {
+ selector: "#viewer",
+ event: "keydown",
+ keyCode: 33,
+ },
+ expectedPage: 1,
+ message: "navigated to 1st page using 'Page Up' key",
+ },
+ {
+ action: {
+ selector: "#viewer",
+ event: "keydown",
+ keyCode: 39,
+ },
+ expectedPage: 2,
+ message: "navigated to 2nd page using 'right' key",
+ },
+ {
+ action: {
+ selector: "#viewer",
+ event: "keydown",
+ keyCode: 37,
+ },
+ expectedPage: 1,
+ message: "navigated to 1st page using 'left' key",
+ },
+ {
+ action: {
+ selector: "#viewer",
+ event: "keydown",
+ keyCode: 35,
+ },
+ expectedPage: 5,
+ message: "navigated to last page using 'home' key",
+ },
+ {
+ action: {
+ selector: "#outlineView .treeItem:nth-child(1) a",
+ event: "click",
+ },
+ expectedPage: 1,
+ message: "navigated to 1st page using outline view",
+ },
+ {
+ action: {
+ selector: "#outlineView .treeItem:nth-child(" + PDF_OUTLINE_ITEMS + ") a",
+ event: "click",
+ },
+ expectedPage: 4,
+ message: "navigated to 4th page using outline view",
+ },
+ {
+ action: {
+ selector: "input#pageNumber",
+ value: 5,
+ event: "change",
+ },
+ expectedPage: 5,
+ message: "navigated to 5th page using pagenumber",
+ },
+];
+
+add_task(async function test() {
+ 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"
+ );
+
+ info("Pref action: " + handlerInfo.preferredAction);
+
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async function(newTabBrowser) {
+ await waitForPdfJS(newTabBrowser, TESTROOT + "file_pdfjs_test.pdf");
+
+ await SpecialPowers.spawn(newTabBrowser, [], async function() {
+ // Check if PDF is opened with internal viewer
+ Assert.ok(
+ content.document.querySelector("div#viewer"),
+ "document content has viewer UI"
+ );
+ });
+
+ await SpecialPowers.spawn(newTabBrowser, [], contentSetUp);
+
+ await runTests(newTabBrowser);
+
+ await SpecialPowers.spawn(newTabBrowser, [], async function() {
+ let pageNumber = content.document.querySelector("input#pageNumber");
+ Assert.equal(
+ pageNumber.value,
+ pageNumber.max,
+ "Document is left on the last page"
+ );
+ });
+ }
+ );
+});
+
+async function contentSetUp() {
+ /**
+ * Outline Items gets appended to the document later on we have to
+ * wait for them before we start to navigate though document
+ *
+ * @param document
+ * @returns {deferred.promise|*}
+ */
+ function waitForOutlineItems(document) {
+ return new Promise((resolve, reject) => {
+ document.addEventListener(
+ "outlineloaded",
+ function(evt) {
+ var outlineCount = evt.detail.outlineCount;
+
+ if (
+ document.querySelectorAll("#outlineView .treeItem").length ===
+ outlineCount
+ ) {
+ resolve();
+ } else {
+ reject("Unable to find outline items.");
+ }
+ },
+ { once: true }
+ );
+ });
+ }
+
+ /**
+ * The key navigation has to happen in page-fit, otherwise it won't scroll
+ * through a complete page
+ *
+ * @param document
+ * @returns {deferred.promise|*}
+ */
+ function setZoomToPageFit(document) {
+ return new Promise(resolve => {
+ document.addEventListener(
+ "pagerendered",
+ function(e) {
+ document.querySelector("#viewer").click();
+ resolve();
+ },
+ { once: true }
+ );
+
+ var select = document.querySelector("select#scaleSelect");
+ select.selectedIndex = 2;
+ select.dispatchEvent(new content.Event("change"));
+ });
+ }
+
+ await waitForOutlineItems(content.document);
+ await setZoomToPageFit(content.document);
+}
+
+/**
+ * As the page changes asynchronously, we have to wait for the event after
+ * we trigger the action so we will be at the expected page number after each action
+ *
+ * @param document
+ * @param window
+ * @param test
+ * @param callback
+ */
+async function runTests(browser) {
+ await SpecialPowers.spawn(browser, [TESTS], async function(contentTESTS) {
+ let window = content;
+ let document = window.document;
+
+ for (let test of contentTESTS) {
+ let deferred = {};
+ deferred.promise = new Promise((resolve, reject) => {
+ deferred.resolve = resolve;
+ deferred.reject = reject;
+ });
+
+ let pageNumber = document.querySelector("input#pageNumber");
+
+ // Add an event-listener to wait for page to change, afterwards resolve the promise
+ let timeout = window.setTimeout(() => deferred.reject(), 5000);
+ window.addEventListener("pagechanging", function pageChange() {
+ if (pageNumber.value == test.expectedPage) {
+ window.removeEventListener("pagechanging", pageChange);
+ window.clearTimeout(timeout);
+ deferred.resolve(+pageNumber.value);
+ }
+ });
+
+ // Get the element and trigger the action for changing the page
+ var el = document.querySelector(test.action.selector);
+ Assert.ok(el, "Element '" + test.action.selector + "' has been found");
+
+ // The value option is for input case
+ if (test.action.value) {
+ el.value = test.action.value;
+ }
+
+ // Dispatch the event for changing the page
+ var ev;
+ if (test.action.event == "keydown") {
+ ev = document.createEvent("KeyboardEvent");
+ ev.initKeyEvent(
+ "keydown",
+ true,
+ true,
+ null,
+ false,
+ false,
+ false,
+ false,
+ test.action.keyCode,
+ 0
+ );
+ el.dispatchEvent(ev);
+ } else {
+ ev = new content.Event(test.action.event);
+ }
+ el.dispatchEvent(ev);
+
+ let pgNumber = await deferred.promise;
+ Assert.equal(pgNumber, test.expectedPage, test.message);
+ }
+
+ var viewer = content.wrappedJSObject.PDFViewerApplication;
+ await viewer.close();
+ });
+}
diff --git a/toolkit/components/pdfjs/test/browser_pdfjs_not_default.js b/toolkit/components/pdfjs/test/browser_pdfjs_not_default.js
new file mode 100644
index 0000000000..ea05348bc9
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser_pdfjs_not_default.js
@@ -0,0 +1,26 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+add_task(async function test_pdfjs_not_default() {
+ var oldAction = changeMimeHandler(Ci.nsIHandlerInfo.useSystemDefault, true);
+ let dirFileObj = getChromeDir(getResolvedURI(gTestPath));
+ dirFileObj.append("file_pdfjs_test.pdf");
+
+ let tab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ dirFileObj.path
+ );
+
+ // If we don't have the Pdfjs actor loaded, this will throw
+ await getPdfjsActor();
+
+ changeMimeHandler(oldAction[0], oldAction[1]);
+
+ gBrowser.removeTab(tab);
+});
+
+function getPdfjsActor() {
+ let win = Services.wm.getMostRecentWindow("navigator:browser");
+ let selectedBrowser = win.gBrowser.selectedBrowser;
+ return selectedBrowser.browsingContext.currentWindowGlobal.getActor("Pdfjs");
+}
diff --git a/toolkit/components/pdfjs/test/browser_pdfjs_notification_close_on_navigation.js b/toolkit/components/pdfjs/test/browser_pdfjs_notification_close_on_navigation.js
new file mode 100644
index 0000000000..a6d4cf0a45
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser_pdfjs_notification_close_on_navigation.js
@@ -0,0 +1,43 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const RELATIVE_DIR = "toolkit/components/pdfjs/test/";
+const TESTROOT = "http://example.com/browser/" + RELATIVE_DIR;
+
+add_task(async function test_notification_is_removed_upon_navigation() {
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async function(browser) {
+ await waitForPdfJSAnnotationLayer(
+ browser,
+ TESTROOT + "file_pdfjs_form.pdf"
+ );
+
+ // Trigger the PDFjs fallback notification bar
+ await ContentTask.spawn(browser, null, async () => {
+ content.wrappedJSObject.PDFViewerApplication.fallback();
+ });
+
+ let notification = await TestUtils.waitForCondition(
+ () =>
+ browser &&
+ gBrowser.getNotificationBox(browser) &&
+ gBrowser.getNotificationBox(browser).currentNotification,
+ "waiting for notification"
+ );
+ ok(notification, "A notification should be shown");
+ is(
+ notification.getAttribute("value"),
+ "pdfjs-fallback",
+ "Notification should be pdfjs-fallback"
+ );
+
+ BrowserTestUtils.loadURI(browser, "https://example.com");
+
+ await TestUtils.waitForCondition(
+ () => !notification.parentNode,
+ "notification should be removed upon navigation to example.com"
+ );
+ }
+ );
+});
diff --git a/toolkit/components/pdfjs/test/browser_pdfjs_octet_stream.js b/toolkit/components/pdfjs/test/browser_pdfjs_octet_stream.js
new file mode 100644
index 0000000000..bb6a228532
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser_pdfjs_octet_stream.js
@@ -0,0 +1,81 @@
+/* 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/"
+);
+
+// Get a ref to the pdf we want to open.
+const PDF_URL = TESTROOT + "file_pdfjs_object_stream.pdf";
+
+var gMIMEService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
+
+/**
+ * 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]] });
+ let handlerInfo = gMIMEService.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, PDF_URL);
+ is(newTabBrowser.currentURI.spec, PDF_URL, "Should load pdfjs");
+ }
+ );
+});
+
+/**
+ * Check that if the octet-stream thing is in a frame, we don't load it inside
+ * PDF.js
+ */
+add_task(async function test_octet_stream_in_frame_downloads() {
+ await SpecialPowers.pushPrefEnv({ set: [["pdfjs.handleOctetStream", true]] });
+
+ let handlerInfo = gMIMEService.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"
+ );
+
+ let dialogPromise = BrowserTestUtils.domWindowOpenedAndLoaded();
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: `data:text/html,<iframe src='${PDF_URL}'>` },
+ async function(newTabBrowser) {
+ let dialogWin = await dialogPromise;
+ ok(dialogWin, "Should have a dialog asking what to do.");
+ dialogWin.close(); // This is going to cancel the dialog.
+ }
+ );
+});
diff --git a/toolkit/components/pdfjs/test/browser_pdfjs_saveas.js b/toolkit/components/pdfjs/test/browser_pdfjs_saveas.js
new file mode 100644
index 0000000000..03ee7012b9
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser_pdfjs_saveas.js
@@ -0,0 +1,135 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const RELATIVE_DIR = "toolkit/components/pdfjs/test/";
+const TESTROOT = "http://example.com/browser/" + RELATIVE_DIR;
+
+var MockFilePicker = SpecialPowers.MockFilePicker;
+MockFilePicker.init(window);
+
+/* import-globals-from ../../../content/tests/browser/common/mockTransfer.js */
+Services.scriptloader.loadSubScript(
+ "chrome://mochitests/content/browser/toolkit/content/tests/browser/common/mockTransfer.js",
+ this
+);
+
+function createTemporarySaveDirectory() {
+ var saveDir = Services.dirsvc.get("TmpD", Ci.nsIFile);
+ saveDir.append("testsavedir");
+ if (!saveDir.exists()) {
+ saveDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755);
+ }
+ return saveDir;
+}
+
+function createPromiseForTransferComplete(expectedFileName, destFile) {
+ return new Promise(resolve => {
+ MockFilePicker.showCallback = fp => {
+ info("Filepicker shown, checking filename");
+ is(fp.defaultString, expectedFileName, "Filename should be correct.");
+ let fileName = fp.defaultString;
+ destFile.append(fileName);
+
+ MockFilePicker.setFiles([destFile]);
+ MockFilePicker.filterIndex = 0; // kSaveAsType_Complete
+
+ MockFilePicker.showCallback = null;
+ mockTransferCallback = function(downloadSuccess) {
+ ok(downloadSuccess, "File should have been downloaded successfully");
+ mockTransferCallback = () => {};
+ resolve();
+ };
+ };
+ });
+}
+
+let tempDir = createTemporarySaveDirectory();
+
+add_task(async function setup() {
+ mockTransferRegisterer.register();
+ registerCleanupFunction(function() {
+ mockTransferRegisterer.unregister();
+ MockFilePicker.cleanup();
+ tempDir.remove(true);
+ });
+});
+
+/**
+ * Check triggering "Save Page As" on a non-forms PDF opens the "Save As" dialog
+ * and successfully saves the file.
+ */
+add_task(async function test_pdf_saveas() {
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async function(browser) {
+ await waitForPdfJS(browser, TESTROOT + "file_pdfjs_test.pdf");
+ let destFile = tempDir.clone();
+ MockFilePicker.displayDirectory = tempDir;
+ let fileSavedPromise = createPromiseForTransferComplete(
+ "file_pdfjs_test.pdf",
+ destFile
+ );
+ saveBrowser(browser);
+ await fileSavedPromise;
+ }
+ );
+});
+
+/**
+ * Check triggering "Save Page As" on a PDF with forms that has been modified
+ * does the following:
+ * 1) opens the "Save As" dialog
+ * 2) successfully saves the file
+ * 3) the new file contains the new form data
+ */
+add_task(async function test_pdf_saveas_forms() {
+ await SpecialPowers.pushPrefEnv({
+ set: [["pdfjs.renderInteractiveForms", true]],
+ });
+ let destFile = tempDir.clone();
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async function(browser) {
+ await waitForPdfJSAnnotationLayer(
+ browser,
+ TESTROOT + "file_pdfjs_form.pdf"
+ );
+ // Fill in the form input field.
+ await SpecialPowers.spawn(browser, [], async function() {
+ let formInput = content.document.querySelector(
+ "#viewerContainer input"
+ );
+ ok(formInput, "PDF contains text field.");
+ is(formInput.value, "", "Text field is empty to start.");
+ formInput.value = "test";
+ formInput.dispatchEvent(new content.window.Event("input"));
+ });
+
+ MockFilePicker.displayDirectory = tempDir;
+ let fileSavedPromise = createPromiseForTransferComplete(
+ "file_pdfjs_form.pdf",
+ destFile
+ );
+ saveBrowser(browser);
+ await fileSavedPromise;
+ }
+ );
+
+ // Now that the file has been modified and saved, load it to verify the form
+ // data persisted.
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async function(browser) {
+ await waitForPdfJSAnnotationLayer(browser, NetUtil.newURI(destFile).spec);
+ await SpecialPowers.spawn(browser, [], async function() {
+ let formInput = content.document.querySelector(
+ "#viewerContainer input"
+ );
+ ok(formInput, "PDF contains text field.");
+ is(formInput.value, "test", "Text field is filled in.");
+ });
+ }
+ );
+});
diff --git a/toolkit/components/pdfjs/test/browser_pdfjs_savedialog.js b/toolkit/components/pdfjs/test/browser_pdfjs_savedialog.js
new file mode 100644
index 0000000000..c59985a5cf
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser_pdfjs_savedialog.js
@@ -0,0 +1,43 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const RELATIVE_DIR = "toolkit/components/pdfjs/test/";
+const TESTROOT = "http://example.com/browser/" + RELATIVE_DIR;
+
+function test() {
+ var oldAction = changeMimeHandler(Ci.nsIHandlerInfo.useSystemDefault, true);
+ var tab = BrowserTestUtils.addTab(gBrowser, TESTROOT + "file_pdfjs_test.pdf");
+ // Test: "Open with" dialog comes up when pdf.js is not selected as the default
+ // handler.
+ addWindowListener(
+ "chrome://mozapps/content/downloads/unknownContentType.xhtml",
+ finish
+ );
+
+ waitForExplicitFinish();
+ registerCleanupFunction(function() {
+ changeMimeHandler(oldAction[0], oldAction[1]);
+ gBrowser.removeTab(tab);
+ });
+}
+
+function addWindowListener(aURL, aCallback) {
+ Services.wm.addListener({
+ onOpenWindow(aXULWindow) {
+ info("window opened, waiting for focus");
+ Services.wm.removeListener(this);
+
+ var domwindow = aXULWindow.docShell.domWindow;
+ waitForFocus(function() {
+ is(
+ domwindow.document.location.href,
+ aURL,
+ "should have seen the right window open"
+ );
+ domwindow.close();
+ aCallback();
+ }, domwindow);
+ },
+ onCloseWindow(aXULWindow) {},
+ });
+}
diff --git a/toolkit/components/pdfjs/test/browser_pdfjs_views.js b/toolkit/components/pdfjs/test/browser_pdfjs_views.js
new file mode 100644
index 0000000000..f2d95c02a6
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser_pdfjs_views.js
@@ -0,0 +1,108 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const RELATIVE_DIR = "toolkit/components/pdfjs/test/";
+const TESTROOT = "http://example.com/browser/" + RELATIVE_DIR;
+
+add_task(async function test() {
+ 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"
+ );
+
+ info("Pref action: " + handlerInfo.preferredAction);
+
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async function(browser) {
+ // check that PDF is opened with internal viewer
+ await waitForPdfJS(browser, TESTROOT + "file_pdfjs_test.pdf");
+
+ await SpecialPowers.spawn(browser, [], async function() {
+ Assert.ok(
+ content.document.querySelector("div#viewer"),
+ "document content has viewer UI"
+ );
+
+ // open sidebar
+ var sidebar = content.document.querySelector("button#sidebarToggle");
+ var outerContainer = content.document.querySelector(
+ "div#outerContainer"
+ );
+
+ sidebar.click();
+ Assert.ok(
+ outerContainer.classList.contains("sidebarOpen"),
+ "sidebar opens on click"
+ );
+
+ // check that thumbnail view is open
+ var thumbnailView = content.document.querySelector("div#thumbnailView");
+ var outlineView = content.document.querySelector("div#outlineView");
+
+ Assert.equal(
+ thumbnailView.getAttribute("class"),
+ null,
+ "Initial view is thumbnail view"
+ );
+ Assert.equal(
+ outlineView.getAttribute("class"),
+ "hidden",
+ "Outline view is hidden initially"
+ );
+
+ // switch to outline view
+ var viewOutlineButton = content.document.querySelector(
+ "button#viewOutline"
+ );
+ viewOutlineButton.click();
+
+ Assert.equal(
+ thumbnailView.getAttribute("class"),
+ "hidden",
+ "Thumbnail view is hidden when outline is selected"
+ );
+ Assert.equal(
+ outlineView.getAttribute("class"),
+ "",
+ "Outline view is visible when selected"
+ );
+
+ // switch back to thumbnail view
+ var viewThumbnailButton = content.document.querySelector(
+ "button#viewThumbnail"
+ );
+ viewThumbnailButton.click();
+
+ Assert.equal(
+ thumbnailView.getAttribute("class"),
+ "",
+ "Thumbnail view is visible when selected"
+ );
+ Assert.equal(
+ outlineView.getAttribute("class"),
+ "hidden",
+ "Outline view is hidden when thumbnail is selected"
+ );
+
+ sidebar.click();
+
+ var viewer = content.wrappedJSObject.PDFViewerApplication;
+ await viewer.close();
+ });
+ }
+ );
+});
diff --git a/toolkit/components/pdfjs/test/browser_pdfjs_zoom.js b/toolkit/components/pdfjs/test/browser_pdfjs_zoom.js
new file mode 100644
index 0000000000..0d55c30fb8
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser_pdfjs_zoom.js
@@ -0,0 +1,272 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+requestLongerTimeout(2);
+
+const RELATIVE_DIR = "toolkit/components/pdfjs/test/";
+const TESTROOT = "http://example.com/browser/" + RELATIVE_DIR;
+
+const TESTS = [
+ {
+ action: {
+ selector: "button#zoomIn",
+ event: "click",
+ },
+ expectedZoom: 1, // 1 - zoom in
+ message: "Zoomed in using the '+' (zoom in) button",
+ },
+
+ {
+ action: {
+ selector: "button#zoomOut",
+ event: "click",
+ },
+ expectedZoom: -1, // -1 - zoom out
+ message: "Zoomed out using the '-' (zoom out) button",
+ },
+
+ {
+ action: {
+ keyboard: true,
+ keyCode: 61,
+ event: "+",
+ },
+ expectedZoom: 1, // 1 - zoom in
+ message: "Zoomed in using the CTRL++ keys",
+ },
+
+ {
+ action: {
+ keyboard: true,
+ keyCode: 109,
+ event: "-",
+ },
+ expectedZoom: -1, // -1 - zoom out
+ message: "Zoomed out using the CTRL+- keys",
+ },
+
+ {
+ action: {
+ selector: "select#scaleSelect",
+ index: 5,
+ event: "change",
+ },
+ expectedZoom: -1, // -1 - zoom out
+ message: "Zoomed using the zoom picker",
+ },
+];
+
+add_task(async function test() {
+ 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"
+ );
+
+ info("Pref action: " + handlerInfo.preferredAction);
+
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async function(newTabBrowser) {
+ await waitForPdfJS(
+ newTabBrowser,
+ TESTROOT + "file_pdfjs_test.pdf#zoom=100"
+ );
+
+ await SpecialPowers.spawn(newTabBrowser, [TESTS], async function(
+ contentTESTS
+ ) {
+ let document = content.document;
+
+ function waitForRender() {
+ return new Promise(resolve => {
+ document.addEventListener(
+ "pagerendered",
+ function onPageRendered(e) {
+ if (e.detail.pageNumber !== 1) {
+ return;
+ }
+
+ document.removeEventListener(
+ "pagerendered",
+ onPageRendered,
+ true
+ );
+ resolve();
+ },
+ true
+ );
+ });
+ }
+
+ // check that PDF is opened with internal viewer
+ Assert.ok(
+ content.document.querySelector("div#viewer"),
+ "document content has viewer UI"
+ );
+
+ let initialWidth, previousWidth;
+ initialWidth = previousWidth = parseInt(
+ content.document.querySelector("div.page[data-page-number='1']").style
+ .width
+ );
+
+ for (let subTest of contentTESTS) {
+ // We zoom using an UI element
+ var ev;
+ if (subTest.action.selector) {
+ // Get the element and trigger the action for changing the zoom
+ var el = document.querySelector(subTest.action.selector);
+ Assert.ok(
+ el,
+ "Element '" + subTest.action.selector + "' has been found"
+ );
+
+ if (subTest.action.index) {
+ el.selectedIndex = subTest.action.index;
+ }
+
+ // Dispatch the event for changing the zoom
+ ev = new content.Event(subTest.action.event);
+ } else {
+ // We zoom using keyboard
+ // Simulate key press
+ ev = new content.KeyboardEvent("keydown", {
+ key: subTest.action.event,
+ keyCode: subTest.action.keyCode,
+ ctrlKey: true,
+ });
+ el = content;
+ }
+
+ el.dispatchEvent(ev);
+ await waitForRender();
+
+ var pageZoomScale = content.document.querySelector(
+ "select#scaleSelect"
+ );
+
+ // The zoom value displayed in the zoom select
+ var zoomValue =
+ pageZoomScale.options[pageZoomScale.selectedIndex].innerHTML;
+
+ let pageContainer = content.document.querySelector(
+ "div.page[data-page-number='1']"
+ );
+ let actualWidth = parseInt(pageContainer.style.width);
+
+ // the actual zoom of the PDF document
+ let computedZoomValue =
+ parseInt((actualWidth / initialWidth).toFixed(2) * 100) + "%";
+ Assert.equal(
+ computedZoomValue,
+ zoomValue,
+ "Content has correct zoom"
+ );
+
+ // Check that document zooms in the expected way (in/out)
+ let zoom = (actualWidth - previousWidth) * subTest.expectedZoom;
+ Assert.ok(zoom > 0, subTest.message);
+
+ previousWidth = actualWidth;
+ }
+
+ var viewer = content.wrappedJSObject.PDFViewerApplication;
+ await viewer.close();
+ });
+ }
+ );
+});
+
+// Performs a SpecialPowers.spawn round-trip to ensure that any setup
+// that needs to be done in the content process by any pending tasks has
+// a chance to complete before continuing.
+function waitForRoundTrip(browser) {
+ return SpecialPowers.spawn(browser, [], () => {});
+}
+
+async function waitForRenderAndGetWidth(newTabBrowser) {
+ return SpecialPowers.spawn(newTabBrowser, [], async function() {
+ function waitForRender(document) {
+ return new Promise(resolve => {
+ document.addEventListener(
+ "pagerendered",
+ function onPageRendered(e) {
+ if (e.detail.pageNumber !== 1) {
+ return;
+ }
+
+ document.removeEventListener("pagerendered", onPageRendered, true);
+ resolve();
+ },
+ true
+ );
+ });
+ }
+ // check that PDF is opened with internal viewer
+ Assert.ok(
+ content.document.querySelector("div#viewer"),
+ "document content has viewer UI"
+ );
+
+ await waitForRender(content.document);
+
+ return parseInt(
+ content.document.querySelector("div.page[data-page-number='1']").style
+ .width
+ );
+ });
+}
+
+add_task(async function test_browser_zoom() {
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async function(newTabBrowser) {
+ await waitForPdfJS(newTabBrowser, TESTROOT + "file_pdfjs_test.pdf");
+
+ const initialWidth = await waitForRenderAndGetWidth(newTabBrowser);
+
+ // Zoom in
+ let newWidthPromise = waitForRenderAndGetWidth(newTabBrowser);
+ await waitForRoundTrip(newTabBrowser);
+ FullZoom.enlarge();
+ ok(
+ (await newWidthPromise) > initialWidth,
+ "Zoom in makes the page bigger."
+ );
+
+ // Reset
+ newWidthPromise = waitForRenderAndGetWidth(newTabBrowser);
+ await waitForRoundTrip(newTabBrowser);
+ FullZoom.reset();
+ is(await newWidthPromise, initialWidth, "Zoom reset restores page.");
+
+ // Zoom out
+ newWidthPromise = waitForRenderAndGetWidth(newTabBrowser);
+ await waitForRoundTrip(newTabBrowser);
+ FullZoom.reduce();
+ ok(
+ (await newWidthPromise) < initialWidth,
+ "Zoom out makes the page smaller."
+ );
+
+ // Clean-up after the PDF viewer.
+ await SpecialPowers.spawn(newTabBrowser, [], function() {
+ const viewer = content.wrappedJSObject.PDFViewerApplication;
+ return viewer.close();
+ });
+ }
+ );
+});
diff --git a/toolkit/components/pdfjs/test/file_pdfjs_form.pdf b/toolkit/components/pdfjs/test/file_pdfjs_form.pdf
new file mode 100644
index 0000000000..c6eff988a6
--- /dev/null
+++ b/toolkit/components/pdfjs/test/file_pdfjs_form.pdf
Binary files differ
diff --git a/toolkit/components/pdfjs/test/file_pdfjs_object_stream.pdf b/toolkit/components/pdfjs/test/file_pdfjs_object_stream.pdf
new file mode 100644
index 0000000000..89066463f1
--- /dev/null
+++ b/toolkit/components/pdfjs/test/file_pdfjs_object_stream.pdf
Binary files differ
diff --git a/toolkit/components/pdfjs/test/file_pdfjs_object_stream.pdf^headers^ b/toolkit/components/pdfjs/test/file_pdfjs_object_stream.pdf^headers^
new file mode 100644
index 0000000000..ff8fb3126e
--- /dev/null
+++ b/toolkit/components/pdfjs/test/file_pdfjs_object_stream.pdf^headers^
@@ -0,0 +1,2 @@
+Content-Type: application/octet-stream
+
diff --git a/toolkit/components/pdfjs/test/file_pdfjs_test.pdf b/toolkit/components/pdfjs/test/file_pdfjs_test.pdf
new file mode 100644
index 0000000000..7ad87e3c2e
--- /dev/null
+++ b/toolkit/components/pdfjs/test/file_pdfjs_test.pdf
Binary files differ
diff --git a/toolkit/components/pdfjs/test/head.js b/toolkit/components/pdfjs/test/head.js
new file mode 100644
index 0000000000..bca608e1f0
--- /dev/null
+++ b/toolkit/components/pdfjs/test/head.js
@@ -0,0 +1,71 @@
+async function waitForPdfJS(browser, url) {
+ await SpecialPowers.pushPrefEnv({
+ set: [["pdfjs.eventBusDispatchToDOM", true]],
+ });
+ // Runs tests after all "load" event handlers have fired off
+ let loadPromise = BrowserTestUtils.waitForContentEvent(
+ browser,
+ "documentloaded",
+ false,
+ null,
+ true
+ );
+ await SpecialPowers.spawn(browser, [url], contentUrl => {
+ content.location = contentUrl;
+ });
+ return loadPromise;
+}
+
+async function waitForPdfJSAnnotationLayer(browser, url) {
+ await SpecialPowers.pushPrefEnv({
+ set: [["pdfjs.eventBusDispatchToDOM", true]],
+ });
+ let loadPromise = BrowserTestUtils.waitForContentEvent(
+ browser,
+ "annotationlayerrendered",
+ false,
+ null,
+ true
+ );
+ await SpecialPowers.spawn(browser, [url], contentUrl => {
+ content.location = contentUrl;
+ });
+ return loadPromise;
+}
+
+function changeMimeHandler(preferredAction, alwaysAskBeforeHandling) {
+ let handlerService = Cc[
+ "@mozilla.org/uriloader/handler-service;1"
+ ].getService(Ci.nsIHandlerService);
+ let mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
+ let handlerInfo = mimeService.getFromTypeAndExtension(
+ "application/pdf",
+ "pdf"
+ );
+ var oldAction = [
+ handlerInfo.preferredAction,
+ handlerInfo.alwaysAskBeforeHandling,
+ ];
+
+ // Change and save mime handler settings
+ handlerInfo.alwaysAskBeforeHandling = alwaysAskBeforeHandling;
+ handlerInfo.preferredAction = preferredAction;
+ handlerService.store(handlerInfo);
+
+ // Refresh data
+ handlerInfo = mimeService.getFromTypeAndExtension("application/pdf", "pdf");
+
+ // Test: Mime handler was updated
+ is(
+ handlerInfo.alwaysAskBeforeHandling,
+ alwaysAskBeforeHandling,
+ "always-ask prompt change successful"
+ );
+ is(
+ handlerInfo.preferredAction,
+ preferredAction,
+ "mime handler change successful"
+ );
+
+ return oldAction;
+}