diff options
Diffstat (limited to 'uriloader/exthandler/tests/unit')
9 files changed, 1046 insertions, 0 deletions
diff --git a/uriloader/exthandler/tests/unit/head_handlerService.js b/uriloader/exthandler/tests/unit/head_handlerService.js new file mode 100644 index 000000000..8b6803d24 --- /dev/null +++ b/uriloader/exthandler/tests/unit/head_handlerService.js @@ -0,0 +1,163 @@ +/* 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/. */ + +// Inspired by the Places infrastructure in head_bookmarks.js + +var Cc = Components.classes; +var Ci = Components.interfaces; +var Cr = Components.results; +var Cu = Components.utils; + +var HandlerServiceTest = { + //**************************************************************************// + // Convenience Getters + + __dirSvc: null, + get _dirSvc() { + if (!this.__dirSvc) + this.__dirSvc = Cc["@mozilla.org/file/directory_service;1"]. + getService(Ci.nsIProperties). + QueryInterface(Ci.nsIDirectoryService); + return this.__dirSvc; + }, + + __consoleSvc: null, + get _consoleSvc() { + if (!this.__consoleSvc) + this.__consoleSvc = Cc["@mozilla.org/consoleservice;1"]. + getService(Ci.nsIConsoleService); + return this.__consoleSvc; + }, + + + //**************************************************************************// + // nsISupports + + interfaces: [Ci.nsIDirectoryServiceProvider, Ci.nsISupports], + + QueryInterface: function HandlerServiceTest_QueryInterface(iid) { + if (!this.interfaces.some( function(v) { return iid.equals(v) } )) + throw Cr.NS_ERROR_NO_INTERFACE; + return this; + }, + + + //**************************************************************************// + // Initialization & Destruction + + init: function HandlerServiceTest_init() { + // Register ourselves as a directory provider for the datasource file + // if there isn't one registered already. + try { + this._dirSvc.get("UMimTyp", Ci.nsIFile); + } catch (ex) { + this._dirSvc.registerProvider(this); + this._providerRegistered = true; + } + + // Delete the existing datasource file, if any, so we start from scratch. + // We also do this after finishing the tests, so there shouldn't be an old + // file lying around, but just in case we delete it here as well. + this._deleteDatasourceFile(); + + // Turn on logging so we can troubleshoot problems with the tests. + var prefBranch = Cc["@mozilla.org/preferences-service;1"]. + getService(Ci.nsIPrefBranch); + prefBranch.setBoolPref("browser.contentHandling.log", true); + }, + + destroy: function HandlerServiceTest_destroy() { + // Delete the existing datasource file, if any, so we don't leave test files + // lying around and we start from scratch the next time. + this._deleteDatasourceFile(); + // Unregister the directory service provider + if (this._providerRegistered) + this._dirSvc.unregisterProvider(this); + }, + + + //**************************************************************************// + // nsIDirectoryServiceProvider + + getFile: function HandlerServiceTest_getFile(property, persistent) { + this.log("getFile: requesting " + property); + + persistent.value = true; + + if (property == "UMimTyp") { + var datasourceFile = this._dirSvc.get("CurProcD", Ci.nsIFile); + datasourceFile.append("mimeTypes.rdf"); + return datasourceFile; + } + + // This causes extraneous errors to show up in the log when the directory + // service asks us first for CurProcD and MozBinD. I wish there was a way + // to suppress those errors. + this.log("the following NS_ERROR_FAILURE exception in " + + "nsIDirectoryServiceProvider::getFile is expected, " + + "as we don't provide the '" + property + "' file"); + throw Cr.NS_ERROR_FAILURE; + }, + + + //**************************************************************************// + // Utilities + + /** + * Delete the datasource file. + */ + _deleteDatasourceFile: function HandlerServiceTest__deleteDatasourceFile() { + var file = this._dirSvc.get("UMimTyp", Ci.nsIFile); + if (file.exists()) + file.remove(false); + }, + + /** + * Get the contents of the datasource as a serialized string. Useful for + * debugging problems with test failures, i.e.: + * + * HandlerServiceTest.log(HandlerServiceTest.getDatasourceContents()); + * + * @returns {string} the serialized datasource + */ + getDatasourceContents: function HandlerServiceTest_getDatasourceContents() { + var rdf = Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService); + + var ioService = Cc["@mozilla.org/network/io-service;1"]. + getService(Ci.nsIIOService); + var fileHandler = ioService.getProtocolHandler("file"). + QueryInterface(Ci.nsIFileProtocolHandler); + var fileURL = fileHandler.getURLSpecFromFile(this.getDatasourceFile()); + var ds = rdf.GetDataSourceBlocking(fileURL); + + var outputStream = { + data: "", + close: function() {}, + flush: function() {}, + write: function (buffer,count) { + this.data += buffer; + return count; + }, + writeFrom: function (stream,count) {}, + isNonBlocking: false + }; + + ds.QueryInterface(Components.interfaces.nsIRDFXMLSource); + ds.Serialize(outputStream); + + return outputStream.data; + }, + + /** + * Log a message to the console and the test log. + */ + log: function HandlerServiceTest_log(message) { + message = "*** HandlerServiceTest: " + message; + this._consoleSvc.logStringMessage(message); + print(message); + } + +}; + +HandlerServiceTest.init(); diff --git a/uriloader/exthandler/tests/unit/mailcap b/uriloader/exthandler/tests/unit/mailcap new file mode 100644 index 000000000..dc93ef804 --- /dev/null +++ b/uriloader/exthandler/tests/unit/mailcap @@ -0,0 +1,2 @@ +text/plain; cat '%s'; needsterminal +text/plain; sed '%s' diff --git a/uriloader/exthandler/tests/unit/tail_handlerService.js b/uriloader/exthandler/tests/unit/tail_handlerService.js new file mode 100644 index 000000000..1d1989127 --- /dev/null +++ b/uriloader/exthandler/tests/unit/tail_handlerService.js @@ -0,0 +1,5 @@ +/* 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/. */ + +HandlerServiceTest.destroy(); diff --git a/uriloader/exthandler/tests/unit/test_badMIMEType.js b/uriloader/exthandler/tests/unit/test_badMIMEType.js new file mode 100644 index 000000000..df1202a0f --- /dev/null +++ b/uriloader/exthandler/tests/unit/test_badMIMEType.js @@ -0,0 +1,26 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- + * 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() { + // "text/plain" has an 0xFF character appended to it. This means it's an + // invalid string, which is tricky to enter using a text editor (I used + // emacs' hexl-mode). It also means an ordinary text editor might drop it + // or convert it to something that *is* valid (in UTF8). So we measure + // its length to make sure this hasn't happened. + var badMimeType = "text/plainÿ"; + do_check_eq(badMimeType.length, 11); + + try { + var type = Cc["@mozilla.org/mime;1"]. + getService(Ci.nsIMIMEService). + getFromTypeAndExtension(badMimeType, "txt"); + } catch (e if (e instanceof Ci.nsIException && + e.result == Cr.NS_ERROR_NOT_AVAILABLE)) { + // This is an expected exception, thrown if the type can't be determined + } finally { + } + // Not crashing is good enough + do_check_eq(true, true); +} diff --git a/uriloader/exthandler/tests/unit/test_getTypeFromExtension_ext_to_type_mapping.js b/uriloader/exthandler/tests/unit/test_getTypeFromExtension_ext_to_type_mapping.js new file mode 100644 index 000000000..d83c486bb --- /dev/null +++ b/uriloader/exthandler/tests/unit/test_getTypeFromExtension_ext_to_type_mapping.js @@ -0,0 +1,53 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- + * 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/. */ + +/** + * Test for bug 508030 <https://bugzilla.mozilla.org/show_bug.cgi?id=508030>: + * nsIMIMEService.getTypeFromExtension fails to find a match in the + * "ext-to-type-mapping" category if the provided extension is not lowercase. + */ +function run_test() { + // --- Common services --- + + const mimeService = Cc["@mozilla.org/mime;1"]. + getService(Ci.nsIMIMEService); + + const categoryManager = Cc["@mozilla.org/categorymanager;1"]. + getService(Ci.nsICategoryManager); + + // --- Test procedure --- + + const kTestExtension = "testextension"; + const kTestExtensionMixedCase = "testExtensIon"; + const kTestMimeType = "application/x-testextension"; + + // Ensure that the test extension is not initially recognized by the operating + // system or the "ext-to-type-mapping" category. + try { + // Try and get the MIME type associated with the extension. + mimeService.getTypeFromExtension(kTestExtension); + // The line above should have thrown an exception. + do_throw("nsIMIMEService.getTypeFromExtension succeeded unexpectedly"); + } catch (e if (e instanceof Ci.nsIException && + e.result == Cr.NS_ERROR_NOT_AVAILABLE)) { + // This is an expected exception, thrown if the type can't be determined. + // Any other exception would cause the test to fail. + } + + // Add a temporary category entry mapping the extension to the MIME type. + categoryManager.addCategoryEntry("ext-to-type-mapping", kTestExtension, + kTestMimeType, false, true); + + // Check that the mapping is recognized in the simple case. + var type = mimeService.getTypeFromExtension(kTestExtension); + do_check_eq(type, kTestMimeType); + + // Check that the mapping is recognized even if the extension has mixed case. + type = mimeService.getTypeFromExtension(kTestExtensionMixedCase); + do_check_eq(type, kTestMimeType); + + // Clean up after ourselves. + categoryManager.deleteCategoryEntry("ext-to-type-mapping", kTestExtension, false); +} diff --git a/uriloader/exthandler/tests/unit/test_getTypeFromExtension_with_empty_Content_Type.js b/uriloader/exthandler/tests/unit/test_getTypeFromExtension_with_empty_Content_Type.js new file mode 100644 index 000000000..1ae2a6fcf --- /dev/null +++ b/uriloader/exthandler/tests/unit/test_getTypeFromExtension_with_empty_Content_Type.js @@ -0,0 +1,186 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- + * 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/. */ + +/** + * Test for bug 484579 <https://bugzilla.mozilla.org/show_bug.cgi?id=484579>: + * nsIMIMEService.getTypeFromExtension may fail unexpectedly on Windows when + * "Content Type" is empty in the registry. + */ +function run_test() { + // --- Preliminary platform check --- + + // If this test is not running on the Windows platform, stop now, before + // calling XPCOMUtils.generateQI during the MockWindowsRegKey declaration. + if (mozinfo.os != "win") + return; + + // --- Modified nsIWindowsRegKey implementation --- + + Cu.import("resource://gre/modules/XPCOMUtils.jsm"); + + /** + * Constructs a new mock registry key by wrapping the provided object. + * + * This mock implementation is tailored for this test, and forces consumers + * of the readStringValue method to believe that the "Content Type" value of + * the ".txt" key under HKEY_CLASSES_ROOT is an empty string. + * + * The same value read from "HKEY_LOCAL_MACHINE\SOFTWARE\Classes" is not + * affected. + * + * @param aWrappedObject An actual nsIWindowsRegKey implementation. + */ + function MockWindowsRegKey(aWrappedObject) { + this._wrappedObject = aWrappedObject; + + // This function creates a forwarding function for wrappedObject + function makeForwardingFunction(functionName) { + return function() { + return aWrappedObject[functionName].apply(aWrappedObject, arguments); + } + } + + // Forward all the functions that are not explicitly overridden + for (var propertyName in aWrappedObject) { + if (!(propertyName in this)) { + if (typeof aWrappedObject[propertyName] == "function") { + this[propertyName] = makeForwardingFunction(propertyName); + } else { + this[propertyName] = aWrappedObject[propertyName]; + } + } + } + } + + MockWindowsRegKey.prototype = { + // --- Overridden nsISupports interface functions --- + + QueryInterface: XPCOMUtils.generateQI([Ci.nsIWindowsRegKey]), + + // --- Overridden nsIWindowsRegKey interface functions --- + + open: function(aRootKey, aRelPath, aMode) { + // Remember the provided root key and path + this._rootKey = aRootKey; + this._relPath = aRelPath; + + // Create the actual registry key + return this._wrappedObject.open(aRootKey, aRelPath, aMode); + }, + + openChild: function(aRelPath, aMode) { + // Open the child key and wrap it + var innerKey = this._wrappedObject.openChild(aRelPath, aMode); + var key = new MockWindowsRegKey(innerKey); + + // Set the properties of the child key and return it + key._rootKey = this._rootKey; + key._relPath = this._relPath + aRelPath; + return key; + }, + + createChild: function(aRelPath, aMode) { + // Create the child key and wrap it + var innerKey = this._wrappedObject.createChild(aRelPath, aMode); + var key = new MockWindowsRegKey(innerKey); + + // Set the properties of the child key and return it + key._rootKey = this._rootKey; + key._relPath = this._relPath + aRelPath; + return key; + }, + + get childCount() { + return this._wrappedObject.childCount; + }, + + get valueCount() { + return this._wrappedObject.valueCount; + }, + + readStringValue: function(aName) { + // If this is the key under test, return a fake value + if (this._rootKey == Ci.nsIWindowsRegKey.ROOT_KEY_CLASSES_ROOT && + this._relPath.toLowerCase() == ".txt" && + aName.toLowerCase() == "content type") { + return ""; + } + + // Return the real value in the registry + return this._wrappedObject.readStringValue(aName); + } + }; + + // --- Mock nsIWindowsRegKey factory --- + + var componentRegistrar = Components.manager. + QueryInterface(Ci.nsIComponentRegistrar); + + var originalWindowsRegKeyCID; + var mockWindowsRegKeyFactory; + + const kMockCID = Components.ID("{9b23dfe9-296b-4740-ba1c-d39c9a16e55e}"); + const kWindowsRegKeyContractID = "@mozilla.org/windows-registry-key;1"; + const kWindowsRegKeyClassName = "nsWindowsRegKey"; + + function registerMockWindowsRegKeyFactory() { + mockWindowsRegKeyFactory = { + createInstance: function(aOuter, aIid) { + if (aOuter != null) + throw Cr.NS_ERROR_NO_AGGREGATION; + + var innerKey = originalWindowsRegKeyFactory.createInstance(null, aIid); + var key = new MockWindowsRegKey(innerKey); + + return key.QueryInterface(aIid); + } + }; + + // Preserve the original factory + originalWindowsRegKeyCID = Cc[kWindowsRegKeyContractID].number; + + // Register the mock factory + componentRegistrar.registerFactory( + kMockCID, + "Mock Windows Registry Key Implementation", + kWindowsRegKeyContractID, + mockWindowsRegKeyFactory + ); + } + + function unregisterMockWindowsRegKeyFactory() { + // Free references to the mock factory + componentRegistrar.unregisterFactory( + kMockCID, + mockWindowsRegKeyFactory + ); + + // Restore the original factory + componentRegistrar.registerFactory( + Components.ID(originalWindowsRegKeyCID), + "", + kWindowsRegKeyContractID, + null + ); + } + + // --- Test procedure --- + + // Activate the override of the ".txt" file association data in the registry + registerMockWindowsRegKeyFactory(); + try { + // Try and get the MIME type associated with the extension. If this + // operation does not throw an unexpected exception, the test succeeds. + var type = Cc["@mozilla.org/mime;1"]. + getService(Ci.nsIMIMEService). + getTypeFromExtension(".txt"); + } catch (e if (e instanceof Ci.nsIException && + e.result == Cr.NS_ERROR_NOT_AVAILABLE)) { + // This is an expected exception, thrown if the type can't be determined + } finally { + // Ensure we restore the original factory when the test is finished + unregisterMockWindowsRegKeyFactory(); + } +} 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"); + } +} diff --git a/uriloader/exthandler/tests/unit/test_punycodeURIs.js b/uriloader/exthandler/tests/unit/test_punycodeURIs.js new file mode 100644 index 000000000..38622c840 --- /dev/null +++ b/uriloader/exthandler/tests/unit/test_punycodeURIs.js @@ -0,0 +1,126 @@ +/* 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/. */ + +// Encoded test URI to work on all platforms/independent of file encoding +const kTestURI = "http://\u65e5\u672c\u8a93.jp/"; +const kExpectedURI = "http://xn--wgv71a309e.jp/"; +const kOutputFile = "result.txt"; + +// Try several times in case the box we're running on is slow. +const kMaxCheckExistAttempts = 30; // seconds +var gCheckExistsAttempts = 0; + +const tempDir = do_get_tempdir(); + +function checkFile() { + // This is where we expect the output + var tempFile = tempDir.clone(); + tempFile.append(kOutputFile); + + if (!tempFile.exists()) { + if (gCheckExistsAttempts >= kMaxCheckExistAttempts) { + do_throw("Expected File " + tempFile.path + " does not exist after " + + kMaxCheckExistAttempts + " seconds"); + } + else { + ++gCheckExistsAttempts; + // Wait a bit longer then try again + do_timeout(1000, checkFile); + return; + } + } + + // Now read it + var fstream = + Components.classes["@mozilla.org/network/file-input-stream;1"] + .createInstance(Components.interfaces.nsIFileInputStream); + var sstream = + Components.classes["@mozilla.org/scriptableinputstream;1"] + .createInstance(Components.interfaces.nsIScriptableInputStream); + fstream.init(tempFile, -1, 0, 0); + sstream.init(fstream); + + // Read the first line only as that's the one we expect WriteArguments + // to be writing the argument to. + var data = sstream.read(4096); + + sstream.close(); + fstream.close(); + + // Now remove the old file + tempFile.remove(false); + + // This currently fails on Mac with an argument like -psn_0_nnnnnn + // This seems to be to do with how the executable is called, but I couldn't + // find a way around it. + // Additionally the lack of OS detection in xpcshell tests sucks, so we'll + // have to check for the argument mac gives us. + if (data.substring(0, 7) != "-psn_0_") + do_check_eq(data, kExpectedURI); + + do_test_finished(); +} + +function run_test() { + if (mozinfo.os == "mac") { + dump("INFO | test_punycodeURIs.js | Skipping test on mac, bug 599475") + return; + } + + // set up the uri to test with + var ioService = + Components.classes["@mozilla.org/network/io-service;1"] + .getService(Components.interfaces.nsIIOService); + + // set up the local handler object + var localHandler = + Components.classes["@mozilla.org/uriloader/local-handler-app;1"] + .createInstance(Components.interfaces.nsILocalHandlerApp); + localHandler.name = "Test Local Handler App"; + + // WriteArgument will just dump its arguments to a file for us. + var processDir = do_get_cwd(); + var exe = processDir.clone(); + exe.append("WriteArgument"); + + if (!exe.exists()) { + // Maybe we are on windows + exe.leafName = "WriteArgument.exe"; + if (!exe.exists()) + do_throw("Could not locate the WriteArgument tests executable\n"); + } + + var outFile = tempDir.clone(); + outFile.append(kOutputFile); + + // Set an environment variable for WriteArgument to pick up + var envSvc = + Components.classes["@mozilla.org/process/environment;1"] + .getService(Components.interfaces.nsIEnvironment); + + // The Write Argument file needs to know where its libraries are, so + // just force the path variable + // For mac + var greDir = HandlerServiceTest._dirSvc.get("GreD", Components.interfaces.nsIFile); + + envSvc.set("DYLD_LIBRARY_PATH", greDir.path); + // For Linux + envSvc.set("LD_LIBRARY_PATH", greDir.path); + //XXX: handle windows + + // Now tell it where we want the file. + envSvc.set("WRITE_ARGUMENT_FILE", outFile.path); + + var uri = ioService.newURI(kTestURI, null, null); + + // Just check we've got these matching, if we haven't there's a problem + // with ascii spec or our test case. + do_check_eq(uri.asciiSpec, kExpectedURI); + + localHandler.executable = exe; + localHandler.launchWithURI(uri); + + do_test_pending(); + do_timeout(1000, checkFile); +} diff --git a/uriloader/exthandler/tests/unit/xpcshell.ini b/uriloader/exthandler/tests/unit/xpcshell.ini new file mode 100644 index 000000000..e268ff9c3 --- /dev/null +++ b/uriloader/exthandler/tests/unit/xpcshell.ini @@ -0,0 +1,15 @@ +[DEFAULT] +head = head_handlerService.js +tail = tail_handlerService.js +run-sequentially = Bug 912235 - Intermittent failures + +[test_getTypeFromExtension_ext_to_type_mapping.js] +[test_getTypeFromExtension_with_empty_Content_Type.js] +[test_badMIMEType.js] +[test_handlerService.js] +support-files = mailcap +# Bug 676997: test consistently fails on Android +fail-if = os == "android" +[test_punycodeURIs.js] +# Bug 676997: test consistently fails on Android +fail-if = os == "android" |