Allow to set up a hook at the end of the initialization (bug 1881319)

With this patch it's now possible to be sure to add a listener
(for example for the "pagerendered" event) before the pdf is set.
This commit is contained in:
Calixte Denizet 2024-02-15 16:01:12 +01:00
parent 72b8b29147
commit 662021d51b
7 changed files with 86 additions and 82 deletions

View File

@ -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", "description": "The color is a string as defined in CSS. Its goal is to help improve readability in high contrast mode",
"type": "string", "type": "string",
"default": "CanvasText" "default": "CanvasText"
},
"hasInitializationHook": {
"type": "boolean",
"default": false
} }
} }
} }

View File

@ -14,6 +14,7 @@
*/ */
import { import {
awaitPromise,
closePages, closePages,
kbCopy, kbCopy,
kbSelectAll, kbSelectAll,
@ -44,12 +45,7 @@ describe("Copy and paste", () => {
"tracemonkey.pdf", "tracemonkey.pdf",
"#hiddenCopyElement", "#hiddenCopyElement",
100, 100,
async page => { waitForTextLayer
await page.waitForFunction(
() => !!window.PDFViewerApplication.eventBus
);
await waitForTextLayer(page);
}
); );
await mockClipboard(pages); await mockClipboard(pages);
}); });
@ -60,7 +56,8 @@ describe("Copy and paste", () => {
it("must check that we've all the contents on copy/paste", async () => { it("must check that we've all the contents on copy/paste", async () => {
await Promise.all( await Promise.all(
pages.map(async ([browserName, page]) => { pages.map(async ([browserName, page, pageSetupPromise]) => {
awaitPromise(pageSetupPromise);
await selectAll(page); await selectAll(page);
const promise = waitForEvent(page, "copy"); const promise = waitForEvent(page, "copy");
@ -151,12 +148,7 @@ describe("Copy and paste", () => {
"copy_paste_ligatures.pdf", "copy_paste_ligatures.pdf",
"#hiddenCopyElement", "#hiddenCopyElement",
100, 100,
async page => { waitForTextLayer
await page.waitForFunction(
() => !!window.PDFViewerApplication.eventBus
);
await waitForTextLayer(page);
}
); );
await mockClipboard(pages); 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 () => { it("must check that the ligatures have been removed when the text has been copied", async () => {
await Promise.all( await Promise.all(
pages.map(async ([browserName, page]) => { pages.map(async ([browserName, page, pageSetupPromise]) => {
awaitPromise(pageSetupPromise);
await selectAll(page); await selectAll(page);
const promise = waitForEvent(page, "copy"); const promise = waitForEvent(page, "copy");

View File

@ -2216,20 +2216,14 @@ describe("FreeText Editor", () => {
"tracemonkey.pdf", "tracemonkey.pdf",
".annotationEditorLayer", ".annotationEditorLayer",
100, 100,
async page => { () => {
await page.waitForFunction(async () => { window.visitedPages = [];
await window.PDFViewerApplication.initializedPromise; window.PDFViewerApplication.eventBus.on(
return true; "pagechanging",
}); ({ pageNumber }) => {
await page.evaluate(() => { 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", "tracemonkey.pdf",
".annotationEditorLayer", ".annotationEditorLayer",
100, 100,
async page => { () => {
await page.waitForFunction(async () => { window.PDFViewerApplication.eventBus.on(
await window.PDFViewerApplication.initializedPromise; "annotationeditorstateschanged",
return true; ({ details }) => {
}); window.editingEvents?.push(details);
await page.evaluate(() => { }
window.PDFViewerApplication.eventBus.on( );
"annotationeditorstateschanged",
({ details }) => {
window.editingEvents?.push(details);
}
);
});
} }
); );
}); });

View File

@ -1773,7 +1773,6 @@ describe("Interaction", () => {
describe("in autoprint.pdf", () => { describe("in autoprint.pdf", () => {
let pages; let pages;
const printHandles = new Map();
beforeAll(async () => { beforeAll(async () => {
// Autoprinting is triggered by the `Open` event, which is one of the // Autoprinting is triggered by the `Open` event, which is one of the
@ -1788,29 +1787,9 @@ describe("Interaction", () => {
"autoprint.pdf", "autoprint.pdf",
"", "",
null /* pageSetup = */, null /* pageSetup = */,
async page => { resolve => {
printHandles.set( window.PDFViewerApplication.eventBus.on("print", resolve, {
page, once: true,
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;
}); });
} }
); );
@ -1818,13 +1797,12 @@ describe("Interaction", () => {
afterAll(async () => { afterAll(async () => {
await closePages(pages); await closePages(pages);
printHandles.clear();
}); });
it("must check if printing is triggered when the document is open", async () => { it("must check if printing is triggered when the document is open", async () => {
await Promise.all( await Promise.all(
pages.map(async ([browserName, page]) => { pages.map(async ([browserName, page, pageSetupPromise]) => {
await awaitPromise(printHandles.get(page)); await awaitPromise(pageSetupPromise);
}) })
); );
}); });

View File

@ -37,6 +37,10 @@ function loadAndWait(filename, selector, zoom, pageSetup, options) {
}); });
let app_options = ""; let app_options = "";
if (pageSetup) {
options ||= {};
options.initializationhook = "true";
}
if (options) { if (options) {
// Options must be handled in app.js::_parseHashParams. // Options must be handled in app.js::_parseHashParams.
for (const [key, value] of Object.entries(options)) { 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}`; }?file=/test/pdfs/${filename}#zoom=${zoom ?? "page-fit"}${app_options}`;
await page.goto(url); await page.goto(url);
let pageSetupPromise = null;
if (pageSetup) { 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(); await page.bringToFront();
@ -58,7 +79,7 @@ function loadAndWait(filename, selector, zoom, pageSetup, options) {
timeout: 0, 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)"); await page.waitForSelector("#viewer:not(.noUserSelect)");
} }
function waitForAnnotationEditorLayer(page) { function waitForAnnotationEditorLayer(resolve) {
return createPromise(page, resolve => { window.PDFViewerApplication.eventBus.on(
window.PDFViewerApplication.eventBus.on( "annotationeditorlayerrendered",
"annotationeditorlayerrendered", resolve
resolve );
);
});
} }
async function waitForTextLayer(page) { function waitForTextLayer(resolve) {
const handle = await createPromise(page, resolve => { window.PDFViewerApplication.eventBus.on("textlayerrendered", resolve);
window.PDFViewerApplication.eventBus.on("textlayerrendered", resolve);
});
return awaitPromise(handle);
} }
async function scrollIntoView(page, selector) { async function scrollIntoView(page, selector) {

View File

@ -237,6 +237,23 @@ const PDFViewerApplication = {
this.bindEvents(); this.bindEvents();
this.bindWindowEvents(); 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(); this._initializedCapability.resolve();
}, },
@ -329,6 +346,9 @@ const PDFViewerApplication = {
params.get("highlighteditorcolors") params.get("highlighteditorcolors")
); );
} }
if (params.get("initializationhook") === "true") {
AppOptions.set("hasInitializationHook", true);
}
} }
}, },

View File

@ -181,6 +181,11 @@ const defaultOptions = {
value: 0, value: 0,
kind: OptionKind.VIEWER + OptionKind.PREFERENCE, kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
}, },
hasInitializationHook: {
/** @type {boolean} */
value: false,
kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
},
highlightEditorColors: { highlightEditorColors: {
/** @type {string} */ /** @type {string} */
value: "yellow=#FFFF98,green=#53FFBC,blue=#80EBFF,pink=#FFCBE6,red=#FF4F5F", value: "yellow=#FFFF98,green=#53FFBC,blue=#80EBFF,pink=#FFCBE6,red=#FF4F5F",