Support file save triggered from the Firefox integrated version.

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.
This commit is contained in:
Brendan Dahl 2020-08-19 12:19:59 -07:00
parent 10f61b8c96
commit 8023175103
4 changed files with 38 additions and 12 deletions

View File

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

View File

@ -874,7 +874,7 @@ const PDFViewerApplication = {
);
},
download() {
download({ sourceEventType = "download" }) {
function downloadByUrl() {
downloadManager.downloadUrl(url, filename);
}
@ -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;
}
@ -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;
}
@ -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;
@ -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);
@ -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);
@ -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;

View File

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

View File

@ -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) {
@ -130,6 +130,7 @@ class DownloadManager {
blobUrl,
originalUrl: url,
filename,
sourceEventType,
},
onResponse
);
@ -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 });