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