Merge pull request #13175 from Snuffleupagus/app-close-save

[GENERIC viewer] Avoid data loss in forms, by triggering saving when the document is closed (issue 12257)
This commit is contained in:
Tim van der Meij 2021-04-05 14:03:18 +02:00 committed by GitHub
commit 3698bc1287
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -802,7 +802,19 @@ const PDFViewerApplication = {
}
if (!this.pdfLoadingTask) {
return undefined;
return;
}
if (
(typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) &&
this.pdfDocument?.annotationStorage.size > 0 &&
this._annotationStorageModified
) {
try {
// Trigger saving, to prevent data loss in forms; see issue 12257.
await this.save({ sourceEventType: "save" });
} catch (reason) {
// Ignoring errors, to ensure that document closing won't break.
}
}
const promises = [];
@ -851,8 +863,6 @@ const PDFViewerApplication = {
PDFBug.cleanup();
}
await Promise.all(promises);
return undefined;
},
/**
@ -949,62 +959,59 @@ const PDFViewerApplication = {
);
},
download({ sourceEventType = "download" } = {}) {
function downloadByUrl() {
downloadManager.downloadUrl(url, filename);
}
const downloadManager = this.downloadManager,
url = this.baseUrl,
filename = this._docFilename;
// When the PDF document isn't ready, or the PDF file is still downloading,
// simply download using the URL.
if (!this.pdfDocument || !this.downloadComplete) {
downloadByUrl();
/**
* @private
*/
_ensureDownloadComplete() {
if (this.pdfDocument && this.downloadComplete) {
return;
}
throw new Error("PDF document not downloaded.");
},
this.pdfDocument
.getData()
.then(function (data) {
const blob = new Blob([data], { type: "application/pdf" });
downloadManager.download(blob, url, filename, sourceEventType);
})
.catch(downloadByUrl); // Error occurred, try downloading with the URL.
async download({ sourceEventType = "download" } = {}) {
const url = this.baseUrl,
filename = this._docFilename;
try {
this._ensureDownloadComplete();
const data = await this.pdfDocument.getData();
const blob = new Blob([data], { type: "application/pdf" });
await this.downloadManager.download(blob, url, filename, sourceEventType);
} catch (reason) {
// When the PDF document isn't ready, or the PDF file is still
// downloading, simply download using the URL.
await this.downloadManager.downloadUrl(url, filename);
}
},
async save({ sourceEventType = "download" } = {}) {
if (this._saveInProgress) {
return;
}
const downloadManager = this.downloadManager,
url = this.baseUrl,
filename = this._docFilename;
// 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({ sourceEventType });
return;
}
this._saveInProgress = true;
await this.pdfScriptingManager.dispatchWillSave();
this.pdfDocument
.saveDocument(this.pdfDocument.annotationStorage)
.then(data => {
const blob = new Blob([data], { type: "application/pdf" });
downloadManager.download(blob, url, filename, sourceEventType);
})
.catch(() => {
this.download({ sourceEventType });
})
.finally(async () => {
await this.pdfScriptingManager.dispatchDidSave();
this._saveInProgress = false;
});
const url = this.baseUrl,
filename = this._docFilename;
try {
this._ensureDownloadComplete();
const data = await this.pdfDocument.saveDocument(
this.pdfDocument.annotationStorage
);
const blob = new Blob([data], { type: "application/pdf" });
await this.downloadManager.download(blob, url, filename, sourceEventType);
} catch (reason) {
// When the PDF document isn't ready, or the PDF file is still
// downloading, simply fallback to a "regular" download.
await this.download({ sourceEventType });
} finally {
await this.pdfScriptingManager.dispatchDidSave();
this._saveInProgress = false;
}
},
downloadOrSave(options) {
@ -1710,11 +1717,19 @@ const PDFViewerApplication = {
}
const { annotationStorage } = pdfDocument;
annotationStorage.onSetModified = function () {
annotationStorage.onSetModified = () => {
window.addEventListener("beforeunload", beforeUnload);
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) {
this._annotationStorageModified = true;
}
};
annotationStorage.onResetModified = function () {
annotationStorage.onResetModified = () => {
window.removeEventListener("beforeunload", beforeUnload);
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) {
delete this._annotationStorageModified;
}
};
},