fix: use proper PDF save approach (#44279)

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
This commit is contained in:
trop[bot] 2024-10-16 13:52:17 -04:00 committed by GitHub
parent 354d6155d8
commit 4241045017
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -13,54 +13,128 @@ This patch can be removed should we choose to support chrome.fileSystem
or support it enough to fix the crash. or support it enough to fix the crash.
diff --git a/chrome/browser/resources/pdf/pdf_viewer.ts b/chrome/browser/resources/pdf/pdf_viewer.ts diff --git a/chrome/browser/resources/pdf/pdf_viewer.ts b/chrome/browser/resources/pdf/pdf_viewer.ts
index 2e621b9a66b0443ad961d32a6bed47e1128035a8..5e7c0e238bfe6eb55a2e795681529679a35b8d03 100644 index 2e621b9a66b0443ad961d32a6bed47e1128035a8..490f647b15b98fbd27dabeaa1349064044774cc5 100644
--- a/chrome/browser/resources/pdf/pdf_viewer.ts --- a/chrome/browser/resources/pdf/pdf_viewer.ts
+++ b/chrome/browser/resources/pdf/pdf_viewer.ts +++ b/chrome/browser/resources/pdf/pdf_viewer.ts
@@ -1012,7 +1012,15 @@ export class PdfViewerElement extends PdfViewerBaseElement { @@ -1012,28 +1012,27 @@ export class PdfViewerElement extends PdfViewerBaseElement {
dataArray = [result.dataToSave]; dataArray = [result.dataToSave];
} }
+ const a = document.createElement('a'); - const blob = new Blob(dataArray);
+ a.download = this.attachments_[index].name;
const blob = new Blob(dataArray);
+ // <if expr="not _google_chrome">
+ a.href = URL.createObjectURL(blob);
+ a.click();
+ URL.revokeObjectURL(a.href);
+ // </if>
+ // <if expr="_google_chrome">
const fileName = this.attachments_[index].name; const fileName = this.attachments_[index].name;
chrome.fileSystem.chooseEntry( - chrome.fileSystem.chooseEntry(
{type: 'saveFile', suggestedName: fileName}, - {type: 'saveFile', suggestedName: fileName},
@@ -1034,6 +1042,7 @@ export class PdfViewerElement extends PdfViewerBaseElement { - (entry?: FileSystemFileEntry) => {
// </if> - if (chrome.runtime.lastError) {
}); - if (chrome.runtime.lastError.message !== 'User cancelled') {
}); - console.error(
+ // </if> - 'chrome.fileSystem.chooseEntry failed: ' +
- chrome.runtime.lastError.message);
- }
- return;
- }
- entry!.createWriter((writer: FileWriter) => {
- writer.write(blob);
- // <if expr="enable_ink">
- // Unblock closing the window now that the user has saved
- // successfully.
- this.setShowBeforeUnloadDialog_(false);
- // </if>
- });
- });
+ const blob = new Blob(dataArray);
+
+ try {
+ const fileHandle = await window.showSaveFilePicker({
+ suggestedName: fileName,
+ });
+
+ const writable = await fileHandle.createWritable();
+ await writable.write(blob);
+ await writable.close();
+ // <if expr="enable_ink">
+ // Unblock closing the window now that the user has saved
+ // successfully.
+ this.setShowBeforeUnloadDialog_(false);
+ // </if>
+ } catch (error: any) {
+ if (error.name !== 'AbortError') {
+ console.error('window.showSaveFilePicker failed: ' + error);
+ }
+ }
} }
/** /**
@@ -1162,7 +1171,15 @@ export class PdfViewerElement extends PdfViewerBaseElement { @@ -1161,36 +1160,33 @@ export class PdfViewerElement extends PdfViewerBaseElement {
fileName = fileName + '.pdf';
} }
// Create blob before callback to avoid race condition. - // Create blob before callback to avoid race condition.
+ const a = document.createElement('a');
+ a.download = fileName;
const blob = new Blob([result.dataToSave], {type: 'application/pdf'}); const blob = new Blob([result.dataToSave], {type: 'application/pdf'});
+ // <if expr="not _google_chrome"> - chrome.fileSystem.chooseEntry(
+ a.href = URL.createObjectURL(blob); - {
+ a.click(); - type: 'saveFile',
+ URL.revokeObjectURL(a.href); - accepts: [{description: '*.pdf', extensions: ['pdf']}],
+ // </if> - suggestedName: fileName,
+ // <if expr="_google_chrome"> - },
chrome.fileSystem.chooseEntry( - (entry?: FileSystemFileEntry) => {
{ - if (chrome.runtime.lastError) {
type: 'saveFile', - if (chrome.runtime.lastError.message !== 'User cancelled') {
@@ -1191,6 +1208,7 @@ export class PdfViewerElement extends PdfViewerBaseElement { - console.error(
// </if> - 'chrome.fileSystem.chooseEntry failed: ' +
}); - chrome.runtime.lastError.message);
}); - }
+ // </if> - return;
- }
- entry!.createWriter((writer: FileWriter) => {
- writer.write(blob);
- // <if expr="enable_ink or enable_pdf_ink2">
- // Unblock closing the window now that the user has saved
- // successfully.
- this.setShowBeforeUnloadDialog_(false);
- // </if>
- // <if expr="enable_pdf_ink2">
- this.hasSavedEdits_ =
- this.hasSavedEdits_ || requestType === SaveRequestType.EDITED;
- // </if>
- });
- });
+ try {
+ const fileHandle = await window.showSaveFilePicker({
+ suggestedName: fileName,
+ types: [{
+ description: 'PDF Files',
+ accept: { 'application/pdf': ['.pdf'] },
+ }],
+ });
+
+ const writable = await fileHandle.createWritable();
+ await writable.write(blob);
+ await writable.close();
+ // <if expr="enable_ink or enable_pdf_ink2">
+ // Unblock closing the window now that the user has saved
+ // successfully.
+ this.setShowBeforeUnloadDialog_(false);
+ // </if>
+ // <if expr="enable_pdf_ink2">
+ this.hasSavedEdits_ =
+ this.hasSavedEdits_ || requestType === SaveRequestType.EDITED;
+ // </if>
+ } catch (error: any) {
+ if (error.name !== 'AbortError') {
+ console.error('window.showSaveFilePicker failed: ' + error);
+ }
+ }
// <if expr="enable_pdf_ink2"> // <if expr="enable_pdf_ink2">
// Ink2 doesn't need to exit annotation mode after save. // Ink2 doesn't need to exit annotation mode after save.
@@ -1300,6 +1296,9 @@ declare global {
interface HTMLElementTagNameMap {
'pdf-viewer': PdfViewerElement;
}
+ interface Window {
+ showSaveFilePicker(opts: unknown): Promise<FileSystemFileHandle>;
+ }
}
customElements.define(PdfViewerElement.is, PdfViewerElement);