diff options
Diffstat (limited to 'uriloader/exthandler/tests/unit/test_handlerService.js')
-rw-r--r-- | uriloader/exthandler/tests/unit/test_handlerService.js | 470 |
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"); + } +} |