!import
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3 *
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
8 *
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
13 *
14 * The Original Code is the Protocol Handler Dialog.
15 *
16 * The Initial Developer of the Original Code is
17 * Mozilla Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 2007
19 * the Initial Developer. All Rights Reserved.
20 *
21 * Contributor(s):
22 * Shawn Wilsher <me@shawnwilsher.com> (original author)
23 * Dan Mosedale <dmose@mozilla.org>
24 * Florian Queze <florian@queze.net>
25 *
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
37 *
38 * ***** END LICENSE BLOCK ***** */
39
40 /**
41 * This dialog builds its content based on arguments passed into it.
42 * window.arguments[0]:
43 * The title of the dialog.
44 * window.arguments[1]:
45 * The url of the image that appears to the left of the description text
46 * window.arguments[2]:
47 * The text of the description that will appear above the choices the user
48 * can choose from.
49 * window.arguments[3]:
50 * The text of the label directly above the choices the user can choose from.
51 * window.arguments[4]:
52 * This is the text to be placed in the label for the checkbox. If no text is
53 * passed (ie, it's an empty string), the checkbox will be hidden.
54 * window.arguments[5]:
55 * The accesskey for the checkbox
56 * window.arguments[6]:
57 * This is the text that is displayed below the checkbox when it is checked.
58 * window.arguments[7]:
59 * This is the nsIHandlerInfo that gives us all our precious information.
60 * window.arguments[8]:
61 * This is the nsIURI that we are being brought up for in the first place.
62 * window.arguments[9]:
63 * The nsIInterfaceRequestor of the parent window; may be null
64 */
65
66 const Cc = Components.classes;
67 const Ci = Components.interfaces;
68 const Cr = Components.results;
69
70 var dialog = {
71 //////////////////////////////////////////////////////////////////////////////
72 //// Member Variables
73
74 _handlerInfo: null,
75 _URI: null,
76 _itemChoose: null,
77 _okButton: null,
78 _windowCtxt: null,
79
80 //////////////////////////////////////////////////////////////////////////////
81 //// Methods
82
83 /**
84 * This function initializes the content of the dialog.
85 */
initialize
86 initialize: function initialize()
87 {
88 this._handlerInfo = window.arguments[7].QueryInterface(Ci.nsIHandlerInfo);
89 this._URI = window.arguments[8].QueryInterface(Ci.nsIURI);
90 this._windowCtxt = window.arguments[9];
91 if (this._windowCtxt)
92 this._windowCtxt.QueryInterface(Ci.nsIInterfaceRequestor);
93 this._itemChoose = document.getElementById("item-choose");
94 this._okButton = document.documentElement.getButton("accept");
95
96 this.updateOKButton();
97
98 var description = {
99 image: document.getElementById("description-image"),
100 text: document.getElementById("description-text")
101 };
102 var options = document.getElementById("item-action-text");
103 var checkbox = {
104 desc: document.getElementById("remember"),
105 text: document.getElementById("remember-text")
106 };
107
108 // Setting values
109 document.title = window.arguments[0];
110 description.image.src = window.arguments[1];
111 description.text.textContent = window.arguments[2];
112 options.value = window.arguments[3];
113 checkbox.desc.label = window.arguments[4];
114 checkbox.desc.accessKey = window.arguments[5];
115 checkbox.text.textContent = window.arguments[6];
116
117 // Hide stuff that needs to be hidden
118 if (!checkbox.desc.label)
119 checkbox.desc.hidden = true;
120
121 // UI is ready, lets populate our list
122 this.populateList();
123 },
124
125 /**
126 * Populates the list that a user can choose from.
127 */
populateList
128 populateList: function populateList()
129 {
130 var items = document.getElementById("items");
131 var possibleHandlers = this._handlerInfo.possibleApplicationHandlers;
132 var preferredHandler = this._handlerInfo.preferredApplicationHandler;
133 var ios = Cc["@mozilla.org/network/io-service;1"].
134 getService(Ci.nsIIOService);
135 for (let i = possibleHandlers.length - 1; i >= 0; --i) {
136 let app = possibleHandlers.queryElementAt(i, Ci.nsIHandlerApp);
137 let elm = document.createElement("richlistitem");
138 elm.setAttribute("type", "handler");
139 elm.setAttribute("name", app.name);
140 elm.obj = app;
141
142 if (app instanceof Ci.nsILocalHandlerApp) {
143 // See if we have an nsILocalHandlerApp and set the icon
144 let uri = ios.newFileURI(app.executable);
145 elm.setAttribute("image", "moz-icon://" + uri.spec + "?size=32");
146 }
147 else if (app instanceof Ci.nsIWebHandlerApp) {
148 let uri = ios.newURI(app.uriTemplate, null, null);
149 if (/^https?/.test(uri.scheme)) {
150 let iconURI;
151 try {
152 iconURI = Cc["@mozilla.org/browser/favicon-service;1"].
153 getService(Ci.nsIFaviconService).
154 getFaviconForPage(ios.newURI(uri.prePath, null, null)).
155 spec;
156 }
157 catch (e) {
158 iconURI = uri.prePath + "/favicon.ico";
159 }
160 elm.setAttribute("image", iconURI);
161 }
162 elm.setAttribute("description", uri.prePath);
163 }
164 else
165 throw "unknown handler type";
166
167 items.insertBefore(elm, this._itemChoose);
168 if (preferredHandler && app == preferredHandler)
169 this.selectedItem = elm;
170 }
171
172 if (this._handlerInfo.hasDefaultHandler) {
173 let elm = document.createElement("richlistitem");
174 elm.setAttribute("type", "handler");
175 elm.id = "os-default-handler";
176 elm.setAttribute("name", this._handlerInfo.defaultDescription);
177
178 items.insertBefore(elm, items.firstChild);
179 if (this._handlerInfo.preferredAction ==
180 Ci.nsIHandlerInfo.useSystemDefault)
181 this.selectedItem = elm;
182 }
183 items.ensureSelectedElementIsVisible();
184 },
185
186 /**
187 * Brings up a filepicker and allows a user to choose an application.
188 */
chooseApplication
189 chooseApplication: function chooseApplication()
190 {
191 var bundle = document.getElementById("base-strings");
192 var title = bundle.getString("choose.application.title");
193
194 var fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
195 fp.init(window, title, Ci.nsIFilePicker.modeOpen);
196 fp.appendFilters(Ci.nsIFilePicker.filterApps);
197
198 if (fp.show() == Ci.nsIFilePicker.returnOK && fp.file) {
199 let uri = Cc["@mozilla.org/network/util;1"].
200 getService(Ci.nsIIOService).
201 newFileURI(fp.file);
202
203 let handlerApp = Cc["@mozilla.org/uriloader/local-handler-app;1"].
204 createInstance(Ci.nsILocalHandlerApp);
205 handlerApp.executable = fp.file;
206
207 // if this application is already in the list, select it and don't add it again
208 let parent = document.getElementById("items");
209 for (let i = 0; i < parent.childNodes.length; ++i) {
210 let elm = parent.childNodes[i];
211 if (elm.obj instanceof Ci.nsILocalHandlerApp && elm.obj.equals(handlerApp)) {
212 parent.selectedItem = elm;
213 parent.ensureSelectedElementIsVisible();
214 return;
215 }
216 }
217
218 let elm = document.createElement("richlistitem");
219 elm.setAttribute("type", "handler");
220 elm.setAttribute("name", fp.file.leafName);
221 elm.setAttribute("image", "moz-icon://" + uri.spec + "?size=32");
222 elm.obj = handlerApp;
223
224 parent.selectedItem = parent.insertBefore(elm, parent.firstChild);
225 parent.ensureSelectedElementIsVisible();
226 }
227 },
228
229 /**
230 * Function called when the OK button is pressed.
231 */
onAccept
232 onAccept: function onAccept()
233 {
234 var checkbox = document.getElementById("remember");
235 if (!checkbox.hidden) {
236 // We need to make sure that the default is properly set now
237 if (this.selectedItem.obj) {
238 // default OS handler doesn't have this property
239 this._handlerInfo.preferredAction = Ci.nsIHandlerInfo.useHelperApp;
240 this._handlerInfo.preferredApplicationHandler = this.selectedItem.obj;
241 }
242 else
243 this._handlerInfo.preferredAction = Ci.nsIHandlerInfo.useSystemDefault;
244 }
245 this._handlerInfo.alwaysAskBeforeHandling = !checkbox.checked;
246
247 var hs = Cc["@mozilla.org/uriloader/handler-service;1"].
248 getService(Ci.nsIHandlerService);
249 hs.store(this._handlerInfo);
250
251 this._handlerInfo.launchWithURI(this._URI, this._windowCtxt);
252
253 return true;
254 },
255
256 /**
257 * Determines if the OK button should be disabled or not
258 */
updateOKButton
259 updateOKButton: function updateOKButton()
260 {
261 this._okButton.disabled = this._itemChoose.selected;
262 },
263
264 /**
265 * Updates the UI based on the checkbox being checked or not.
266 */
onCheck
267 onCheck: function onCheck()
268 {
269 if (document.getElementById("remember").checked)
270 document.getElementById("remember-text").setAttribute("visible", "true");
271 else
272 document.getElementById("remember-text").removeAttribute("visible");
273 },
274
275 /**
276 * Function called when the user double clicks on an item of the list
277 */
onDblClick
278 onDblClick: function onDblClick()
279 {
280 if (this.selectedItem == this._itemChoose)
281 this.chooseApplication();
282 else
283 document.documentElement.acceptDialog();
284 },
285
286 /////////////////////////////////////////////////////////////////////////////
287 //// Getters / Setters
288
289 /**
290 * Returns/sets the selected element in the richlistbox
291 */
get_selectedItem
292 get selectedItem()
293 {
294 return document.getElementById("items").selectedItem;
295 },
set_selectedItem
296 set selectedItem(aItem)
297 {
298 return document.getElementById("items").selectedItem = aItem;
299 }
300
301 };