diff --git a/extensions/chromium/preferences_schema.json b/extensions/chromium/preferences_schema.json index 7c00e57e6ba1d..476e1b368ba07 100644 --- a/extensions/chromium/preferences_schema.json +++ b/extensions/chromium/preferences_schema.json @@ -198,6 +198,10 @@ "description": "The color is a string as defined in CSS. Its goal is to help improve readability in high contrast mode", "type": "string", "default": "CanvasText" + }, + "hasInitializationHook": { + "type": "boolean", + "default": false } } } diff --git a/test/integration/copy_paste_spec.mjs b/test/integration/copy_paste_spec.mjs index dac86b8cf11dd..35f27a1bcda90 100644 --- a/test/integration/copy_paste_spec.mjs +++ b/test/integration/copy_paste_spec.mjs @@ -14,6 +14,7 @@ */ import { + awaitPromise, closePages, kbCopy, kbSelectAll, @@ -44,12 +45,7 @@ describe("Copy and paste", () => { "tracemonkey.pdf", "#hiddenCopyElement", 100, - async page => { - await page.waitForFunction( - () => !!window.PDFViewerApplication.eventBus - ); - await waitForTextLayer(page); - } + waitForTextLayer ); await mockClipboard(pages); }); @@ -60,7 +56,8 @@ describe("Copy and paste", () => { it("must check that we've all the contents on copy/paste", async () => { await Promise.all( - pages.map(async ([browserName, page]) => { + pages.map(async ([browserName, page, pageSetupPromise]) => { + awaitPromise(pageSetupPromise); await selectAll(page); const promise = waitForEvent(page, "copy"); @@ -151,12 +148,7 @@ describe("Copy and paste", () => { "copy_paste_ligatures.pdf", "#hiddenCopyElement", 100, - async page => { - await page.waitForFunction( - () => !!window.PDFViewerApplication.eventBus - ); - await waitForTextLayer(page); - } + waitForTextLayer ); await mockClipboard(pages); }); @@ -167,7 +159,8 @@ describe("Copy and paste", () => { it("must check that the ligatures have been removed when the text has been copied", async () => { await Promise.all( - pages.map(async ([browserName, page]) => { + pages.map(async ([browserName, page, pageSetupPromise]) => { + awaitPromise(pageSetupPromise); await selectAll(page); const promise = waitForEvent(page, "copy"); diff --git a/test/integration/freetext_editor_spec.mjs b/test/integration/freetext_editor_spec.mjs index f3cff4cea8164..a09994233824a 100644 --- a/test/integration/freetext_editor_spec.mjs +++ b/test/integration/freetext_editor_spec.mjs @@ -2216,20 +2216,14 @@ describe("FreeText Editor", () => { "tracemonkey.pdf", ".annotationEditorLayer", 100, - async page => { - await page.waitForFunction(async () => { - await window.PDFViewerApplication.initializedPromise; - return true; - }); - await page.evaluate(() => { - window.visitedPages = []; - window.PDFViewerApplication.eventBus.on( - "pagechanging", - ({ pageNumber }) => { - window.visitedPages.push(pageNumber); - } - ); - }); + () => { + window.visitedPages = []; + window.PDFViewerApplication.eventBus.on( + "pagechanging", + ({ pageNumber }) => { + window.visitedPages.push(pageNumber); + } + ); } ); }); @@ -2469,19 +2463,13 @@ describe("FreeText Editor", () => { "tracemonkey.pdf", ".annotationEditorLayer", 100, - async page => { - await page.waitForFunction(async () => { - await window.PDFViewerApplication.initializedPromise; - return true; - }); - await page.evaluate(() => { - window.PDFViewerApplication.eventBus.on( - "annotationeditorstateschanged", - ({ details }) => { - window.editingEvents?.push(details); - } - ); - }); + () => { + window.PDFViewerApplication.eventBus.on( + "annotationeditorstateschanged", + ({ details }) => { + window.editingEvents?.push(details); + } + ); } ); }); diff --git a/test/integration/scripting_spec.mjs b/test/integration/scripting_spec.mjs index 5f29be1ef4547..b6bf98c10597f 100644 --- a/test/integration/scripting_spec.mjs +++ b/test/integration/scripting_spec.mjs @@ -1773,7 +1773,6 @@ describe("Interaction", () => { describe("in autoprint.pdf", () => { let pages; - const printHandles = new Map(); beforeAll(async () => { // Autoprinting is triggered by the `Open` event, which is one of the @@ -1788,29 +1787,9 @@ describe("Interaction", () => { "autoprint.pdf", "", null /* pageSetup = */, - async page => { - printHandles.set( - page, - await page.evaluateHandle(() => [ - new Promise(resolve => { - globalThis.printResolve = resolve; - }), - ]) - ); - await page.waitForFunction(() => { - if (!window.PDFViewerApplication?.eventBus) { - return false; - } - window.PDFViewerApplication.eventBus.on( - "print", - () => { - const resolve = globalThis.printResolve; - delete globalThis.printResolve; - resolve(); - }, - { once: true } - ); - return true; + resolve => { + window.PDFViewerApplication.eventBus.on("print", resolve, { + once: true, }); } ); @@ -1818,13 +1797,12 @@ describe("Interaction", () => { afterAll(async () => { await closePages(pages); - printHandles.clear(); }); it("must check if printing is triggered when the document is open", async () => { await Promise.all( - pages.map(async ([browserName, page]) => { - await awaitPromise(printHandles.get(page)); + pages.map(async ([browserName, page, pageSetupPromise]) => { + await awaitPromise(pageSetupPromise); }) ); }); diff --git a/test/integration/test_utils.mjs b/test/integration/test_utils.mjs index 037b547a1d7e5..9246117275a18 100644 --- a/test/integration/test_utils.mjs +++ b/test/integration/test_utils.mjs @@ -37,6 +37,10 @@ function loadAndWait(filename, selector, zoom, pageSetup, options) { }); let app_options = ""; + if (pageSetup) { + options ||= {}; + options.initializationhook = "true"; + } if (options) { // Options must be handled in app.js::_parseHashParams. for (const [key, value] of Object.entries(options)) { @@ -48,8 +52,25 @@ function loadAndWait(filename, selector, zoom, pageSetup, options) { }?file=/test/pdfs/${filename}#zoom=${zoom ?? "page-fit"}${app_options}`; await page.goto(url); + let pageSetupPromise = null; if (pageSetup) { - await pageSetup(page); + await page.waitForFunction( + () => !!window.PDFViewerApplication.eventBus + ); + pageSetupPromise = await page.evaluateHandle( + cb => [ + new Promise(resolve => { + window.PDFViewerApplication.eventBus.dispatch( + "initializationhook", + { + // eslint-disable-next-line no-eval + callback: () => eval(`(${cb})`)(resolve), + } + ); + }), + ], + pageSetup.toString() + ); } await page.bringToFront(); @@ -58,7 +79,7 @@ function loadAndWait(filename, selector, zoom, pageSetup, options) { timeout: 0, }); } - return [session.name, page]; + return [session.name, page, pageSetupPromise]; }) ); } @@ -298,20 +319,15 @@ async function dragAndDropAnnotation(page, startX, startY, tX, tY) { await page.waitForSelector("#viewer:not(.noUserSelect)"); } -function waitForAnnotationEditorLayer(page) { - return createPromise(page, resolve => { - window.PDFViewerApplication.eventBus.on( - "annotationeditorlayerrendered", - resolve - ); - }); +function waitForAnnotationEditorLayer(resolve) { + window.PDFViewerApplication.eventBus.on( + "annotationeditorlayerrendered", + resolve + ); } -async function waitForTextLayer(page) { - const handle = await createPromise(page, resolve => { - window.PDFViewerApplication.eventBus.on("textlayerrendered", resolve); - }); - return awaitPromise(handle); +function waitForTextLayer(resolve) { + window.PDFViewerApplication.eventBus.on("textlayerrendered", resolve); } async function scrollIntoView(page, selector) { diff --git a/web/app.js b/web/app.js index 49cf9a9f53faf..19b82fe28e810 100644 --- a/web/app.js +++ b/web/app.js @@ -237,6 +237,23 @@ const PDFViewerApplication = { this.bindEvents(); this.bindWindowEvents(); + if ( + typeof PDFJSDev !== "undefined" && + PDFJSDev.test("TESTING || MOZCENTRAL") && + AppOptions.get("hasInitializationHook") + ) { + await new Promise(resolve => { + this.eventBus.on( + "initializationhook", + ({ callback }) => { + callback(); + resolve(); + }, + { once: true } + ); + }); + } + this._initializedCapability.resolve(); }, @@ -329,6 +346,9 @@ const PDFViewerApplication = { params.get("highlighteditorcolors") ); } + if (params.get("initializationhook") === "true") { + AppOptions.set("hasInitializationHook", true); + } } }, diff --git a/web/app_options.js b/web/app_options.js index 80fdc9c24d647..61ad13862f93c 100644 --- a/web/app_options.js +++ b/web/app_options.js @@ -181,6 +181,11 @@ const defaultOptions = { value: 0, kind: OptionKind.VIEWER + OptionKind.PREFERENCE, }, + hasInitializationHook: { + /** @type {boolean} */ + value: false, + kind: OptionKind.VIEWER + OptionKind.PREFERENCE, + }, highlightEditorColors: { /** @type {string} */ value: "yellow=#FFFF98,green=#53FFBC,blue=#80EBFF,pink=#FFCBE6,red=#FF4F5F",