mirror of
https://github.com/mozilla/pdf.js.git
synced 2026-06-22 16:05:56 +02:00
Add a 'supportsDownloading' browser option to gate saving/downloading
Introduces a 'supportsDownloading' browser option (defaulting to false)
that lets embedders disable the save/download paths entirely. When
disabled:
- the toolbar and secondary-toolbar download buttons are hidden;
- PDFViewerApplication.{download,save,downloadOrSave} and the
"beforeunload" save prompt bail out early;
- the BaseDownloadManager helpers (download, downloadData,
openOrDownloadData) and the Firefox/generic _triggerDownload
implementations no-op.
This commit is contained in:
parent
2ed018ec2d
commit
ece1e2ed0c
@ -1455,6 +1455,72 @@ describe("PDF viewer", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("Save/download disabled when supportsDownloading is false", () => {
|
||||
let pages;
|
||||
|
||||
beforeEach(async () => {
|
||||
pages = await loadAndWait(
|
||||
"tracemonkey.pdf",
|
||||
".textLayer .endOfContent",
|
||||
null,
|
||||
null,
|
||||
{ supportsDownloading: false }
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await closePages(pages);
|
||||
});
|
||||
|
||||
it("must hide the download buttons and skip save/download", async () => {
|
||||
await Promise.all(
|
||||
pages.map(async ([browserName, page]) => {
|
||||
await page.waitForSelector("#downloadButton", { hidden: true });
|
||||
await waitAndClick(page, "#secondaryToolbarToggleButton");
|
||||
await page.waitForSelector("#secondaryDownload", { hidden: true });
|
||||
|
||||
const triggered = await page.evaluate(async () => {
|
||||
const app = window.PDFViewerApplication;
|
||||
const calls = [];
|
||||
const saveDocument = app.pdfDocument.saveDocument.bind(
|
||||
app.pdfDocument
|
||||
);
|
||||
app.pdfDocument.saveDocument = (...args) => {
|
||||
calls.push("saveDocument");
|
||||
return saveDocument(...args);
|
||||
};
|
||||
|
||||
// Each bail-out path dispatches a TESTING-only "downloadskipped"
|
||||
// event, so we can deterministically wait for all four attempts to
|
||||
// run to completion.
|
||||
let skipped = 0;
|
||||
const allSkipped = new Promise(resolve => {
|
||||
app.eventBus.on("downloadskipped", function listener() {
|
||||
if (++skipped === 4) {
|
||||
app.eventBus.off("downloadskipped", listener);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
await app.download();
|
||||
await app.save();
|
||||
await app.downloadOrSave();
|
||||
app.eventBus.dispatch("download", { source: null });
|
||||
await allSkipped;
|
||||
|
||||
return { calls, skipped, downloadManager: app.downloadManager };
|
||||
});
|
||||
expect(triggered.downloadManager)
|
||||
.withContext(`In ${browserName}`)
|
||||
.toBeNull();
|
||||
expect(triggered.calls).withContext(`In ${browserName}`).toEqual([]);
|
||||
expect(triggered.skipped).withContext(`In ${browserName}`).toBe(4);
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Pinch-zoom", () => {
|
||||
let pages;
|
||||
|
||||
|
||||
36
web/app.js
36
web/app.js
@ -385,6 +385,7 @@ const PDFViewerApplication = {
|
||||
maxCanvasPixels: x => parseInt(x, 10),
|
||||
spreadModeOnLoad: x => parseInt(x, 10),
|
||||
supportsCaretBrowsingMode: x => x === "true",
|
||||
supportsDownloading: x => x === "true",
|
||||
viewerCssTheme: x => parseInt(x, 10),
|
||||
forcePageColors: x => x === "true",
|
||||
pageColorsBackground: x => x,
|
||||
@ -434,7 +435,16 @@ const PDFViewerApplication = {
|
||||
ignoreDestinationZoom: AppOptions.get("ignoreDestinationZoom"),
|
||||
}));
|
||||
|
||||
const downloadManager = (this.downloadManager = new DownloadManager());
|
||||
const supportsDownloading = AppOptions.get("supportsDownloading");
|
||||
const downloadManager = (this.downloadManager = supportsDownloading
|
||||
? new DownloadManager()
|
||||
: null);
|
||||
if (appConfig.secondaryToolbar?.downloadButton) {
|
||||
appConfig.secondaryToolbar.downloadButton.hidden = !supportsDownloading;
|
||||
}
|
||||
if (appConfig.toolbar?.download) {
|
||||
appConfig.toolbar.download.hidden = !supportsDownloading;
|
||||
}
|
||||
|
||||
const findController = (this.findController = new PDFFindController({
|
||||
linkService,
|
||||
@ -1311,6 +1321,13 @@ const PDFViewerApplication = {
|
||||
},
|
||||
|
||||
async download() {
|
||||
if (!this.downloadManager) {
|
||||
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("TESTING")) {
|
||||
this.eventBus.dispatch("downloadskipped", { source: this });
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let data;
|
||||
try {
|
||||
data = await (this.pdfDocument
|
||||
@ -1323,6 +1340,13 @@ const PDFViewerApplication = {
|
||||
},
|
||||
|
||||
async save() {
|
||||
if (!this.downloadManager) {
|
||||
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("TESTING")) {
|
||||
this.eventBus.dispatch("downloadskipped", { source: this });
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._saveInProgress) {
|
||||
return;
|
||||
}
|
||||
@ -1354,6 +1378,13 @@ const PDFViewerApplication = {
|
||||
},
|
||||
|
||||
async downloadOrSave() {
|
||||
if (!this.downloadManager) {
|
||||
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("TESTING")) {
|
||||
this.eventBus.dispatch("downloadskipped", { source: this });
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// In the Firefox case, this method MUST always trigger a download.
|
||||
// When the user is closing a modified and unsaved document, we display a
|
||||
// prompt asking for saving or not. In case they save, we must wait for
|
||||
@ -2442,6 +2473,9 @@ const PDFViewerApplication = {
|
||||
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("TESTING")) {
|
||||
return;
|
||||
}
|
||||
if (!this.downloadManager) {
|
||||
return;
|
||||
}
|
||||
if (!this.pdfDocument) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -102,6 +102,11 @@ const defaultOptions = {
|
||||
value: true,
|
||||
kind: OptionKind.BROWSER,
|
||||
},
|
||||
supportsDownloading: {
|
||||
/** @type {boolean} */
|
||||
value: true,
|
||||
kind: OptionKind.BROWSER,
|
||||
},
|
||||
supportsIntegratedFind: {
|
||||
/** @type {boolean} */
|
||||
value: false,
|
||||
|
||||
@ -126,7 +126,7 @@ class PDFAttachmentViewer extends BaseTreeViewer {
|
||||
: fallbackContent;
|
||||
|
||||
if (content) {
|
||||
this.downloadManager.openOrDownloadData(content, filename);
|
||||
this.downloadManager?.openOrDownloadData(content, filename);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -155,7 +155,10 @@ class PDFOutlineViewer extends BaseTreeViewer {
|
||||
const content = await linkService.getAttachmentContent(attachmentId);
|
||||
|
||||
if (content) {
|
||||
this.downloadManager.openOrDownloadData(content, attachment.filename);
|
||||
this.downloadManager?.openOrDownloadData(
|
||||
content,
|
||||
attachment.filename
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user