/* 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 = Services.prefs; 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 = Services.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 = Cc[ "@mozilla.org/uriloader/local-handler-app;1" ].createInstance(Ci.nsILocalHandlerApp); localHandler.name = "Local Handler"; localHandler.executable = executable; 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. Assert.ok(handlerInfo instanceof Ci.nsIHandlerInfo); Assert.equal(handlerInfo.type, "nonexistent/type"); // Deprecated property, but we should still make sure it's set correctly. Assert.equal(handlerInfo.MIMEType, "nonexistent/type"); // These properties are the ones the handler service knows how to store. Assert.equal(handlerInfo.preferredAction, Ci.nsIHandlerInfo.saveToDisk); Assert.equal(handlerInfo.preferredApplicationHandler, null); Assert.equal(handlerInfo.possibleApplicationHandlers.length, 0); Assert.equal( handlerInfo.alwaysAskBeforeHandling, prefSvc.getBoolPref( "browser.download.always_ask_before_handling_new_types", false ) ); // These properties are initialized to default values by the service, // so we might as well make sure they're initialized to the right defaults. Assert.equal(handlerInfo.description, ""); Assert.equal(handlerInfo.hasDefaultHandler, false); Assert.equal(handlerInfo.defaultDescription, ""); 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"); Assert.equal(protoInfo.preferredAction, protoInfo.alwaysAsk); Assert.ok(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"); Assert.equal(0, protoInfo.possibleApplicationHandlers.length); // NOTE: this assertion will fail if the system executing the test does not // have a handler registered for the http protocol. This is very unlikely to // actually happen except on certain configurations of Linux, but one of // those configurations is the default WSL Ubuntu install. So, if you are // running this test locally and seeing a failure here, it might not be // anything to really worry about. Assert.ok(!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. Assert.equal(0, protoInfo.possibleApplicationHandlers.length); Assert.ok(protoInfo.alwaysAskBeforeHandling); // OS default exists, injected default exists, explicit warning pref: false prefSvc.setBoolPref(kExternalWarningPrefPrefix + "mailto", false); protoInfo = protoSvc.getProtocolHandlerInfo("mailto"); if (AppConstants.MOZ_APP_NAME == "thunderbird") { Assert.equal(0, protoInfo.possibleApplicationHandlers.length); } else { Assert.equal(1, protoInfo.possibleApplicationHandlers.length); } // Win7+ or Linux's GIO might not have a default mailto: handler if (noMailto) { Assert.ok(protoInfo.alwaysAskBeforeHandling); } else { Assert.ok(!protoInfo.alwaysAskBeforeHandling); } // OS default exists, injected default exists, explicit warning pref: true prefSvc.setBoolPref(kExternalWarningPrefPrefix + "mailto", true); protoInfo = protoSvc.getProtocolHandlerInfo("mailto"); if (AppConstants.MOZ_APP_NAME == "thunderbird") { Assert.equal(0, protoInfo.possibleApplicationHandlers.length); } else { Assert.equal(1, protoInfo.possibleApplicationHandlers.length); // Win7+ or Linux's GIO may have no default mailto: handler, so we'd ask // anyway. Otherwise, the default handlers will not have stored preferred // actions etc., so re-requesting them after the warning pref has changed // will use the updated pref value. So both when we have and do not have // a default mailto: handler, we'll ask: Assert.ok(protoInfo.alwaysAskBeforeHandling); // As soon as anyone actually stores updated defaults into the profile // database, that default will stop tracking the warning pref. } // 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"); if (AppConstants.MOZ_APP_NAME == "thunderbird") { Assert.equal(0, protoInfo.possibleApplicationHandlers.length); } else { Assert.equal(1, protoInfo.possibleApplicationHandlers.length); Assert.ok(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); Assert.equal(handlerInfo.preferredAction, Ci.nsIHandlerInfo.useHelperApp); Assert.notEqual(handlerInfo.preferredApplicationHandler, null); var preferredHandler = handlerInfo.preferredApplicationHandler; Assert.equal(typeof preferredHandler, "object"); Assert.equal(preferredHandler.name, "Local Handler"); Assert.ok(preferredHandler instanceof Ci.nsILocalHandlerApp); preferredHandler.QueryInterface(Ci.nsILocalHandlerApp); Assert.equal(preferredHandler.executable.path, localHandler.executable.path); Assert.ok(!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"]; handlerTypes.push("mailto"); for (let handler of handlerSvc.enumerate()) { Assert.notEqual(handlerTypes.indexOf(handler.type), -1); handlerTypes.splice(handlerTypes.indexOf(handler.type), 1); } Assert.equal(handlerTypes.length, 0); // Make sure the handler service's remove method removes a handler record. handlerSvc.remove(handlerInfo2); let handlers = handlerSvc.enumerate(); while (handlers.hasMoreElements()) { Assert.notEqual( 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 ); Assert.equal(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 ); Assert.equal(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 ); Assert.equal(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 ); Assert.equal(possibleHandlersInfo.possibleApplicationHandlers.length, 0); // Add two handlers, store the object, re-retrieve it, and make sure it has // two handlers. possibleHandlersInfo.possibleApplicationHandlers.appendElement(localHandler); possibleHandlersInfo.possibleApplicationHandlers.appendElement(webHandler); handlerSvc.store(possibleHandlersInfo); possibleHandlersInfo = mimeSvc.getFromTypeAndExtension( "nonexistent/possible-handlers", null ); Assert.equal(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. Assert.equal(localPossibleHandler.name, localHandler.name); Assert.ok(localPossibleHandler.equals(localHandler)); Assert.equal(webPossibleHandler.name, webHandler.name); Assert.ok(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 ); Assert.equal(possibleHandlersInfo.possibleApplicationHandlers.length, 1); // Make sure the handler is the one we didn't remove. webPossibleHandler = possibleHandlersInfo.possibleApplicationHandlers.queryElementAt( 0, Ci.nsIWebHandlerApp ); Assert.equal(webPossibleHandler.name, webHandler.name); Assert.ok(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); Assert.ok(handlerApp.equals(localApp)); localApp.executable = executable; Assert.equal(0, localApp.parameterCount); localApp.appendParameter("-test1"); Assert.equal(1, localApp.parameterCount); localApp.appendParameter("-test2"); Assert.equal(2, localApp.parameterCount); Assert.ok(localApp.parameterExists("-test1")); Assert.ok(localApp.parameterExists("-test2")); Assert.ok(!localApp.parameterExists("-false")); localApp.clearParameters(); Assert.equal(0, localApp.parameterCount); var localApp2 = Cc[ "@mozilla.org/uriloader/local-handler-app;1" ].createInstance(Ci.nsILocalHandlerApp); localApp2.executable = executable; localApp.clearParameters(); Assert.ok(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"); Assert.ok(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"); Assert.ok(!localApp2.equals(localApp)); var str; str = localApp.getParameter(0); Assert.equal(str, "-test1"); str = localApp.getParameter(1); Assert.equal(str, "-test2"); str = localApp.getParameter(2); Assert.equal(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"); Assert.equal(lolType, ""); // add a handler for the extension var lolHandler = mimeSvc.getFromTypeAndExtension("application/lolcat", null); Assert.ok(!lolHandler.extensionExists("lolcat")); lolHandler.preferredAction = Ci.nsIHandlerInfo.useHelperApp; lolHandler.preferredApplicationHandler = localHandler; lolHandler.alwaysAskBeforeHandling = false; lolHandler.appendExtension("lolcat"); // store the handler Assert.ok(!handlerSvc.exists(lolHandler)); handlerSvc.store(lolHandler); Assert.ok(handlerSvc.exists(lolHandler)); // test now-existent extension lolType = handlerSvc.getTypeFromExtension("lolcat"); Assert.equal(lolType, "application/lolcat"); // test mailcap entries with needsterminal are ignored on non-Windows non-Mac. if (mozinfo.os != "win" && mozinfo.os != "mac") { prefSvc.setStringPref( "helpers.private_mailcap_file", do_get_file("mailcap").path ); handlerInfo = mimeSvc.getFromTypeAndExtension("text/plain", null); Assert.equal(handlerInfo.preferredAction, Ci.nsIHandlerInfo.saveToDisk); Assert.equal(handlerInfo.defaultDescription, "sed"); } }