Disable printing when enablePermission is true and the pdf isn't allowed to be printed (bug 1978985)

This commit is contained in:
Calixte Denizet 2025-07-28 17:42:13 +02:00
parent f16e0b6daa
commit 806f9c1cee
6 changed files with 117 additions and 5 deletions

View File

@ -1302,4 +1302,57 @@ describe("PDF viewer", () => {
); );
}); });
}); });
describe("Printing can be disallowed for some pdfs (bug 1978985)", () => {
let pages;
beforeEach(async () => {
pages = await loadAndWait(
"print_protection.pdf",
"#passwordDialog",
null,
null,
{ enablePermissions: true }
);
});
afterEach(async () => {
await closePages(pages);
});
it("must check that printing is disallowed", async () => {
await Promise.all(
pages.map(async ([browserName, page]) => {
await page.waitForSelector("#printButton", {
visible: true,
});
const selector = "#passwordDialog input#password";
await page.waitForSelector(selector, { visible: true });
await page.type(selector, "1234");
await page.click("#passwordDialog button#passwordSubmit");
await page.waitForSelector(".textLayer .endOfContent");
// The print button should be hidden.
await page.waitForSelector("#printButton", {
hidden: true,
});
await page.waitForSelector("#secondaryPrint", {
hidden: true,
});
const hasThrown = await page.evaluate(() => {
try {
window.print();
} catch {
return true;
}
return false;
});
expect(hasThrown).withContext(`In ${browserName}`).toBeTrue();
})
);
});
});
}); });

View File

@ -738,3 +738,4 @@
!bug1978317.pdf !bug1978317.pdf
!dates.pdf !dates.pdf
!dates_save.pdf !dates_save.pdf
!print_protection.pdf

BIN
test/pdfs/print_protection.pdf Executable file

Binary file not shown.

View File

