michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /** michael@0: * This dialog builds its content based on arguments passed into it. michael@0: * window.arguments[0]: michael@0: * The title of the dialog. michael@0: * window.arguments[1]: michael@0: * The url of the image that appears to the left of the description text michael@0: * window.arguments[2]: michael@0: * The text of the description that will appear above the choices the user michael@0: * can choose from. michael@0: * window.arguments[3]: michael@0: * The text of the label directly above the choices the user can choose from. michael@0: * window.arguments[4]: michael@0: * This is the text to be placed in the label for the checkbox. If no text is michael@0: * passed (ie, it's an empty string), the checkbox will be hidden. michael@0: * window.arguments[5]: michael@0: * The accesskey for the checkbox michael@0: * window.arguments[6]: michael@0: * This is the text that is displayed below the checkbox when it is checked. michael@0: * window.arguments[7]: michael@0: * This is the nsIHandlerInfo that gives us all our precious information. michael@0: * window.arguments[8]: michael@0: * This is the nsIURI that we are being brought up for in the first place. michael@0: * window.arguments[9]: michael@0: * The nsIInterfaceRequestor of the parent window; may be null michael@0: */ michael@0: michael@0: const Cc = Components.classes; michael@0: const Ci = Components.interfaces; michael@0: const Cr = Components.results; michael@0: michael@0: var dialog = { michael@0: ////////////////////////////////////////////////////////////////////////////// michael@0: //// Member Variables michael@0: michael@0: _handlerInfo: null, michael@0: _URI: null, michael@0: _itemChoose: null, michael@0: _okButton: null, michael@0: _windowCtxt: null, michael@0: michael@0: ////////////////////////////////////////////////////////////////////////////// michael@0: //// Methods michael@0: michael@0: /** michael@0: * This function initializes the content of the dialog. michael@0: */ michael@0: initialize: function initialize() michael@0: { michael@0: this._handlerInfo = window.arguments[7].QueryInterface(Ci.nsIHandlerInfo); michael@0: this._URI = window.arguments[8].QueryInterface(Ci.nsIURI); michael@0: this._windowCtxt = window.arguments[9]; michael@0: if (this._windowCtxt) michael@0: this._windowCtxt.QueryInterface(Ci.nsIInterfaceRequestor); michael@0: this._itemChoose = document.getElementById("item-choose"); michael@0: this._okButton = document.documentElement.getButton("accept"); michael@0: michael@0: this.updateOKButton(); michael@0: michael@0: var description = { michael@0: image: document.getElementById("description-image"), michael@0: text: document.getElementById("description-text") michael@0: }; michael@0: var options = document.getElementById("item-action-text"); michael@0: var checkbox = { michael@0: desc: document.getElementById("remember"), michael@0: text: document.getElementById("remember-text") michael@0: }; michael@0: michael@0: // Setting values michael@0: document.title = window.arguments[0]; michael@0: description.image.src = window.arguments[1]; michael@0: description.text.textContent = window.arguments[2]; michael@0: options.value = window.arguments[3]; michael@0: checkbox.desc.label = window.arguments[4]; michael@0: checkbox.desc.accessKey = window.arguments[5]; michael@0: checkbox.text.textContent = window.arguments[6]; michael@0: michael@0: // Hide stuff that needs to be hidden michael@0: if (!checkbox.desc.label) michael@0: checkbox.desc.hidden = true; michael@0: michael@0: // UI is ready, lets populate our list michael@0: this.populateList(); michael@0: }, michael@0: michael@0: /** michael@0: * Populates the list that a user can choose from. michael@0: */ michael@0: populateList: function populateList() michael@0: { michael@0: var items = document.getElementById("items"); michael@0: var possibleHandlers = this._handlerInfo.possibleApplicationHandlers; michael@0: var preferredHandler = this._handlerInfo.preferredApplicationHandler; michael@0: var ios = Cc["@mozilla.org/network/io-service;1"]. michael@0: getService(Ci.nsIIOService); michael@0: for (let i = possibleHandlers.length - 1; i >= 0; --i) { michael@0: let app = possibleHandlers.queryElementAt(i, Ci.nsIHandlerApp); michael@0: let elm = document.createElement("richlistitem"); michael@0: elm.setAttribute("type", "handler"); michael@0: elm.setAttribute("name", app.name); michael@0: elm.obj = app; michael@0: michael@0: if (app instanceof Ci.nsILocalHandlerApp) { michael@0: // See if we have an nsILocalHandlerApp and set the icon michael@0: let uri = ios.newFileURI(app.executable); michael@0: elm.setAttribute("image", "moz-icon://" + uri.spec + "?size=32"); michael@0: } michael@0: else if (app instanceof Ci.nsIWebHandlerApp) { michael@0: let uri = ios.newURI(app.uriTemplate, null, null); michael@0: if (/^https?/.test(uri.scheme)) { michael@0: // Unfortunately we can't use the favicon service to get the favicon, michael@0: // because the service looks for a record with the exact URL we give michael@0: // it, and users won't have such records for URLs they don't visit, michael@0: // and users won't visit the handler's URL template, they'll only michael@0: // visit URLs derived from that template (i.e. with %s in the template michael@0: // replaced by the URL of the content being handled). michael@0: elm.setAttribute("image", uri.prePath + "/favicon.ico"); michael@0: } michael@0: elm.setAttribute("description", uri.prePath); michael@0: } michael@0: else if (app instanceof Ci.nsIDBusHandlerApp){ michael@0: elm.setAttribute("description", app.method); michael@0: } michael@0: else michael@0: throw "unknown handler type"; michael@0: michael@0: items.insertBefore(elm, this._itemChoose); michael@0: if (preferredHandler && app == preferredHandler) michael@0: this.selectedItem = elm; michael@0: } michael@0: michael@0: if (this._handlerInfo.hasDefaultHandler) { michael@0: let elm = document.createElement("richlistitem"); michael@0: elm.setAttribute("type", "handler"); michael@0: elm.id = "os-default-handler"; michael@0: elm.setAttribute("name", this._handlerInfo.defaultDescription); michael@0: michael@0: items.insertBefore(elm, items.firstChild); michael@0: if (this._handlerInfo.preferredAction == michael@0: Ci.nsIHandlerInfo.useSystemDefault) michael@0: this.selectedItem = elm; michael@0: } michael@0: items.ensureSelectedElementIsVisible(); michael@0: }, michael@0: michael@0: /** michael@0: * Brings up a filepicker and allows a user to choose an application. michael@0: */ michael@0: chooseApplication: function chooseApplication() michael@0: { michael@0: var bundle = document.getElementById("base-strings"); michael@0: var title = bundle.getString("choose.application.title"); michael@0: michael@0: var fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker); michael@0: fp.init(window, title, Ci.nsIFilePicker.modeOpen); michael@0: fp.appendFilters(Ci.nsIFilePicker.filterApps); michael@0: michael@0: if (fp.show() == Ci.nsIFilePicker.returnOK && fp.file) { michael@0: let uri = Cc["@mozilla.org/network/util;1"]. michael@0: getService(Ci.nsIIOService). michael@0: newFileURI(fp.file); michael@0: michael@0: let handlerApp = Cc["@mozilla.org/uriloader/local-handler-app;1"]. michael@0: createInstance(Ci.nsILocalHandlerApp); michael@0: handlerApp.executable = fp.file; michael@0: michael@0: // if this application is already in the list, select it and don't add it again michael@0: let parent = document.getElementById("items"); michael@0: for (let i = 0; i < parent.childNodes.length; ++i) { michael@0: let elm = parent.childNodes[i]; michael@0: if (elm.obj instanceof Ci.nsILocalHandlerApp && elm.obj.equals(handlerApp)) { michael@0: parent.selectedItem = elm; michael@0: parent.ensureSelectedElementIsVisible(); michael@0: return; michael@0: } michael@0: } michael@0: michael@0: let elm = document.createElement("richlistitem"); michael@0: elm.setAttribute("type", "handler"); michael@0: elm.setAttribute("name", fp.file.leafName); michael@0: elm.setAttribute("image", "moz-icon://" + uri.spec + "?size=32"); michael@0: elm.obj = handlerApp; michael@0: michael@0: parent.selectedItem = parent.insertBefore(elm, parent.firstChild); michael@0: parent.ensureSelectedElementIsVisible(); michael@0: } michael@0: }, michael@0: michael@0: /** michael@0: * Function called when the OK button is pressed. michael@0: */ michael@0: onAccept: function onAccept() michael@0: { michael@0: var checkbox = document.getElementById("remember"); michael@0: if (!checkbox.hidden) { michael@0: // We need to make sure that the default is properly set now michael@0: if (this.selectedItem.obj) { michael@0: // default OS handler doesn't have this property michael@0: this._handlerInfo.preferredAction = Ci.nsIHandlerInfo.useHelperApp; michael@0: this._handlerInfo.preferredApplicationHandler = this.selectedItem.obj; michael@0: } michael@0: else michael@0: this._handlerInfo.preferredAction = Ci.nsIHandlerInfo.useSystemDefault; michael@0: } michael@0: this._handlerInfo.alwaysAskBeforeHandling = !checkbox.checked; michael@0: michael@0: var hs = Cc["@mozilla.org/uriloader/handler-service;1"]. michael@0: getService(Ci.nsIHandlerService); michael@0: hs.store(this._handlerInfo); michael@0: michael@0: this._handlerInfo.launchWithURI(this._URI, this._windowCtxt); michael@0: michael@0: return true; michael@0: }, michael@0: michael@0: /** michael@0: * Determines if the OK button should be disabled or not michael@0: */ michael@0: updateOKButton: function updateOKButton() michael@0: { michael@0: this._okButton.disabled = this._itemChoose.selected; michael@0: }, michael@0: michael@0: /** michael@0: * Updates the UI based on the checkbox being checked or not. michael@0: */ michael@0: onCheck: function onCheck() michael@0: { michael@0: if (document.getElementById("remember").checked) michael@0: document.getElementById("remember-text").setAttribute("visible", "true"); michael@0: else michael@0: document.getElementById("remember-text").removeAttribute("visible"); michael@0: }, michael@0: michael@0: /** michael@0: * Function called when the user double clicks on an item of the list michael@0: */ michael@0: onDblClick: function onDblClick() michael@0: { michael@0: if (this.selectedItem == this._itemChoose) michael@0: this.chooseApplication(); michael@0: else michael@0: document.documentElement.acceptDialog(); michael@0: }, michael@0: michael@0: ///////////////////////////////////////////////////////////////////////////// michael@0: //// Getters / Setters michael@0: michael@0: /** michael@0: * Returns/sets the selected element in the richlistbox michael@0: */ michael@0: get selectedItem() michael@0: { michael@0: return document.getElementById("items").selectedItem; michael@0: }, michael@0: set selectedItem(aItem) michael@0: { michael@0: return document.getElementById("items").selectedItem = aItem; michael@0: } michael@0: michael@0: };