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",
"type": "string",
"default": "CanvasText"
},
"hasInitializationHook": {
"type": "boolean",
"default": false
}
}
}

View File

@ -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");

View File

@ -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);
}
);
}
);
});

View File

@ -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);
})
);
});

View File

@ -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) {

View File

@ -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);
}
}
},

View File

@ -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",