Skip to content

Commit

Permalink
Support file save triggered from the Firefox integrated version.
Browse files Browse the repository at this point in the history
Related to https://bugzilla.mozilla.org/show_bug.cgi?id=1659753

This allows Firefox trigger a "save" event from ctrl/cmd+s or the "Save
Page As" context menu, which in turn lets pdf.js generate a new PDF if
there is form data to save.

I also now use `sourceEventType` on downloads so Firefox can determine if
it should launch the "open with" dialog or "save as" dialog.
  • Loading branch information
Brendan Dahl committed Aug 21, 2020
1 parent 10f61b8 commit 8023175
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 12 deletions.
2 changes: 1 addition & 1 deletion src/display/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -2541,7 +2541,7 @@ class WorkerTransport {
numPages: this._numPages,
annotationStorage:
(annotationStorage && annotationStorage.getAll()) || null,
filename: this._fullReader.filename,
filename: this._fullReader ? this._fullReader.filename : null,
})
.finally(() => {
annotationStorage.resetModified();
Expand Down
26 changes: 17 additions & 9 deletions web/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -874,7 +874,7 @@ const PDFViewerApplication = {
);
},

download() {
download({ sourceEventType = "download" }) {
function downloadByUrl() {
downloadManager.downloadUrl(url, filename);
}
Expand Down Expand Up @@ -902,12 +902,12 @@ const PDFViewerApplication = {
.getData()
.then(function (data) {
const blob = new Blob([data], { type: "application/pdf" });
downloadManager.download(blob, url, filename);
downloadManager.download(blob, url, filename, sourceEventType);
})
.catch(downloadByUrl); // Error occurred, try downloading with the URL.
},

save() {
save({ sourceEventType = "download" }) {
if (this._saveInProgress) {
return;
}
Expand All @@ -927,7 +927,7 @@ const PDFViewerApplication = {
// When the PDF document isn't ready, or the PDF file is still downloading,
// simply download using the URL.
if (!this.pdfDocument || !this.downloadComplete) {
this.download();
this.download({ sourceEventType });
return;
}

Expand All @@ -936,10 +936,10 @@ const PDFViewerApplication = {
.saveDocument(this.pdfDocument.annotationStorage)
.then(data => {
const blob = new Blob([data], { type: "application/pdf" });
downloadManager.download(blob, url, filename);
downloadManager.download(blob, url, filename, sourceEventType);
})
.catch(() => {
this.download();
this.download({ sourceEventType });
})
.finally(() => {
this._saveInProgress = false;
Expand Down Expand Up @@ -1722,6 +1722,7 @@ const PDFViewerApplication = {
eventBus._on("presentationmode", webViewerPresentationMode);
eventBus._on("print", webViewerPrint);
eventBus._on("download", webViewerDownload);
eventBus._on("save", webViewerSave);
eventBus._on("firstpage", webViewerFirstPage);
eventBus._on("lastpage", webViewerLastPage);
eventBus._on("nextpage", webViewerNextPage);
Expand Down Expand Up @@ -1800,6 +1801,7 @@ const PDFViewerApplication = {
eventBus._off("presentationmode", webViewerPresentationMode);
eventBus._off("print", webViewerPrint);
eventBus._off("download", webViewerDownload);
eventBus._off("save", webViewerSave);
eventBus._off("firstpage", webViewerFirstPage);
eventBus._off("lastpage", webViewerLastPage);
eventBus._off("nextpage", webViewerNextPage);
Expand Down Expand Up @@ -2334,16 +2336,22 @@ function webViewerPresentationMode() {
function webViewerPrint() {
window.print();
}
function webViewerDownload() {
function webViewerDownloadOrSave(sourceEventType) {
if (
PDFViewerApplication.pdfDocument &&
PDFViewerApplication.pdfDocument.annotationStorage.size > 0
) {
PDFViewerApplication.save();
PDFViewerApplication.save({ sourceEventType });
} else {
PDFViewerApplication.download();
PDFViewerApplication.download({ sourceEventType });
}
}
function webViewerDownload() {
webViewerDownloadOrSave("download");
}
function webViewerSave() {
webViewerDownloadOrSave("save");
}
function webViewerFirstPage() {
if (PDFViewerApplication.pdfDocument) {
PDFViewerApplication.page = 1;
Expand Down
8 changes: 7 additions & 1 deletion web/download_manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,13 @@ class DownloadManager {
download(blobUrl, filename);
}

download(blob, url, filename) {
/**
* @param sourceEventType {string} Used to signal what triggered the download.
* The version of PDF.js integrated with Firefox uses this to to determine
* which dialog to show. "save" triggers "save as" and "download" triggers
* the "open with" dialog.
*/
download(blob, url, filename, sourceEventType = "download") {
if (navigator.msSaveBlob) {
// IE10 / IE11
if (!navigator.msSaveBlob(blob, filename)) {
Expand Down
14 changes: 13 additions & 1 deletion web/firefoxcom.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ class DownloadManager {
);
}

download(blob, url, filename) {
download(blob, url, filename, sourceEventType = "download") {
const blobUrl = URL.createObjectURL(blob);
const onResponse = err => {
if (err && this.onerror) {
Expand All @@ -130,6 +130,7 @@ class DownloadManager {
blobUrl,
originalUrl: url,
filename,
sourceEventType,
},
onResponse
);
Expand Down Expand Up @@ -231,6 +232,17 @@ class MozL10n {
}
})();

(function listenSaveEvent() {
const handleEvent = function ({ type, detail }) {
if (!PDFViewerApplication.initialized) {
return;
}
PDFViewerApplication.eventBus.dispatch(type, { source: window });
};

window.addEventListener("save", handleEvent);
})();

class FirefoxComDataRangeTransport extends PDFDataRangeTransport {
requestDataRange(begin, end) {
FirefoxCom.request("requestDataRange", { begin, end });
Expand Down

0 comments on commit 8023175

Please sign in to comment.