diff options
Diffstat (limited to 'toolkit/components/apppicker/content')
-rw-r--r-- | toolkit/components/apppicker/content/appPicker.js | 226 | ||||
-rw-r--r-- | toolkit/components/apppicker/content/appPicker.xhtml | 56 |
2 files changed, 282 insertions, 0 deletions
diff --git a/toolkit/components/apppicker/content/appPicker.js b/toolkit/components/apppicker/content/appPicker.js new file mode 100644 index 0000000000..dc2a97af8c --- /dev/null +++ b/toolkit/components/apppicker/content/appPicker.js @@ -0,0 +1,226 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const { AppConstants } = ChromeUtils.importESModule( + "resource://gre/modules/AppConstants.sys.mjs" +); + +function AppPicker() {} + +AppPicker.prototype = { + // Class members + _incomingParams: null, + + /** + * Init the dialog and populate the application list + */ + appPickerLoad: function appPickerLoad() { + const nsILocalHandlerApp = Ci.nsILocalHandlerApp; + + document.addEventListener("dialogaccept", function () { + g_dialog.appPickerOK(); + }); + document.addEventListener("dialogcancel", function () { + g_dialog.appPickerCancel(); + }); + document.addEventListener("dialogextra2", function () { + g_dialog.appPickerBrowse(); + }); + + this._incomingParams = window.arguments[0]; + this._incomingParams.handlerApp = null; + + document.title = this._incomingParams.title; + + // Header creation - at the very least, we must have + // a mime type: + // + // (icon) Zip File + // (icon) filename + // + // (icon) Web Feed + // (icon) mime/type + // + // (icon) mime/type + // (icon) + + var mimeInfo = this._incomingParams.mimeInfo; + var filename = this._incomingParams.filename; + if (!filename) { + filename = mimeInfo.MIMEType; + } + var description = this._incomingParams.description; + if (!description) { + description = filename; + filename = ""; + } + + // Setup the dialog header information + document + .getElementById("content-description") + .setAttribute("value", description); + document + .getElementById("suggested-filename") + .setAttribute("value", filename || ""); + document + .getElementById("content-icon") + .setAttribute( + "src", + "moz-icon://" + filename + "?size=32&contentType=" + mimeInfo.MIMEType + ); + + // Grab a list of nsILocalHandlerApp application helpers to list + var fileList = mimeInfo.possibleLocalHandlers; + + var list = document.getElementById("app-picker-listbox"); + + var primaryCount = 0; + + if (!fileList || !fileList.length) { + // display a message saying nothing is configured + document.getElementById("app-picker-notfound").removeAttribute("hidden"); + return; + } + + for (var idx = 0; idx < fileList.length; idx++) { + var file = fileList.queryElementAt(idx, nsILocalHandlerApp); + try { + if (!file.executable || !file.executable.isFile()) { + continue; + } + } catch (err) { + continue; + } + + var item = document.createXULElement("richlistitem"); + item.handlerApp = file; + list.appendChild(item); + + var image = document.createXULElement("image"); + image.setAttribute("src", this.getFileIconURL(file.executable)); + item.appendChild(image); + + var label = document.createXULElement("label"); + label.setAttribute("value", this.getFileDisplayName(file.executable)); + item.appendChild(label); + + primaryCount++; + } + + if (primaryCount == 0) { + // display a message saying nothing is configured + document.getElementById("app-picker-notfound").removeAttribute("hidden"); + } + }, + + /** + * Retrieve the moz-icon for the app + */ + getFileIconURL: function getFileIconURL(file) { + const nsIFileProtocolHandler = Ci.nsIFileProtocolHandler; + + var fph = Services.io + .getProtocolHandler("file") + .QueryInterface(nsIFileProtocolHandler); + if (!fph) { + return ""; + } + + var urlSpec = fph.getURLSpecFromActualFile(file); + return "moz-icon://" + urlSpec + "?size=32"; + }, + + /** + * Retrieve the pretty description from the file + */ + getFileDisplayName: function getFileDisplayName(file) { + if (AppConstants.platform == "win") { + if (file instanceof Ci.nsILocalFileWin) { + try { + return file.getVersionInfoField("FileDescription"); + } catch (e) {} + } + } else if (AppConstants.platform == "macosx") { + if (file instanceof Ci.nsILocalFileMac) { + try { + return file.bundleDisplayName; + } catch (e) {} + } + } + return file.leafName; + }, + + /** + * Double click accepts an app + */ + appDoubleClick: function appDoubleClick() { + var list = document.getElementById("app-picker-listbox"); + var selItem = list.selectedItem; + + if (!selItem) { + this._incomingParams.handlerApp = null; + return true; + } + + this._incomingParams.handlerApp = selItem.handlerApp; + window.close(); + + return true; + }, + + appPickerOK: function appPickerOK() { + if (this._incomingParams.handlerApp) { + return; + } + + var list = document.getElementById("app-picker-listbox"); + var selItem = list.selectedItem; + + if (!selItem) { + this._incomingParams.handlerApp = null; + return; + } + this._incomingParams.handlerApp = selItem.handlerApp; + }, + + appPickerCancel: function appPickerCancel() { + this._incomingParams.handlerApp = null; + }, + + /** + * User browse for an app. + */ + appPickerBrowse: function appPickerBrowse() { + var nsIFilePicker = Ci.nsIFilePicker; + var fp = Cc["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker); + + fp.init(window, this._incomingParams.title, nsIFilePicker.modeOpen); + fp.appendFilters(nsIFilePicker.filterApps); + + var startLocation; + if (AppConstants.platform == "win") { + startLocation = "ProgF"; // Program Files + } else if (AppConstants.platform == "macosx") { + startLocation = "LocApp"; // Local Applications + } else { + startLocation = "Home"; + } + fp.displayDirectory = Services.dirsvc.get(startLocation, Ci.nsIFile); + + fp.open(rv => { + if (rv == nsIFilePicker.returnOK && fp.file) { + var localHandlerApp = Cc[ + "@mozilla.org/uriloader/local-handler-app;1" + ].createInstance(Ci.nsILocalHandlerApp); + localHandlerApp.executable = fp.file; + + this._incomingParams.handlerApp = localHandlerApp; + window.close(); + } + }); + }, +}; + +// Global object +var g_dialog = new AppPicker(); diff --git a/toolkit/components/apppicker/content/appPicker.xhtml b/toolkit/components/apppicker/content/appPicker.xhtml new file mode 100644 index 0000000000..689946220c --- /dev/null +++ b/toolkit/components/apppicker/content/appPicker.xhtml @@ -0,0 +1,56 @@ +<?xml version="1.0"?> + +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?> +<?xml-stylesheet href="chrome://global/skin/appPicker.css" type="text/css"?> + +<!DOCTYPE window> + +<window + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + xmlns:html="http://www.w3.org/1999/xhtml" + onload="g_dialog.appPickerLoad();" + aria-describedby="content-description suggested-filename" + persist="screenX screenY" +> + <dialog + id="app-picker" + buttons="accept,cancel,extra2" + data-l10n-id="app-picker-browse-button" + data-l10n-attrs="buttonlabelextra2" + defaultButton="accept" + > + <linkset> + <html:link rel="localization" href="toolkit/global/appPicker.ftl" /> + </linkset> + <script src="chrome://global/content/appPicker.js" /> + + <hbox id="file-info" align="center"> + <image id="content-icon" src="" /> + <vbox flex="1"> + <label id="content-description" crop="center" value="" /> + <label id="suggested-filename" crop="center" value="" /> + </vbox> + </hbox> + + <label + id="sendto-message" + data-l10n-id="app-picker-send-msg" + control="app-picker-listbox" + /> + + <richlistbox + id="app-picker-listbox" + ondblclick="g_dialog.appDoubleClick();" + /> + + <label + id="app-picker-notfound" + data-l10n-id="app-picker-no-app-found" + hidden="true" + /> + </dialog> +</window> |