Wed, 31 Dec 2014 07:22:50 +0100
Correct previous dual key logic pending first delivery installment.
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 function run_test() {
6 //**************************************************************************//
7 // Constants
9 const handlerSvc = Cc["@mozilla.org/uriloader/handler-service;1"].
10 getService(Ci.nsIHandlerService);
12 const mimeSvc = Cc["@mozilla.org/mime;1"].
13 getService(Ci.nsIMIMEService);
15 const protoSvc = Cc["@mozilla.org/uriloader/external-protocol-service;1"].
16 getService(Ci.nsIExternalProtocolService);
18 const prefSvc = Cc["@mozilla.org/preferences-service;1"].
19 getService(Ci.nsIPrefService);
21 const ioService = Cc["@mozilla.org/network/io-service;1"].
22 getService(Ci.nsIIOService);
24 const env = Cc["@mozilla.org/process/environment;1"].
25 getService(Components.interfaces.nsIEnvironment);
27 const rootPrefBranch = prefSvc.getBranch("");
29 let noMailto = false;
30 let isWindows = ("@mozilla.org/windows-registry-key;1" in Components.classes);
31 if (isWindows) {
32 // Check mailto handler from registry.
33 // If registry entry is nothing, no mailto handler
34 let regSvc = Cc["@mozilla.org/windows-registry-key;1"].
35 createInstance(Ci.nsIWindowsRegKey);
36 try {
37 regSvc.open(regSvc.ROOT_KEY_CLASSES_ROOT,
38 "mailto",
39 regSvc.ACCESS_READ);
40 noMailto = false;
41 } catch (ex) {
42 noMailto = true;
43 }
44 regSvc.close();
45 }
47 //**************************************************************************//
48 // Sample Data
50 // It doesn't matter whether or not this nsIFile is actually executable,
51 // only that it has a path and exists. Since we don't know any executable
52 // that exists on all platforms (except possibly the application being
53 // tested, but there doesn't seem to be a way to get a reference to that
54 // from the directory service), we use the temporary directory itself.
55 var executable = HandlerServiceTest._dirSvc.get("TmpD", Ci.nsIFile);
56 // XXX We could, of course, create an actual executable in the directory:
57 //executable.append("localhandler");
58 //if (!executable.exists())
59 // executable.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0755);
61 var localHandler = {
62 name: "Local Handler",
63 executable: executable,
64 interfaces: [Ci.nsIHandlerApp, Ci.nsILocalHandlerApp, Ci.nsISupports],
65 QueryInterface: function(iid) {
66 if (!this.interfaces.some( function(v) { return iid.equals(v) } ))
67 throw Cr.NS_ERROR_NO_INTERFACE;
68 return this;
69 }
70 };
72 var webHandler = Cc["@mozilla.org/uriloader/web-handler-app;1"].
73 createInstance(Ci.nsIWebHandlerApp);
74 webHandler.name = "Web Handler";
75 webHandler.uriTemplate = "http://www.example.com/?%s";
77 // FIXME: these tests create and manipulate enough variables that it would
78 // make sense to move each test into its own scope so we don't run the risk
79 // of one test stomping on another's data.
82 //**************************************************************************//
83 // Test Default Properties
85 // Get a handler info for a MIME type that neither the application nor
86 // the OS knows about and make sure its properties are set to the proper
87 // default values.
89 var handlerInfo = mimeSvc.getFromTypeAndExtension("nonexistent/type", null);
91 // Make sure it's also an nsIHandlerInfo.
92 do_check_true(handlerInfo instanceof Ci.nsIHandlerInfo);
94 do_check_eq(handlerInfo.type, "nonexistent/type");
96 // Deprecated property, but we should still make sure it's set correctly.
97 do_check_eq(handlerInfo.MIMEType, "nonexistent/type");
99 // These properties are the ones the handler service knows how to store.
100 do_check_eq(handlerInfo.preferredAction, Ci.nsIHandlerInfo.saveToDisk);
101 do_check_eq(handlerInfo.preferredApplicationHandler, null);
102 do_check_eq(handlerInfo.possibleApplicationHandlers.length, 0);
103 do_check_true(handlerInfo.alwaysAskBeforeHandling);
105 // These properties are initialized to default values by the service,
106 // so we might as well make sure they're initialized to the right defaults.
107 do_check_eq(handlerInfo.description, "");
108 do_check_eq(handlerInfo.hasDefaultHandler, false);
109 do_check_eq(handlerInfo.defaultDescription, "");
111 // test some default protocol info properties
112 var haveDefaultHandlersVersion = false;
113 try {
114 // If we have a defaultHandlersVersion pref, then assume that we're in the
115 // firefox tree and that we'll also have default handlers.
116 // Bug 395131 has been filed to make this test work more generically
117 // by providing our own prefs for this test rather than this icky
118 // special casing.
119 rootPrefBranch.getCharPref("gecko.handlerService.defaultHandlersVersion");
120 haveDefaultHandlersVersion = true;
121 } catch (ex) {}
123 const kExternalWarningDefault =
124 "network.protocol-handler.warn-external-default";
125 prefSvc.setBoolPref(kExternalWarningDefault, true);
127 // XXX add more thorough protocol info property checking
129 // no OS default handler exists
130 var protoInfo = protoSvc.getProtocolHandlerInfo("x-moz-rheet");
131 do_check_eq(protoInfo.preferredAction, protoInfo.alwaysAsk);
132 do_check_true(protoInfo.alwaysAskBeforeHandling);
134 // OS default exists, injected default does not exist,
135 // explicit warning pref: false
136 const kExternalWarningPrefPrefix = "network.protocol-handler.warn-external.";
137 prefSvc.setBoolPref(kExternalWarningPrefPrefix + "http", false);
138 protoInfo = protoSvc.getProtocolHandlerInfo("http");
139 do_check_eq(0, protoInfo.possibleApplicationHandlers.length);
140 do_check_false(protoInfo.alwaysAskBeforeHandling);
142 // OS default exists, injected default does not exist,
143 // explicit warning pref: true
144 prefSvc.setBoolPref(kExternalWarningPrefPrefix + "http", true);
145 protoInfo = protoSvc.getProtocolHandlerInfo("http");
146 // OS handler isn't included in possibleApplicationHandlers, so length is 0
147 // Once they become instances of nsILocalHandlerApp, this number will need
148 // to change.
149 do_check_eq(0, protoInfo.possibleApplicationHandlers.length);
150 do_check_true(protoInfo.alwaysAskBeforeHandling);
152 // OS default exists, injected default exists, explicit warning pref: false
153 prefSvc.setBoolPref(kExternalWarningPrefPrefix + "mailto", false);
154 protoInfo = protoSvc.getProtocolHandlerInfo("mailto");
155 if (haveDefaultHandlersVersion)
156 do_check_eq(2, protoInfo.possibleApplicationHandlers.length);
157 else
158 do_check_eq(0, protoInfo.possibleApplicationHandlers.length);
160 // Win7+ might not have a default mailto: handler
161 if (noMailto)
162 do_check_true(protoInfo.alwaysAskBeforeHandling);
163 else
164 do_check_false(protoInfo.alwaysAskBeforeHandling);
166 // OS default exists, injected default exists, explicit warning pref: true
167 prefSvc.setBoolPref(kExternalWarningPrefPrefix + "mailto", true);
168 protoInfo = protoSvc.getProtocolHandlerInfo("mailto");
169 if (haveDefaultHandlersVersion) {
170 do_check_eq(2, protoInfo.possibleApplicationHandlers.length);
171 // Win7+ might not have a default mailto: handler, but on other platforms
172 // alwaysAskBeforeHandling is expected to be false here, because although
173 // the pref is true, the value in RDF is false. The injected mailto handler
174 // carried over the default pref value, and so when we set the pref above
175 // to true it's ignored.
176 if (noMailto)
177 do_check_true(protoInfo.alwaysAskBeforeHandling);
178 else
179 do_check_false(protoInfo.alwaysAskBeforeHandling);
181 } else {
182 do_check_eq(0, protoInfo.possibleApplicationHandlers.length);
183 do_check_true(protoInfo.alwaysAskBeforeHandling);
184 }
186 if (haveDefaultHandlersVersion) {
187 // Now set the value stored in RDF to true, and the pref to false, to make
188 // sure we still get the right value. (Basically, same thing as above but
189 // with the values reversed.)
190 prefSvc.setBoolPref(kExternalWarningPrefPrefix + "mailto", false);
191 protoInfo.alwaysAskBeforeHandling = true;
192 handlerSvc.store(protoInfo);
193 protoInfo = protoSvc.getProtocolHandlerInfo("mailto");
194 do_check_eq(2, protoInfo.possibleApplicationHandlers.length);
195 do_check_true(protoInfo.alwaysAskBeforeHandling);
196 }
199 //**************************************************************************//
200 // Test Round-Trip Data Integrity
202 // Test round-trip data integrity by setting the properties of the handler
203 // info object to different values, telling the handler service to store the
204 // object, and then retrieving a new info object for the same type and making
205 // sure its properties are identical.
207 handlerInfo.preferredAction = Ci.nsIHandlerInfo.useHelperApp;
208 handlerInfo.preferredApplicationHandler = localHandler;
209 handlerInfo.alwaysAskBeforeHandling = false;
211 handlerSvc.store(handlerInfo);
213 handlerInfo = mimeSvc.getFromTypeAndExtension("nonexistent/type", null);
215 do_check_eq(handlerInfo.preferredAction, Ci.nsIHandlerInfo.useHelperApp);
217 do_check_neq(handlerInfo.preferredApplicationHandler, null);
218 var preferredHandler = handlerInfo.preferredApplicationHandler;
219 do_check_eq(typeof preferredHandler, "object");
220 do_check_eq(preferredHandler.name, "Local Handler");
221 do_check_true(preferredHandler instanceof Ci.nsILocalHandlerApp);
222 preferredHandler.QueryInterface(Ci.nsILocalHandlerApp);
223 do_check_eq(preferredHandler.executable.path, localHandler.executable.path);
225 do_check_false(handlerInfo.alwaysAskBeforeHandling);
227 // Make sure the handler service's enumerate method lists all known handlers.
228 var handlerInfo2 = mimeSvc.getFromTypeAndExtension("nonexistent/type2", null);
229 handlerSvc.store(handlerInfo2);
230 var handlerTypes = ["nonexistent/type", "nonexistent/type2"];
231 if (haveDefaultHandlersVersion) {
232 handlerTypes.push("webcal");
233 handlerTypes.push("mailto");
234 handlerTypes.push("irc");
235 handlerTypes.push("ircs");
236 }
237 var handlers = handlerSvc.enumerate();
238 while (handlers.hasMoreElements()) {
239 var handler = handlers.getNext().QueryInterface(Ci.nsIHandlerInfo);
240 do_check_neq(handlerTypes.indexOf(handler.type), -1);
241 handlerTypes.splice(handlerTypes.indexOf(handler.type), 1);
242 }
243 do_check_eq(handlerTypes.length, 0);
245 // Make sure the handler service's remove method removes a handler record.
246 handlerSvc.remove(handlerInfo2);
247 handlers = handlerSvc.enumerate();
248 while (handlers.hasMoreElements())
249 do_check_neq(handlers.getNext().QueryInterface(Ci.nsIHandlerInfo).type,
250 handlerInfo2.type);
252 // Make sure we can store and retrieve a handler info object with no preferred
253 // handler.
254 var noPreferredHandlerInfo =
255 mimeSvc.getFromTypeAndExtension("nonexistent/no-preferred-handler", null);
256 handlerSvc.store(noPreferredHandlerInfo);
257 noPreferredHandlerInfo =
258 mimeSvc.getFromTypeAndExtension("nonexistent/no-preferred-handler", null);
259 do_check_eq(noPreferredHandlerInfo.preferredApplicationHandler, null);
261 // Make sure that the handler service removes an existing handler record
262 // if we store a handler info object with no preferred handler.
263 var removePreferredHandlerInfo =
264 mimeSvc.getFromTypeAndExtension("nonexistent/rem-preferred-handler", null);
265 removePreferredHandlerInfo.preferredApplicationHandler = localHandler;
266 handlerSvc.store(removePreferredHandlerInfo);
267 removePreferredHandlerInfo =
268 mimeSvc.getFromTypeAndExtension("nonexistent/rem-preferred-handler", null);
269 removePreferredHandlerInfo.preferredApplicationHandler = null;
270 handlerSvc.store(removePreferredHandlerInfo);
271 removePreferredHandlerInfo =
272 mimeSvc.getFromTypeAndExtension("nonexistent/rem-preferred-handler", null);
273 do_check_eq(removePreferredHandlerInfo.preferredApplicationHandler, null);
275 // Make sure we can store and retrieve a handler info object with possible
276 // handlers. We test both adding and removing handlers.
278 // Get a handler info and make sure it has no possible handlers.
279 var possibleHandlersInfo =
280 mimeSvc.getFromTypeAndExtension("nonexistent/possible-handlers", null);
281 do_check_eq(possibleHandlersInfo.possibleApplicationHandlers.length, 0);
283 // Store and re-retrieve the handler and make sure it still has no possible
284 // handlers.
285 handlerSvc.store(possibleHandlersInfo);
286 possibleHandlersInfo =
287 mimeSvc.getFromTypeAndExtension("nonexistent/possible-handlers", null);
288 do_check_eq(possibleHandlersInfo.possibleApplicationHandlers.length, 0);
290 // Add two handlers, store the object, re-retrieve it, and make sure it has
291 // two handlers.
292 possibleHandlersInfo.possibleApplicationHandlers.appendElement(localHandler,
293 false);
294 possibleHandlersInfo.possibleApplicationHandlers.appendElement(webHandler,
295 false);
296 handlerSvc.store(possibleHandlersInfo);
297 possibleHandlersInfo =
298 mimeSvc.getFromTypeAndExtension("nonexistent/possible-handlers", null);
299 do_check_eq(possibleHandlersInfo.possibleApplicationHandlers.length, 2);
301 // Figure out which is the local and which is the web handler and the index
302 // in the array of the local handler, which is the one we're going to remove
303 // to test removal of a handler.
304 var handler1 = possibleHandlersInfo.possibleApplicationHandlers.
305 queryElementAt(0, Ci.nsIHandlerApp);
306 var handler2 = possibleHandlersInfo.possibleApplicationHandlers.
307 queryElementAt(1, Ci.nsIHandlerApp);
308 var localPossibleHandler, webPossibleHandler, localIndex;
309 if (handler1 instanceof Ci.nsILocalHandlerApp)
310 [localPossibleHandler, webPossibleHandler, localIndex] = [handler1,
311 handler2,
312 0];
313 else
314 [localPossibleHandler, webPossibleHandler, localIndex] = [handler2,
315 handler1,
316 1];
317 localPossibleHandler.QueryInterface(Ci.nsILocalHandlerApp);
318 webPossibleHandler.QueryInterface(Ci.nsIWebHandlerApp);
320 // Make sure the two handlers are the ones we stored.
321 do_check_eq(localPossibleHandler.name, localHandler.name);
322 do_check_true(localPossibleHandler.equals(localHandler));
323 do_check_eq(webPossibleHandler.name, webHandler.name);
324 do_check_true(webPossibleHandler.equals(webHandler));
326 // Remove a handler, store the object, re-retrieve it, and make sure
327 // it only has one handler.
328 possibleHandlersInfo.possibleApplicationHandlers.removeElementAt(localIndex);
329 handlerSvc.store(possibleHandlersInfo);
330 possibleHandlersInfo =
331 mimeSvc.getFromTypeAndExtension("nonexistent/possible-handlers", null);
332 do_check_eq(possibleHandlersInfo.possibleApplicationHandlers.length, 1);
334 // Make sure the handler is the one we didn't remove.
335 webPossibleHandler = possibleHandlersInfo.possibleApplicationHandlers.
336 queryElementAt(0, Ci.nsIWebHandlerApp);
337 do_check_eq(webPossibleHandler.name, webHandler.name);
338 do_check_true(webPossibleHandler.equals(webHandler));
340 //////////////////////////////////////////////////////
341 // handler info command line parameters and equality
342 var localApp = Cc["@mozilla.org/uriloader/local-handler-app;1"].
343 createInstance(Ci.nsILocalHandlerApp);
344 var handlerApp = localApp.QueryInterface(Ci.nsIHandlerApp);
346 do_check_true(handlerApp.equals(localApp));
348 localApp.executable = executable;
350 do_check_eq(0, localApp.parameterCount);
351 localApp.appendParameter("-test1");
352 do_check_eq(1, localApp.parameterCount);
353 localApp.appendParameter("-test2");
354 do_check_eq(2, localApp.parameterCount);
355 do_check_true(localApp.parameterExists("-test1"));
356 do_check_true(localApp.parameterExists("-test2"));
357 do_check_false(localApp.parameterExists("-false"));
358 localApp.clearParameters();
359 do_check_eq(0, localApp.parameterCount);
361 var localApp2 = Cc["@mozilla.org/uriloader/local-handler-app;1"].
362 createInstance(Ci.nsILocalHandlerApp);
364 localApp2.executable = executable;
366 localApp.clearParameters();
367 do_check_true(localApp.equals(localApp2));
369 // equal:
370 // cut -d 1 -f 2
371 // cut -d 1 -f 2
373 localApp.appendParameter("-test1");
374 localApp.appendParameter("-test2");
375 localApp.appendParameter("-test3");
376 localApp2.appendParameter("-test1");
377 localApp2.appendParameter("-test2");
378 localApp2.appendParameter("-test3");
379 do_check_true(localApp.equals(localApp2));
381 // not equal:
382 // cut -d 1 -f 2
383 // cut -f 1 -d 2
385 localApp.clearParameters();
386 localApp2.clearParameters();
388 localApp.appendParameter("-test1");
389 localApp.appendParameter("-test2");
390 localApp.appendParameter("-test3");
391 localApp2.appendParameter("-test2");
392 localApp2.appendParameter("-test1");
393 localApp2.appendParameter("-test3");
394 do_check_false(localApp2.equals(localApp));
396 var str;
397 str = localApp.getParameter(0)
398 do_check_eq(str, "-test1");
399 str = localApp.getParameter(1)
400 do_check_eq(str, "-test2");
401 str = localApp.getParameter(2)
402 do_check_eq(str, "-test3");
404 // FIXME: test round trip integrity for a protocol.
405 // FIXME: test round trip integrity for a handler info with a web handler.
407 //**************************************************************************//
408 // getTypeFromExtension tests
410 // test nonexistent extension
411 var lolType = handlerSvc.getTypeFromExtension("lolcat");
412 do_check_eq(lolType, "");
415 // add a handler for the extension
416 var lolHandler = mimeSvc.getFromTypeAndExtension("application/lolcat", null);
418 do_check_false(lolHandler.extensionExists("lolcat"));
419 lolHandler.preferredAction = Ci.nsIHandlerInfo.useHelperApp;
420 lolHandler.preferredApplicationHandler = localHandler;
421 lolHandler.alwaysAskBeforeHandling = false;
423 // store the handler
424 do_check_false(handlerSvc.exists(lolHandler));
425 handlerSvc.store(lolHandler);
426 do_check_true(handlerSvc.exists(lolHandler));
428 // Get a file:// string pointing to mimeTypes.rdf
429 var rdfFile = HandlerServiceTest._dirSvc.get("UMimTyp", Ci.nsIFile);
430 var fileHandler = ioService.getProtocolHandler("file").QueryInterface(Ci.nsIFileProtocolHandler);
431 var rdfFileURI = fileHandler.getURLSpecFromFile(rdfFile);
433 // Assign a file extenstion to the handler. handlerSvc.store() doesn't
434 // actually store any file extensions added with setFileExtensions(), you
435 // have to wade into RDF muck to do so.
437 // Based on toolkit/mozapps/downloads/content/helperApps.js :: addExtension()
438 var gRDF = Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService);
439 var mimeSource = gRDF.GetUnicodeResource("urn:mimetype:application/lolcat");
440 var valueProperty = gRDF.GetUnicodeResource("http://home.netscape.com/NC-rdf#fileExtensions");
441 var mimeLiteral = gRDF.GetLiteral("lolcat");
443 var DS = gRDF.GetDataSourceBlocking(rdfFileURI);
444 DS.Assert(mimeSource, valueProperty, mimeLiteral, true);
447 // test now-existent extension
448 lolType = handlerSvc.getTypeFromExtension("lolcat");
449 do_check_eq(lolType, "application/lolcat");
451 if (env.get("PERSONAL_MAILCAP")) {
452 handlerInfo = mimeSvc.getFromTypeAndExtension("text/plain", null);
453 do_check_eq(handlerInfo.preferredAction, Ci.nsIHandlerInfo.useSystemDefault);
454 do_check_eq(handlerInfo.defaultDescription, "sed");
455 }
456 }