Merge pull request #16391 from calixteman/gv_open_in_app
[GeckoView] Add a button to download and open the file in an external app (bug 1829367)
This commit is contained in:
commit
da03d322ed
@ -43,6 +43,8 @@ save.title=Save
|
|||||||
save_label=Save
|
save_label=Save
|
||||||
bookmark1.title=Current Page (View URL from Current Page)
|
bookmark1.title=Current Page (View URL from Current Page)
|
||||||
bookmark1_label=Current Page
|
bookmark1_label=Current Page
|
||||||
|
open_in_app.title=Open in app
|
||||||
|
open_in_app_label=Open in app
|
||||||
|
|
||||||
# Secondary toolbar and context menu
|
# Secondary toolbar and context menu
|
||||||
tools.title=Tools
|
tools.title=Tools
|
||||||
|
27
web/app.js
27
web/app.js
@ -1012,7 +1012,7 @@ const PDFViewerApplication = {
|
|||||||
throw new Error("PDF document not downloaded.");
|
throw new Error("PDF document not downloaded.");
|
||||||
},
|
},
|
||||||
|
|
||||||
async download() {
|
async download(options = {}) {
|
||||||
const url = this._downloadUrl,
|
const url = this._downloadUrl,
|
||||||
filename = this._docFilename;
|
filename = this._docFilename;
|
||||||
try {
|
try {
|
||||||
@ -1021,15 +1021,15 @@ const PDFViewerApplication = {
|
|||||||
const data = await this.pdfDocument.getData();
|
const data = await this.pdfDocument.getData();
|
||||||
const blob = new Blob([data], { type: "application/pdf" });
|
const blob = new Blob([data], { type: "application/pdf" });
|
||||||
|
|
||||||
await this.downloadManager.download(blob, url, filename);
|
await this.downloadManager.download(blob, url, filename, options);
|
||||||
} catch (reason) {
|
} catch (reason) {
|
||||||
// When the PDF document isn't ready, or the PDF file is still
|
// When the PDF document isn't ready, or the PDF file is still
|
||||||
// downloading, simply download using the URL.
|
// downloading, simply download using the URL.
|
||||||
await this.downloadManager.downloadUrl(url, filename);
|
await this.downloadManager.downloadUrl(url, filename, options);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
async save() {
|
async save(options = {}) {
|
||||||
if (this._saveInProgress) {
|
if (this._saveInProgress) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1044,12 +1044,12 @@ const PDFViewerApplication = {
|
|||||||
const data = await this.pdfDocument.saveDocument();
|
const data = await this.pdfDocument.saveDocument();
|
||||||
const blob = new Blob([data], { type: "application/pdf" });
|
const blob = new Blob([data], { type: "application/pdf" });
|
||||||
|
|
||||||
await this.downloadManager.download(blob, url, filename);
|
await this.downloadManager.download(blob, url, filename, options);
|
||||||
} catch (reason) {
|
} catch (reason) {
|
||||||
// When the PDF document isn't ready, or the PDF file is still
|
// When the PDF document isn't ready, or the PDF file is still
|
||||||
// downloading, simply fallback to a "regular" download.
|
// downloading, simply fallback to a "regular" download.
|
||||||
console.error(`Error when saving the document: ${reason.message}`);
|
console.error(`Error when saving the document: ${reason.message}`);
|
||||||
await this.download();
|
await this.download(options);
|
||||||
} finally {
|
} finally {
|
||||||
await this.pdfScriptingManager.dispatchDidSave();
|
await this.pdfScriptingManager.dispatchDidSave();
|
||||||
this._saveInProgress = false;
|
this._saveInProgress = false;
|
||||||
@ -1063,14 +1063,18 @@ const PDFViewerApplication = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
downloadOrSave() {
|
downloadOrSave(options = {}) {
|
||||||
if (this.pdfDocument?.annotationStorage.size > 0) {
|
if (this.pdfDocument?.annotationStorage.size > 0) {
|
||||||
this.save();
|
this.save(options);
|
||||||
} else {
|
} else {
|
||||||
this.download();
|
this.download(options);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
openInExternalApp() {
|
||||||
|
this.downloadOrSave({ openInExternalApp: true });
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Report the error; used for errors affecting loading and/or parsing of
|
* Report the error; used for errors affecting loading and/or parsing of
|
||||||
* the entire PDF document.
|
* the entire PDF document.
|
||||||
@ -1852,6 +1856,7 @@ const PDFViewerApplication = {
|
|||||||
);
|
);
|
||||||
eventBus._on("print", webViewerPrint);
|
eventBus._on("print", webViewerPrint);
|
||||||
eventBus._on("download", webViewerDownload);
|
eventBus._on("download", webViewerDownload);
|
||||||
|
eventBus._on("openinexternalapp", webViewerOpenInExternalApp);
|
||||||
eventBus._on("firstpage", webViewerFirstPage);
|
eventBus._on("firstpage", webViewerFirstPage);
|
||||||
eventBus._on("lastpage", webViewerLastPage);
|
eventBus._on("lastpage", webViewerLastPage);
|
||||||
eventBus._on("nextpage", webViewerNextPage);
|
eventBus._on("nextpage", webViewerNextPage);
|
||||||
@ -1984,6 +1989,7 @@ const PDFViewerApplication = {
|
|||||||
eventBus._off("presentationmode", webViewerPresentationMode);
|
eventBus._off("presentationmode", webViewerPresentationMode);
|
||||||
eventBus._off("print", webViewerPrint);
|
eventBus._off("print", webViewerPrint);
|
||||||
eventBus._off("download", webViewerDownload);
|
eventBus._off("download", webViewerDownload);
|
||||||
|
eventBus._off("openinexternalapp", webViewerOpenInExternalApp);
|
||||||
eventBus._off("firstpage", webViewerFirstPage);
|
eventBus._off("firstpage", webViewerFirstPage);
|
||||||
eventBus._off("lastpage", webViewerLastPage);
|
eventBus._off("lastpage", webViewerLastPage);
|
||||||
eventBus._off("nextpage", webViewerNextPage);
|
eventBus._off("nextpage", webViewerNextPage);
|
||||||
@ -2500,6 +2506,9 @@ function webViewerPrint() {
|
|||||||
function webViewerDownload() {
|
function webViewerDownload() {
|
||||||
PDFViewerApplication.downloadOrSave();
|
PDFViewerApplication.downloadOrSave();
|
||||||
}
|
}
|
||||||
|
function webViewerOpenInExternalApp() {
|
||||||
|
PDFViewerApplication.openInExternalApp();
|
||||||
|
}
|
||||||
function webViewerFirstPage() {
|
function webViewerFirstPage() {
|
||||||
PDFViewerApplication.page = 1;
|
PDFViewerApplication.page = 1;
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ function download(blobUrl, filename) {
|
|||||||
class DownloadManager {
|
class DownloadManager {
|
||||||
#openBlobUrls = new WeakMap();
|
#openBlobUrls = new WeakMap();
|
||||||
|
|
||||||
downloadUrl(url, filename) {
|
downloadUrl(url, filename, _options) {
|
||||||
if (!createValidAbsoluteUrl(url, "http://example.com")) {
|
if (!createValidAbsoluteUrl(url, "http://example.com")) {
|
||||||
console.error(`downloadUrl - not a valid URL: ${url}`);
|
console.error(`downloadUrl - not a valid URL: ${url}`);
|
||||||
return; // restricted/invalid URL
|
return; // restricted/invalid URL
|
||||||
@ -110,7 +110,7 @@ class DownloadManager {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
download(blob, url, filename) {
|
download(blob, url, filename, _options) {
|
||||||
const blobUrl = URL.createObjectURL(blob);
|
const blobUrl = URL.createObjectURL(blob);
|
||||||
download(blobUrl, filename);
|
download(blobUrl, filename);
|
||||||
}
|
}
|
||||||
|
@ -108,10 +108,11 @@ class FirefoxCom {
|
|||||||
class DownloadManager {
|
class DownloadManager {
|
||||||
#openBlobUrls = new WeakMap();
|
#openBlobUrls = new WeakMap();
|
||||||
|
|
||||||
downloadUrl(url, filename) {
|
downloadUrl(url, filename, options = {}) {
|
||||||
FirefoxCom.request("download", {
|
FirefoxCom.request("download", {
|
||||||
originalUrl: url,
|
originalUrl: url,
|
||||||
filename,
|
filename,
|
||||||
|
options,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,13 +161,14 @@ class DownloadManager {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
download(blob, url, filename) {
|
download(blob, url, filename, options = {}) {
|
||||||
const blobUrl = URL.createObjectURL(blob);
|
const blobUrl = URL.createObjectURL(blob);
|
||||||
|
|
||||||
FirefoxCom.request("download", {
|
FirefoxCom.request("download", {
|
||||||
blobUrl,
|
blobUrl,
|
||||||
originalUrl: url,
|
originalUrl: url,
|
||||||
filename,
|
filename,
|
||||||
|
options,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
11
web/images/gv-toolbarButton-openinapp.svg
Normal file
11
web/images/gv-toolbarButton-openinapp.svg
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M4 4.5H6.5V7H4V4.5Z" fill="black"/>
|
||||||
|
<path d="M6.5 10.5H4V13H6.5V10.5Z" fill="black"/>
|
||||||
|
<path d="M13.25 10.5H10.75V13H13.25V10.5Z" fill="black"/>
|
||||||
|
<path d="M17.5 10.5H20V13H17.5V10.5Z" fill="black"/>
|
||||||
|
<path d="M6.5 16.5H4V19H6.5V16.5Z" fill="black"/>
|
||||||
|
<path d="M10.75 16.5H13.25V19H10.75V16.5Z" fill="black"/>
|
||||||
|
<path d="M20 16.5H17.5V19H20V16.5Z" fill="black"/>
|
||||||
|
<path d="M13.25 4.5H10.75V7H13.25V4.5Z" fill="black"/>
|
||||||
|
<path d="M17.5 4.5H20V7H17.5V4.5Z" fill="black"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 573 B |
@ -156,8 +156,9 @@ class IDownloadManager {
|
|||||||
/**
|
/**
|
||||||
* @param {string} url
|
* @param {string} url
|
||||||
* @param {string} filename
|
* @param {string} filename
|
||||||
|
* @param {Object} [options]
|
||||||
*/
|
*/
|
||||||
downloadUrl(url, filename) {}
|
downloadUrl(url, filename, options) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Uint8Array} data
|
* @param {Uint8Array} data
|
||||||
@ -178,8 +179,9 @@ class IDownloadManager {
|
|||||||
* @param {Blob} blob
|
* @param {Blob} blob
|
||||||
* @param {string} url
|
* @param {string} url
|
||||||
* @param {string} filename
|
* @param {string} filename
|
||||||
|
* @param {Object} [options]
|
||||||
*/
|
*/
|
||||||
download(blob, url, filename) {}
|
download(blob, url, filename, options) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -32,7 +32,10 @@ class Toolbar {
|
|||||||
*/
|
*/
|
||||||
constructor(options, eventBus, _l10n) {
|
constructor(options, eventBus, _l10n) {
|
||||||
this.#eventBus = eventBus;
|
this.#eventBus = eventBus;
|
||||||
this.#buttons = [{ element: options.download, eventName: "download" }];
|
this.#buttons = [
|
||||||
|
{ element: options.download, eventName: "download" },
|
||||||
|
{ element: options.openInApp, eventName: "openinexternalapp" },
|
||||||
|
];
|
||||||
|
|
||||||
// Bind the event listeners for click and various other actions.
|
// Bind the event listeners for click and various other actions.
|
||||||
this.#bindListeners(options);
|
this.#bindListeners(options);
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
--toolbar-fg-color: #15141a;
|
--toolbar-fg-color: #15141a;
|
||||||
|
|
||||||
--toolbarButton-download-icon: url(images/gv-toolbarButton-download.svg);
|
--toolbarButton-download-icon: url(images/gv-toolbarButton-download.svg);
|
||||||
|
--toolbarButton-openinapp-icon: url(images/gv-toolbarButton-openinapp.svg);
|
||||||
}
|
}
|
||||||
|
|
||||||
:root:dir(rtl) {
|
:root:dir(rtl) {
|
||||||
@ -217,6 +218,10 @@ body {
|
|||||||
mask-image: var(--toolbarButton-download-icon);
|
mask-image: var(--toolbarButton-download-icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#openInApp::before {
|
||||||
|
mask-image: var(--toolbarButton-openinapp-icon);
|
||||||
|
}
|
||||||
|
|
||||||
.dialogButton {
|
.dialogButton {
|
||||||
width: auto;
|
width: auto;
|
||||||
margin: 3px 4px 2px !important;
|
margin: 3px 4px 2px !important;
|
||||||
|
@ -85,6 +85,9 @@ See https://github.com/adobe-type-tools/cmap-resources
|
|||||||
<button id="download" class="toolbarButton" title="Save" tabindex="31" data-l10n-id="download">
|
<button id="download" class="toolbarButton" title="Save" tabindex="31" data-l10n-id="download">
|
||||||
<span data-l10n-id="download_label">Download</span>
|
<span data-l10n-id="download_label">Download</span>
|
||||||
</button>
|
</button>
|
||||||
|
<button id="openInApp" class="toolbarButton" title="Open in app" tabindex="32" data-l10n-id="open_in_app">
|
||||||
|
<span data-l10n-id="open_in_app_label">Open in app</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="viewerContainer" tabindex="0">
|
<div id="viewerContainer" tabindex="0">
|
||||||
|
@ -45,6 +45,7 @@ function getViewerConfiguration() {
|
|||||||
mainContainer,
|
mainContainer,
|
||||||
container: document.getElementById("floatingToolbar"),
|
container: document.getElementById("floatingToolbar"),
|
||||||
download: document.getElementById("download"),
|
download: document.getElementById("download"),
|
||||||
|
openInApp: document.getElementById("openInApp"),
|
||||||
},
|
},
|
||||||
|
|
||||||
passwordOverlay: {
|
passwordOverlay: {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user