fix_crash_when_saving_edited_pdf_files.patch 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
  2. From: Shelley Vohr <[email protected]>
  3. Date: Mon, 17 Jan 2022 23:47:54 +0100
  4. Subject: fix: crash when saving edited PDF files
  5. This commit fixes a crash that persists any time a user attempts to
  6. download an edited PDF. This was happening because the logic flow for
  7. downloading of any edited PDF triggers a call to
  8. chrome.fileSystem.chooseEntry, which we do not support and which
  9. therefore causes unmapped page access crashes.
  10. This patch can be removed should we choose to support chrome.fileSystem
  11. or support it enough to fix the crash.
  12. diff --git a/chrome/browser/resources/pdf/pdf_viewer.ts b/chrome/browser/resources/pdf/pdf_viewer.ts
  13. index 4f83c769386ab3f8b9e62ecf82964a3b85b06625..c86ac99a1ad70eddb34cdfa65e2e3fab546c4c83 100644
  14. --- a/chrome/browser/resources/pdf/pdf_viewer.ts
  15. +++ b/chrome/browser/resources/pdf/pdf_viewer.ts
  16. @@ -1051,28 +1051,27 @@ export class PdfViewerElement extends PdfViewerBaseElement {
  17. dataArray = [result.dataToSave];
  18. }
  19. - const blob = new Blob(dataArray);
  20. const fileName = this.attachments_[index].name;
  21. - chrome.fileSystem.chooseEntry(
  22. - {type: 'saveFile', suggestedName: fileName},
  23. - (entry?: FileSystemFileEntry) => {
  24. - if (chrome.runtime.lastError) {
  25. - if (chrome.runtime.lastError.message !== 'User cancelled') {
  26. - console.error(
  27. - 'chrome.fileSystem.chooseEntry failed: ' +
  28. - chrome.runtime.lastError.message);
  29. - }
  30. - return;
  31. - }
  32. - entry!.createWriter((writer: FileWriter) => {
  33. - writer.write(blob);
  34. - // <if expr="enable_ink">
  35. - // Unblock closing the window now that the user has saved
  36. - // successfully.
  37. - this.setShowBeforeUnloadDialog_(false);
  38. - // </if>
  39. - });
  40. - });
  41. + const blob = new Blob(dataArray);
  42. +
  43. + try {
  44. + const fileHandle = await window.showSaveFilePicker({
  45. + suggestedName: fileName,
  46. + });
  47. +
  48. + const writable = await fileHandle.createWritable();
  49. + await writable.write(blob);
  50. + await writable.close();
  51. + // <if expr="enable_ink">
  52. + // Unblock closing the window now that the user has saved
  53. + // successfully.
  54. + this.setShowBeforeUnloadDialog_(false);
  55. + // </if>
  56. + } catch (error: any) {
  57. + if (error.name !== 'AbortError') {
  58. + console.error('window.showSaveFilePicker failed: ' + error);
  59. + }
  60. + }
  61. }
  62. /**
  63. @@ -1256,36 +1255,33 @@ export class PdfViewerElement extends PdfViewerBaseElement {
  64. fileName = fileName + '.pdf';
  65. }
  66. - // Create blob before callback to avoid race condition.
  67. const blob = new Blob([result.dataToSave], {type: 'application/pdf'});
  68. - chrome.fileSystem.chooseEntry(
  69. - {
  70. - type: 'saveFile',
  71. - accepts: [{description: '*.pdf', extensions: ['pdf']}],
  72. - suggestedName: fileName,
  73. - },
  74. - (entry?: FileSystemFileEntry) => {
  75. - if (chrome.runtime.lastError) {
  76. - if (chrome.runtime.lastError.message !== 'User cancelled') {
  77. - console.error(
  78. - 'chrome.fileSystem.chooseEntry failed: ' +
  79. - chrome.runtime.lastError.message);
  80. - }
  81. - return;
  82. - }
  83. - entry!.createWriter((writer: FileWriter) => {
  84. - writer.write(blob);
  85. - // <if expr="enable_ink or enable_pdf_ink2">
  86. - // Unblock closing the window now that the user has saved
  87. - // successfully.
  88. - this.setShowBeforeUnloadDialog_(false);
  89. - // </if>
  90. - // <if expr="enable_pdf_ink2">
  91. - this.hasSavedEdits_ =
  92. - this.hasSavedEdits_ || requestType === SaveRequestType.EDITED;
  93. - // </if>
  94. - });
  95. - });
  96. + try {
  97. + const fileHandle = await window.showSaveFilePicker({
  98. + suggestedName: fileName,
  99. + types: [{
  100. + description: 'PDF Files',
  101. + accept: { 'application/pdf': ['.pdf'] },
  102. + }],
  103. + });
  104. +
  105. + const writable = await fileHandle.createWritable();
  106. + await writable.write(blob);
  107. + await writable.close();
  108. + // <if expr="enable_ink or enable_pdf_ink2">
  109. + // Unblock closing the window now that the user has saved
  110. + // successfully.
  111. + this.setShowBeforeUnloadDialog_(false);
  112. + // </if>
  113. + // <if expr="enable_pdf_ink2">
  114. + this.hasSavedEdits_ =
  115. + this.hasSavedEdits_ || requestType === SaveRequestType.EDITED;
  116. + // </if>
  117. + } catch (error: any) {
  118. + if (error.name !== 'AbortError') {
  119. + console.error('window.showSaveFilePicker failed: ' + error);
  120. + }
  121. + }
  122. // <if expr="enable_pdf_ink2">
  123. // Ink2 doesn't need to exit annotation mode after save.
  124. @@ -1421,6 +1417,9 @@ declare global {
  125. interface HTMLElementTagNameMap {
  126. 'pdf-viewer': PdfViewerElement;
  127. }
  128. + interface Window {
  129. + showSaveFilePicker(opts: unknown): Promise<FileSystemFileHandle>;
  130. + }
  131. }
  132. customElements.define(PdfViewerElement.is, PdfViewerElement);