summaryrefslogtreecommitdiffstats
path: root/uriloader/exthandler/tests/unit/test_handlerService.js
diff options
context:
space:
mode:
Diffstat (limited to 'uriloader/exthandler/tests/unit/test_handlerService.js')
-rw-r--r--uriloader/exthandler/tests/unit/test_handlerService.js470
1 files changed, 470 insertions, 0 deletions
diff --git a/uriloader/exthandler/tests/unit/test_handlerService.js b/uriloader/exthandler/tests/unit/test_handlerService.js
new file mode 100644
index 000000000..3facc63ae
--- /dev/null
+++ b/uriloader/exthandler/tests/unit/test_handlerService.js
@@ -0,0 +1,470 @@
+/* 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/. */
+
+function run_test() {
+ //**************************************************************************//
+ // Constants
+
+ const handlerSvc = Cc["@mozilla.org/uriloader/handler-service;1"].
+ getService(Ci.nsIHandlerService);
+
+ const mimeSvc = Cc["@mozilla.org/mime;1"].
+ getService(Ci.nsIMIMEService);
+
+ const protoSvc = Cc["@mozilla.org/uriloader/external-protocol-service;1"].
+ getService(Ci.nsIExternalProtocolService);
+
+ const prefSvc = Cc["@mozilla.org/preferences-service;1"].
+ getService(Ci.nsIPrefService);
+
+ const ioService = Cc["@mozilla.org/network/io-service;1"].
+ getService(Ci.nsIIOService);
+
+ const env = Cc["@mozilla.org/process/environment;1"].
+ getService(Components.interfaces.nsIEnvironment);
+
+ const rootPrefBranch = prefSvc.getBranch("");
+
+ let noMailto = false;
+ if (mozinfo.os == "win") {
+ // Check mailto handler from registry.
+ // If registry entry is nothing, no mailto handler
+ let regSvc = Cc["@mozilla.org/windows-registry-key;1"].
+ createInstance(Ci.nsIWindowsRegKey);
+ try {
+ regSvc.open(regSvc.ROOT_KEY_CLASSES_ROOT,
+ "mailto",
+ regSvc.ACCESS_READ);
+ noMailto = false;
+ } catch (ex) {
+ noMailto = true;
+ }
+ regSvc.close();
+ }
+
+ if (mozinfo.os == "linux") {
+ // Check mailto handler from GIO
+ // If there isn't one, then we have no mailto handler
+ let gIOSvc = Cc["@mozilla.org/gio-service;1"].
+ createInstance(Ci.nsIGIOService);
+ try {
+ gIOSvc.getAppForURIScheme("mailto");
+ noMailto = false;
+ } catch (ex) {
+ noMailto = true;
+ }
+ }
+
+ //**************************************************************************//
+ // Sample Data
+
+ // It doesn't matter whether or not this nsIFile is actually executable,
+ // only that it has a path and exists. Since we don't know any executable
+ // that exists on all platforms (except possibly the application being
+ // tested, but there doesn't seem to be a way to get a reference to that
+ // from the directory service), we use the temporary directory itself.
+ var executable = HandlerServiceTest._dirSvc.get("TmpD", Ci.nsIFile);
+ // XXX We could, of course, create an actual executable in the directory:
+ //executable.append("localhandler");
+ //if (!executable.exists())
+ // executable.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o755);
+
+ var localHandler = {
+ name: "Local Handler",
+ executable: executable,
+ interfaces: [Ci.nsIHandlerApp, Ci.nsILocalHandlerApp, Ci.nsISupports],
+ QueryInterface: function(iid) {
+ if (!this.interfaces.some( function(v) { return iid.equals(v) } ))
+ throw Cr.NS_ERROR_NO_INTERFACE;
+ return this;
+ }
+ };
+
+ var webHandler = Cc["@mozilla.org/uriloader/web-handler-app;1"].
+ createInstance(Ci.nsIWebHandlerApp);
+ webHandler.name = "Web Handler";
+ webHandler.uriTemplate = "http://www.example.com/?%s";
+
+ // FIXME: these tests create and manipulate enough variables that it would
+ // make sense to move each test into its own scope so we don't run the risk
+ // of one test stomping on another's data.
+
+
+ //**************************************************************************//
+ // Test Default Properties
+
+ // Get a handler info for a MIME type that neither the application nor
+ // the OS knows about and make sure its properties are set to the proper
+ // default values.
+
+ var handlerInfo = mimeSvc.getFromTypeAndExtension("nonexistent/type", null);
+
+ // Make sure it's also an nsIHandlerInfo.
+ do_check_true(handlerInfo instanceof Ci.nsIHandlerInfo);
+
+ do_check_eq(handlerInfo.type, "nonexistent/type");
+
+ // Deprecated property, but we should still make sure it's set correctly.
+ do_check_eq(handlerInfo.MIMEType, "nonexistent/type");
+
+ // These properties are the ones the handler service knows how to store.
+ do_check_eq(handlerInfo.preferredAction, Ci.nsIHandlerInfo.saveToDisk);
+ do_check_eq(handlerInfo.preferredApplicationHandler, null);
+ do_check_eq(handlerInfo.possibleApplicationHandlers.length, 0);
+ do_check_true(handlerInfo.alwaysAskBeforeHandling);
+
+ // These properties are initialized to default values by the service,
+ // so we might as well make sure they're initialized to the right defaults.
+ do_check_eq(handlerInfo.description, "");
+ do_check_eq(handlerInfo.hasDefaultHandler, false);
+ do_check_eq(handlerInfo.defaultDescription, "");
+
+ // test some default protocol info properties
+ var haveDefaultHandlersVersion = false;
+ try {
+ // If we have a defaultHandlersVersion pref, then assume that we're in the
+ // firefox tree and that we'll also have default handlers.
+ // Bug 395131 has been filed to make this test work more generically
+ // by providing our own prefs for this test rather than this icky
+ // special casing.
+ rootPrefBranch.getCharPref("gecko.handlerService.defaultHandlersVersion");
+ haveDefaultHandlersVersion = true;
+ } catch (ex) {}
+
+ const kExternalWarningDefault =
+ "network.protocol-handler.warn-external-default";
+ prefSvc.setBoolPref(kExternalWarningDefault, true);
+
+ // XXX add more thorough protocol info property checking
+
+ // no OS default handler exists
+ var protoInfo = protoSvc.getProtocolHandlerInfo("x-moz-rheet");
+ do_check_eq(protoInfo.preferredAction, protoInfo.alwaysAsk);
+ do_check_true(protoInfo.alwaysAskBeforeHandling);
+
+ // OS default exists, injected default does not exist,
+ // explicit warning pref: false
+ const kExternalWarningPrefPrefix = "network.protocol-handler.warn-external.";
+ prefSvc.setBoolPref(kExternalWarningPrefPrefix + "http", false);
+ protoInfo = protoSvc.getProtocolHandlerInfo("http");
+ do_check_eq(0, protoInfo.possibleApplicationHandlers.length);
+ do_check_false(protoInfo.alwaysAskBeforeHandling);
+
+ // OS default exists, injected default does not exist,
+ // explicit warning pref: true
+ prefSvc.setBoolPref(kExternalWarningPrefPrefix + "http", true);
+ protoInfo = protoSvc.getProtocolHandlerInfo("http");
+ // OS handler isn't included in possibleApplicationHandlers, so length is 0
+ // Once they become instances of nsILocalHandlerApp, this number will need
+ // to change.
+ do_check_eq(0, protoInfo.possibleApplicationHandlers.length);
+ do_check_true(protoInfo.alwaysAskBeforeHandling);
+
+ // OS default exists, injected default exists, explicit warning pref: false
+ prefSvc.setBoolPref(kExternalWarningPrefPrefix + "mailto", false);
+ protoInfo = protoSvc.getProtocolHandlerInfo("mailto");
+ if (haveDefaultHandlersVersion)
+ do_check_eq(2, protoInfo.possibleApplicationHandlers.length);
+ else
+ do_check_eq(0, protoInfo.possibleApplicationHandlers.length);
+
+ // Win7+ or Linux's GIO might not have a default mailto: handler
+ if (noMailto)
+ do_check_true(protoInfo.alwaysAskBeforeHandling);
+ else
+ do_check_false(protoInfo.alwaysAskBeforeHandling);
+
+ // OS default exists, injected default exists, explicit warning pref: true
+ prefSvc.setBoolPref(kExternalWarningPrefPrefix + "mailto", true);
+ protoInfo = protoSvc.getProtocolHandlerInfo("mailto");
+ if (haveDefaultHandlersVersion) {
+ do_check_eq(2, protoInfo.possibleApplicationHandlers.length);
+ // Win7+ or Linux's GIO may have no default mailto: handler. Otherwise
+ // alwaysAskBeforeHandling is expected to be false here, because although
+ // the pref is true, the value in RDF is false. The injected mailto handler
+ // carried over the default pref value, and so when we set the pref above
+ // to true it's ignored.
+ if (noMailto)
+ do_check_true(protoInfo.alwaysAskBeforeHandling);
+ else
+ do_check_false(protoInfo.alwaysAskBeforeHandling);
+
+ } else {
+ do_check_eq(0, protoInfo.possibleApplicationHandlers.length);
+ do_check_true(protoInfo.alwaysAskBeforeHandling);
+ }
+
+ if (haveDefaultHandlersVersion) {
+ // Now set the value stored in RDF to true, and the pref to false, to make
+ // sure we still get the right value. (Basically, same thing as above but
+ // with the values reversed.)
+ prefSvc.setBoolPref(kExternalWarningPrefPrefix + "mailto", false);
+ protoInfo.alwaysAskBeforeHandling = true;
+ handlerSvc.store(protoInfo);
+ protoInfo = protoSvc.getProtocolHandlerInfo("mailto");
+ do_check_eq(2, protoInfo.possibleApplicationHandlers.length);
+ do_check_true(protoInfo.alwaysAskBeforeHandling);
+ }
+
+
+ //**************************************************************************//
+ // Test Round-Trip Data Integrity
+
+ // Test round-trip data integrity by setting the properties of the handler
+ // info object to different values, telling the handler service to store the
+ // object, and then retrieving a new info object for the same type and making
+ // sure its properties are identical.
+
+ handlerInfo.preferredAction = Ci.nsIHandlerInfo.useHelperApp;
+ handlerInfo.preferredApplicationHandler = localHandler;
+ handlerInfo.alwaysAskBeforeHandling = false;
+
+ handlerSvc.store(handlerInfo);
+
+ handlerInfo = mimeSvc.getFromTypeAndExtension("nonexistent/type", null);
+
+ do_check_eq(handlerInfo.preferredAction, Ci.nsIHandlerInfo.useHelperApp);
+
+ do_check_neq(handlerInfo.preferredApplicationHandler, null);
+ var preferredHandler = handlerInfo.preferredApplicationHandler;
+ do_check_eq(typeof preferredHandler, "object");
+ do_check_eq(preferredHandler.name, "Local Handler");
+ do_check_true(preferredHandler instanceof Ci.nsILocalHandlerApp);
+ preferredHandler.QueryInterface(Ci.nsILocalHandlerApp);
+ do_check_eq(preferredHandler.executable.path, localHandler.executable.path);
+
+ do_check_false(handlerInfo.alwaysAskBeforeHandling);
+
+ // Make sure the handler service's enumerate method lists all known handlers.
+ var handlerInfo2 = mimeSvc.getFromTypeAndExtension("nonexistent/type2", null);
+ handlerSvc.store(handlerInfo2);
+ var handlerTypes = ["nonexistent/type", "nonexistent/type2"];
+ if (haveDefaultHandlersVersion) {
+ handlerTypes.push("webcal");
+ handlerTypes.push("mailto");
+ handlerTypes.push("irc");
+ handlerTypes.push("ircs");
+ }
+ var handlers = handlerSvc.enumerate();
+ while (handlers.hasMoreElements()) {
+ var handler = handlers.getNext().QueryInterface(Ci.nsIHandlerInfo);
+ do_check_neq(handlerTypes.indexOf(handler.type), -1);
+ handlerTypes.splice(handlerTypes.indexOf(handler.type), 1);
+ }
+ do_check_eq(handlerTypes.length, 0);
+
+ // Make sure the handler service's remove method removes a handler record.
+ handlerSvc.remove(handlerInfo2);
+ handlers = handlerSvc.enumerate();
+ while (handlers.hasMoreElements())
+ do_check_neq(handlers.getNext().QueryInterface(Ci.nsIHandlerInfo).type,
+ handlerInfo2.type);
+
+ // Make sure we can store and retrieve a handler info object with no preferred
+ // handler.
+ var noPreferredHandlerInfo =
+ mimeSvc.getFromTypeAndExtension("nonexistent/no-preferred-handler", null);
+ handlerSvc.store(noPreferredHandlerInfo);
+ noPreferredHandlerInfo =
+ mimeSvc.getFromTypeAndExtension("nonexistent/no-preferred-handler", null);
+ do_check_eq(noPreferredHandlerInfo.preferredApplicationHandler, null);
+
+ // Make sure that the handler service removes an existing handler record
+ // if we store a handler info object with no preferred handler.
+ var removePreferredHandlerInfo =
+ mimeSvc.getFromTypeAndExtension("nonexistent/rem-preferred-handler", null);
+ removePreferredHandlerInfo.preferredApplicationHandler = localHandler;
+ handlerSvc.store(removePreferredHandlerInfo);
+ removePreferredHandlerInfo =
+ mimeSvc.getFromTypeAndExtension("nonexistent/rem-preferred-handler", null);
+ removePreferredHandlerInfo.preferredApplicationHandler = null;
+ handlerSvc.store(removePreferredHandlerInfo);
+ removePreferredHandlerInfo =
+ mimeSvc.getFromTypeAndExtension("nonexistent/rem-preferred-handler", null);
+ do_check_eq(removePreferredHandlerInfo.preferredApplicationHandler, null);
+
+ // Make sure we can store and retrieve a handler info object with possible
+ // handlers. We test both adding and removing handlers.
+
+ // Get a handler info and make sure it has no possible handlers.
+ var possibleHandlersInfo =
+ mimeSvc.getFromTypeAndExtension("nonexistent/possible-handlers", null);
+ do_check_eq(possibleHandlersInfo.possibleApplicationHandlers.length, 0);
+
+ // Store and re-retrieve the handler and make sure it still has no possible
+ // handlers.
+ handlerSvc.store(possibleHandlersInfo);
+ possibleHandlersInfo =
+ mimeSvc.getFromTypeAndExtension("nonexistent/possible-handlers", null);
+ do_check_eq(possibleHandlersInfo.possibleApplicationHandlers.length, 0);
+
+ // Add two handlers, store the object, re-retrieve it, and make sure it has
+ // two handlers.
+ possibleHandlersInfo.possibleApplicationHandlers.appendElement(localHandler,
+ false);
+ possibleHandlersInfo.possibleApplicationHandlers.appendElement(webHandler,
+ false);
+ handlerSvc.store(possibleHandlersInfo);
+ possibleHandlersInfo =
+ mimeSvc.getFromTypeAndExtension("nonexistent/possible-handlers", null);
+ do_check_eq(possibleHandlersInfo.possibleApplicationHandlers.length, 2);
+
+ // Figure out which is the local and which is the web handler and the index
+ // in the array of the local handler, which is the one we're going to remove
+ // to test removal of a handler.
+ var handler1 = possibleHandlersInfo.possibleApplicationHandlers.
+ queryElementAt(0, Ci.nsIHandlerApp);
+ var handler2 = possibleHandlersInfo.possibleApplicationHandlers.
+ queryElementAt(1, Ci.nsIHandlerApp);
+ var localPossibleHandler, webPossibleHandler, localIndex;
+ if (handler1 instanceof Ci.nsILocalHandlerApp)
+ [localPossibleHandler, webPossibleHandler, localIndex] = [handler1,
+ handler2,
+ 0];
+ else
+ [localPossibleHandler, webPossibleHandler, localIndex] = [handler2,
+ handler1,
+ 1];
+ localPossibleHandler.QueryInterface(Ci.nsILocalHandlerApp);
+ webPossibleHandler.QueryInterface(Ci.nsIWebHandlerApp);
+
+ // Make sure the two handlers are the ones we stored.
+ do_check_eq(localPossibleHandler.name, localHandler.name);
+ do_check_true(localPossibleHandler.equals(localHandler));
+ do_check_eq(webPossibleHandler.name, webHandler.name);
+ do_check_true(webPossibleHandler.equals(webHandler));
+
+ // Remove a handler, store the object, re-retrieve it, and make sure
+ // it only has one handler.
+ possibleHandlersInfo.possibleApplicationHandlers.removeElementAt(localIndex);
+ handlerSvc.store(possibleHandlersInfo);
+ possibleHandlersInfo =
+ mimeSvc.getFromTypeAndExtension("nonexistent/possible-handlers", null);
+ do_check_eq(possibleHandlersInfo.possibleApplicationHandlers.length, 1);
+
+ // Make sure the handler is the one we didn't remove.
+ webPossibleHandler = possibleHandlersInfo.possibleApplicationHandlers.
+ queryElementAt(0, Ci.nsIWebHandlerApp);
+ do_check_eq(webPossibleHandler.name, webHandler.name);
+ do_check_true(webPossibleHandler.equals(webHandler));
+
+ //////////////////////////////////////////////////////
+ // handler info command line parameters and equality
+ var localApp = Cc["@mozilla.org/uriloader/local-handler-app;1"].
+ createInstance(Ci.nsILocalHandlerApp);
+ var handlerApp = localApp.QueryInterface(Ci.nsIHandlerApp);
+
+ do_check_true(handlerApp.equals(localApp));
+
+ localApp.executable = executable;
+
+ do_check_eq(0, localApp.parameterCount);
+ localApp.appendParameter("-test1");
+ do_check_eq(1, localApp.parameterCount);
+ localApp.appendParameter("-test2");
+ do_check_eq(2, localApp.parameterCount);
+ do_check_true(localApp.parameterExists("-test1"));
+ do_check_true(localApp.parameterExists("-test2"));
+ do_check_false(localApp.parameterExists("-false"));
+ localApp.clearParameters();
+ do_check_eq(0, localApp.parameterCount);
+
+ var localApp2 = Cc["@mozilla.org/uriloader/local-handler-app;1"].
+ createInstance(Ci.nsILocalHandlerApp);
+
+ localApp2.executable = executable;
+
+ localApp.clearParameters();
+ do_check_true(localApp.equals(localApp2));
+
+ // equal:
+ // cut -d 1 -f 2
+ // cut -d 1 -f 2
+
+ localApp.appendParameter("-test1");
+ localApp.appendParameter("-test2");
+ localApp.appendParameter("-test3");
+ localApp2.appendParameter("-test1");
+ localApp2.appendParameter("-test2");
+ localApp2.appendParameter("-test3");
+ do_check_true(localApp.equals(localApp2));
+
+ // not equal:
+ // cut -d 1 -f 2
+ // cut -f 1 -d 2
+
+ localApp.clearParameters();
+ localApp2.clearParameters();
+
+ localApp.appendParameter("-test1");
+ localApp.appendParameter("-test2");
+ localApp.appendParameter("-test3");
+ localApp2.appendParameter("-test2");
+ localApp2.appendParameter("-test1");
+ localApp2.appendParameter("-test3");
+ do_check_false(localApp2.equals(localApp));
+
+ var str;
+ str = localApp.getParameter(0)
+ do_check_eq(str, "-test1");
+ str = localApp.getParameter(1)
+ do_check_eq(str, "-test2");
+ str = localApp.getParameter(2)
+ do_check_eq(str, "-test3");
+
+ // FIXME: test round trip integrity for a protocol.
+ // FIXME: test round trip integrity for a handler info with a web handler.
+
+ //**************************************************************************//
+ // getTypeFromExtension tests
+
+ // test nonexistent extension
+ var lolType = handlerSvc.getTypeFromExtension("lolcat");
+ do_check_eq(lolType, "");
+
+
+ // add a handler for the extension
+ var lolHandler = mimeSvc.getFromTypeAndExtension("application/lolcat", null);
+
+ do_check_false(lolHandler.extensionExists("lolcat"));
+ lolHandler.preferredAction = Ci.nsIHandlerInfo.useHelperApp;
+ lolHandler.preferredApplicationHandler = localHandler;
+ lolHandler.alwaysAskBeforeHandling = false;
+
+ // store the handler
+ do_check_false(handlerSvc.exists(lolHandler));
+ handlerSvc.store(lolHandler);
+ do_check_true(handlerSvc.exists(lolHandler));
+
+ // Get a file:// string pointing to mimeTypes.rdf
+ var rdfFile = HandlerServiceTest._dirSvc.get("UMimTyp", Ci.nsIFile);
+ var fileHandler = ioService.getProtocolHandler("file").QueryInterface(Ci.nsIFileProtocolHandler);
+ var rdfFileURI = fileHandler.getURLSpecFromFile(rdfFile);
+
+ // Assign a file extenstion to the handler. handlerSvc.store() doesn't
+ // actually store any file extensions added with setFileExtensions(), you
+ // have to wade into RDF muck to do so.
+
+ // Based on toolkit/mozapps/downloads/content/helperApps.js :: addExtension()
+ var gRDF = Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService);
+ var mimeSource = gRDF.GetUnicodeResource("urn:mimetype:application/lolcat");
+ var valueProperty = gRDF.GetUnicodeResource("http://home.netscape.com/NC-rdf#fileExtensions");
+ var mimeLiteral = gRDF.GetLiteral("lolcat");
+
+ var DS = gRDF.GetDataSourceBlocking(rdfFileURI);
+ DS.Assert(mimeSource, valueProperty, mimeLiteral, true);
+
+
+ // test now-existent extension
+ lolType = handlerSvc.getTypeFromExtension("lolcat");
+ do_check_eq(lolType, "application/lolcat");
+
+ // test mailcap entries with needsterminal are ignored on non-Windows non-Mac.
+ if (mozinfo.os != "win" && mozinfo.os != "mac") {
+ env.set('PERSONAL_MAILCAP', do_get_file('mailcap').path);
+ handlerInfo = mimeSvc.getFromTypeAndExtension("text/plain", null);
+ do_check_eq(handlerInfo.preferredAction, Ci.nsIHandlerInfo.useSystemDefault);
+ do_check_eq(handlerInfo.defaultDescription, "sed");
+ }
+}