@ -190,6 +190,7 @@ const PDFViewerApplication = {
_caretBrowsing: null, _caretBrowsing: null,
_isScrolling: false, _isScrolling: false,
editorUndoBar: null, editorUndoBar: null,
_printPermissionPromise: null,
// Called once when the document is loaded. // Called once when the document is loaded.
async initialize(appConfig) { async initialize(appConfig) {
@ -369,6 +370,7 @@ const PDFViewerApplication = {
enableAutoLinking: x => x === "true", enableAutoLinking: x => x === "true",
enableFakeMLManager: x => x === "true", enableFakeMLManager: x => x === "true",
enableGuessAltText: x => x === "true", enableGuessAltText: x => x === "true",
enablePermissions: x => x === "true",
enableUpdatedAddImage: x => x === "true", enableUpdatedAddImage: x => x === "true",
highlightEditorColors: x => x, highlightEditorColors: x => x,
maxCanvasPixels: x => parseInt(x), maxCanvasPixels: x => parseInt(x),
@ -407,6 +409,7 @@ const PDFViewerApplication = {
) )
: new EventBus(); : new EventBus();
this.eventBus = AppOptions.eventBus = eventBus; this.eventBus = AppOptions.eventBus = eventBus;
mlManager?.setEventBus(eventBus, abortSignal); mlManager?.setEventBus(eventBus, abortSignal);
const overlayManager = (this.overlayManager = new OverlayManager()); const overlayManager = (this.overlayManager = new OverlayManager());
@ -798,9 +801,19 @@ const PDFViewerApplication = {
}); });
} }
const togglePrintingButtons = visible => {
appConfig.toolbar?.print?.classList.toggle("hidden", !visible);
appConfig.secondaryToolbar?.printButton.classList.toggle(
"hidden",
!visible
);
};
if (!this.supportsPrinting) { if (!this.supportsPrinting) {
appConfig.toolbar?.print?.classList.add("hidden"); togglePrintingButtons(false);
appConfig.secondaryToolbar?.printButton.classList.add("hidden"); } else {
eventBus.on("printingallowed", ({ isAllowed }) =>
togglePrintingButtons(isAllowed)
);
} }
if (!this.supportsFullscreen) { if (!this.supportsFullscreen) {
@ -1335,6 +1348,25 @@ const PDFViewerApplication = {
load(pdfDocument) { load(pdfDocument) {
this.pdfDocument = pdfDocument; this.pdfDocument = pdfDocument;
this._printPermissionPromise = new Promise(resolve => {
this.eventBus.on(
"printingallowed",
({ isAllowed }) => {
if (
typeof PDFJSDev !== "undefined" &&
PDFJSDev.test("MOZCENTRAL") &&
!isAllowed
) {
window.print = () => {
console.warn("Printing is not allowed.");
};
}
resolve(isAllowed);
},
{ once: true }
);
});
pdfDocument.getDownloadInfo().then(({ length }) => { pdfDocument.getDownloadInfo().then(({ length }) => {
this._contentLength = length; // Ensure that the correct length is used. this._contentLength = length; // Ensure that the correct length is used.
this.loadingBar?.hide(); this.loadingBar?.hide();
@ -1893,7 +1925,7 @@ const PDFViewerApplication = {
return; return;
} }
if (!this.supportsPrinting) { if (!this.supportsPrinting || !this.pdfViewer.printingAllowed) {
this._otherError("pdfjs-printing-not-supported"); this._otherError("pdfjs-printing-not-supported");
return; return;
} }
@ -1961,8 +1993,8 @@ const PDFViewerApplication = {
this.pdfPresentationMode?.request(); this.pdfPresentationMode?.request();
}, },
triggerPrinting() { async triggerPrinting() {
if (this.supportsPrinting) { if (this.supportsPrinting && (await this._printPermissionPromise)) {
window.print(); window.print();
} }
}, },

View File

@ -256,6 +256,10 @@ window.print = function () {
dispatchEvent("beforeprint"); dispatchEvent("beforeprint");
} finally { } finally {
if (!activeService) { if (!activeService) {
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("TESTING")) {
// eslint-disable-next-line no-unsafe-finally
throw new Error("window.print() is not supported");
}
console.error("Expected print service to be initialized."); console.error("Expected print service to be initialized.");
ensureOverlay().then(function () { ensureOverlay().then(function () {
overlayManager.closeIfActive(dialog); overlayManager.closeIfActive(dialog);

View File

@ -254,6 +254,8 @@ class PDFViewer {
#mlManager = null; #mlManager = null;
#printingAllowed = true;
#scrollTimeoutId = null; #scrollTimeoutId = null;
#switchAnnotationEditorModeAC = null; #switchAnnotationEditorModeAC = null;
@ -415,6 +417,10 @@ class PDFViewer {
} }
} }
get printingAllowed() {
return this.#printingAllowed;
}
get pagesCount() { get pagesCount() {
return this._pages.length; return this._pages.length;
} }
@ -672,9 +678,23 @@ class PDFViewer {
textLayerMode: this.#textLayerMode, textLayerMode: this.#textLayerMode,
}; };
if (!permissions) { if (!permissions) {
this.#printingAllowed = true;
this.eventBus.dispatch("printingallowed", {
source: this,
isAllowed: this.#printingAllowed,
});
return params; return params;
} }
this.#printingAllowed =
permissions.includes(PermissionFlag.PRINT_HIGH_QUALITY) ||
permissions.includes(PermissionFlag.PRINT);
this.eventBus.dispatch("printingallowed", {
source: this,
isAllowed: this.#printingAllowed,
});
if ( if (
!permissions.includes(PermissionFlag.COPY) && !permissions.includes(PermissionFlag.COPY) &&
this.#textLayerMode === TextLayerMode.ENABLE this.#textLayerMode === TextLayerMode.ENABLE
@ -843,6 +863,8 @@ class PDFViewer {
this.#annotationEditorUIManager?.destroy(); this.#annotationEditorUIManager?.destroy();
this.#annotationEditorUIManager = null; this.#annotationEditorUIManager = null;
this.#printingAllowed = true;
} }
this.pdfDocument = pdfDocument; this.pdfDocument = pdfDocument;