From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- .../tests/unit/test_handlerService_store.js | 752 +++++++++++++++++++++ 1 file changed, 752 insertions(+) create mode 100644 uriloader/exthandler/tests/unit/test_handlerService_store.js (limited to 'uriloader/exthandler/tests/unit/test_handlerService_store.js') diff --git a/uriloader/exthandler/tests/unit/test_handlerService_store.js b/uriloader/exthandler/tests/unit/test_handlerService_store.js new file mode 100644 index 0000000000..03573dbc2c --- /dev/null +++ b/uriloader/exthandler/tests/unit/test_handlerService_store.js @@ -0,0 +1,752 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* + * Tests the nsIHandlerService interface. + */ + +// Set up an nsIWebHandlerApp instance that can be used in multiple tests. +let webHandlerApp = Cc[ + "@mozilla.org/uriloader/web-handler-app;1" +].createInstance(Ci.nsIWebHandlerApp); +webHandlerApp.name = "Web Handler"; +webHandlerApp.uriTemplate = "https://www.example.com/?url=%s"; +let expectedWebHandlerApp = { + name: webHandlerApp.name, + uriTemplate: webHandlerApp.uriTemplate, +}; + +// Set up an nsILocalHandlerApp instance that can be used in multiple tests. The +// executable should exist, but it doesn't need to point to an actual file, so +// we simply initialize it to the path of an existing directory. +let localHandlerApp = Cc[ + "@mozilla.org/uriloader/local-handler-app;1" +].createInstance(Ci.nsILocalHandlerApp); +localHandlerApp.name = "Local Handler"; +localHandlerApp.executable = FileUtils.getFile("TmpD", []); +let expectedLocalHandlerApp = { + name: localHandlerApp.name, + executable: localHandlerApp.executable, +}; + +/** + * Returns a new nsIHandlerInfo instance initialized to known values that don't + * depend on the platform and are easier to verify later. + * + * @param type + * Because the "preferredAction" is initialized to saveToDisk, this + * should represent a MIME type rather than a protocol. + */ +function getKnownHandlerInfo(type) { + let handlerInfo = HandlerServiceTestUtils.getBlankHandlerInfo(type); + handlerInfo.preferredAction = Ci.nsIHandlerInfo.saveToDisk; + handlerInfo.alwaysAskBeforeHandling = false; + return handlerInfo; +} + +/** + * Checks that the information stored in the handler service instance under + * testing matches the test data files. + */ +function assertAllHandlerInfosMatchTestData() { + let handlerInfos = HandlerServiceTestUtils.getAllHandlerInfos(); + + // It's important that the MIME types we check here do not exist at the + // operating system level, otherwise the list of handlers and file extensions + // will be merged. The current implementation avoids duplicate entries. + + HandlerServiceTestUtils.assertHandlerInfoMatches(handlerInfos.shift(), { + type: "example/type.handleinternally", + preferredAction: Ci.nsIHandlerInfo.handleInternally, + alwaysAskBeforeHandling: false, + fileExtensions: ["example_one"], + }); + + HandlerServiceTestUtils.assertHandlerInfoMatches(handlerInfos.shift(), { + type: "example/type.savetodisk", + preferredAction: Ci.nsIHandlerInfo.saveToDisk, + alwaysAskBeforeHandling: true, + preferredApplicationHandler: { + name: "Example Default Handler", + uriTemplate: "https://www.example.com/?url=%s", + }, + possibleApplicationHandlers: [ + { + name: "Example Default Handler", + uriTemplate: "https://www.example.com/?url=%s", + }, + ], + fileExtensions: ["example_two", "example_three"], + }); + + HandlerServiceTestUtils.assertHandlerInfoMatches(handlerInfos.shift(), { + type: "example/type.usehelperapp", + preferredAction: Ci.nsIHandlerInfo.useHelperApp, + alwaysAskBeforeHandling: true, + preferredApplicationHandler: { + name: "Example Default Handler", + uriTemplate: "https://www.example.com/?url=%s", + }, + possibleApplicationHandlers: [ + { + name: "Example Default Handler", + uriTemplate: "https://www.example.com/?url=%s", + }, + { + name: "Example Possible Handler One", + uriTemplate: "http://www.example.com/?id=1&url=%s", + }, + { + name: "Example Possible Handler Two", + uriTemplate: "http://www.example.com/?id=2&url=%s", + }, + ], + fileExtensions: ["example_two", "example_three"], + }); + + HandlerServiceTestUtils.assertHandlerInfoMatches(handlerInfos.shift(), { + type: "example/type.usesystemdefault", + preferredAction: Ci.nsIHandlerInfo.useSystemDefault, + alwaysAskBeforeHandling: false, + possibleApplicationHandlers: [ + { + name: "Example Possible Handler", + uriTemplate: "http://www.example.com/?url=%s", + }, + ], + }); + + HandlerServiceTestUtils.assertHandlerInfoMatches(handlerInfos.shift(), { + type: "examplescheme.usehelperapp", + preferredAction: Ci.nsIHandlerInfo.useHelperApp, + alwaysAskBeforeHandling: true, + preferredApplicationHandler: { + name: "Example Default Handler", + uriTemplate: "https://www.example.com/?url=%s", + }, + possibleApplicationHandlers: [ + { + name: "Example Default Handler", + uriTemplate: "https://www.example.com/?url=%s", + }, + { + name: "Example Possible Handler One", + uriTemplate: "http://www.example.com/?id=1&url=%s", + }, + { + name: "Example Possible Handler Two", + uriTemplate: "http://www.example.com/?id=2&url=%s", + }, + ], + }); + + HandlerServiceTestUtils.assertHandlerInfoMatches(handlerInfos.shift(), { + type: "examplescheme.usesystemdefault", + preferredAction: Ci.nsIHandlerInfo.useSystemDefault, + alwaysAskBeforeHandling: false, + possibleApplicationHandlers: [ + { + name: "Example Possible Handler", + uriTemplate: "http://www.example.com/?url=%s", + }, + ], + }); + + Assert.equal(handlerInfos.length, 0); +} + +/** + * Loads data from a file in a predefined format, verifying that the format is + * recognized and all the known properties are loaded and saved. + */ +add_task(async function test_store_fillHandlerInfo_predefined() { + // Test that the file format used in previous versions can be loaded. + await copyTestDataToHandlerStore(); + await assertAllHandlerInfosMatchTestData(); + + // Keep a copy of the nsIHandlerInfo instances, then delete the handler store + // and populate it with the known data. Since the handler store is empty, the + // default handlers for the current locale are also injected, so we have to + // delete them manually before adding the other nsIHandlerInfo instances. + let testHandlerInfos = HandlerServiceTestUtils.getAllHandlerInfos(); + await deleteHandlerStore(); + for (let handlerInfo of HandlerServiceTestUtils.getAllHandlerInfos()) { + gHandlerService.remove(handlerInfo); + } + for (let handlerInfo of testHandlerInfos) { + gHandlerService.store(handlerInfo); + } + + // Test that the known data still matches after saving it and reloading. + await unloadHandlerStore(); + await assertAllHandlerInfosMatchTestData(); +}); + +/** + * Check that "store" is able to add new instances, that "remove" and "exists" + * work, and that "fillHandlerInfo" throws when the instance does not exist. + */ +add_task(async function test_store_remove_exists() { + // Test both MIME types and protocols. + for (let type of [ + "example/type.usehelperapp", + "examplescheme.usehelperapp", + ]) { + // Create new nsIHandlerInfo instances before loading the test data. + await deleteHandlerStore(); + let handlerInfoPresent = HandlerServiceTestUtils.getHandlerInfo(type); + let handlerInfoAbsent = HandlerServiceTestUtils.getHandlerInfo(type + "2"); + + // Set up known properties that we can verify later. + handlerInfoAbsent.preferredAction = Ci.nsIHandlerInfo.saveToDisk; + handlerInfoAbsent.alwaysAskBeforeHandling = false; + + await copyTestDataToHandlerStore(); + + Assert.ok(gHandlerService.exists(handlerInfoPresent)); + Assert.ok(!gHandlerService.exists(handlerInfoAbsent)); + + gHandlerService.store(handlerInfoAbsent); + gHandlerService.remove(handlerInfoPresent); + + await unloadHandlerStore(); + + Assert.ok(!gHandlerService.exists(handlerInfoPresent)); + Assert.ok(gHandlerService.exists(handlerInfoAbsent)); + + Assert.throws( + () => gHandlerService.fillHandlerInfo(handlerInfoPresent, ""), + ex => ex.result == Cr.NS_ERROR_NOT_AVAILABLE + ); + + let actualHandlerInfo = HandlerServiceTestUtils.getHandlerInfo(type + "2"); + HandlerServiceTestUtils.assertHandlerInfoMatches(actualHandlerInfo, { + type: type + "2", + preferredAction: Ci.nsIHandlerInfo.saveToDisk, + alwaysAskBeforeHandling: false, + }); + } +}); + +/** + * Tests that it is possible to save an nsIHandlerInfo instance with a + * "preferredAction" that is either a valid or an unknown value, and the + * action always takes on an appropriate value when reloading. + */ +add_task(async function test_store_preferredAction() { + await deleteHandlerStore(); + + let handlerInfo = getKnownHandlerInfo("example/new"); + // Valid action values should all remain unchanged across a refresh, except + // for alwaysAsk which may be overridden with useHelperApp depending on prefs. + // Invalid action values should always convert to useHelperApp. + const actions = [ + { + preferred: Ci.nsIHandlerInfo.alwaysAsk, + expected: Ci.nsIHandlerInfo.alwaysAsk, + }, + { + preferred: Ci.nsIHandlerInfo.handleInternally, + expected: Ci.nsIHandlerInfo.handleInternally, + }, + { preferred: 999, expected: Ci.nsIHandlerInfo.useHelperApp }, + ]; + + for (let action of actions) { + handlerInfo.preferredAction = action.preferred; + gHandlerService.store(handlerInfo); + gHandlerService.fillHandlerInfo(handlerInfo, ""); + Assert.equal(handlerInfo.preferredAction, action.expected); + } +}); + +/** + * Tests that it is possible to save an nsIHandlerInfo instance containing an + * nsILocalHandlerApp instance pointing to an executable that doesn't exist, but + * this entry is ignored when reloading. + */ +add_task(async function test_store_localHandlerApp_missing() { + if (!("@mozilla.org/uriloader/dbus-handler-app;1" in Cc)) { + info("Skipping test because it does not apply to this platform."); + return; + } + + let missingHandlerApp = Cc[ + "@mozilla.org/uriloader/local-handler-app;1" + ].createInstance(Ci.nsILocalHandlerApp); + missingHandlerApp.name = "Non-existing Handler"; + missingHandlerApp.executable = FileUtils.getFile("TmpD", ["nonexisting"]); + + await deleteHandlerStore(); + + let handlerInfo = getKnownHandlerInfo("example/new"); + handlerInfo.preferredApplicationHandler = missingHandlerApp; + handlerInfo.possibleApplicationHandlers.appendElement(missingHandlerApp); + handlerInfo.possibleApplicationHandlers.appendElement(webHandlerApp); + gHandlerService.store(handlerInfo); + + await unloadHandlerStore(); + + let actualHandlerInfo = HandlerServiceTestUtils.getHandlerInfo("example/new"); + HandlerServiceTestUtils.assertHandlerInfoMatches(actualHandlerInfo, { + type: "example/new", + preferredAction: Ci.nsIHandlerInfo.saveToDisk, + alwaysAskBeforeHandling: false, + possibleApplicationHandlers: [expectedWebHandlerApp], + }); +}); + +/** + * Test saving and reloading an instance of nsIDBusHandlerApp. + */ +add_task(async function test_store_dBusHandlerApp() { + if (!("@mozilla.org/uriloader/dbus-handler-app;1" in Cc)) { + info("Skipping test because it does not apply to this platform."); + return; + } + + // Set up an nsIDBusHandlerApp instance for testing. + let dBusHandlerApp = Cc[ + "@mozilla.org/uriloader/dbus-handler-app;1" + ].createInstance(Ci.nsIDBusHandlerApp); + dBusHandlerApp.name = "DBus Handler"; + dBusHandlerApp.service = "test.method.server"; + dBusHandlerApp.method = "Method"; + dBusHandlerApp.dBusInterface = "test.method.Type"; + dBusHandlerApp.objectPath = "/test/method/Object"; + let expectedDBusHandlerApp = { + name: dBusHandlerApp.name, + service: dBusHandlerApp.service, + method: dBusHandlerApp.method, + dBusInterface: dBusHandlerApp.dBusInterface, + objectPath: dBusHandlerApp.objectPath, + }; + + await deleteHandlerStore(); + + let handlerInfo = getKnownHandlerInfo("example/new"); + handlerInfo.preferredApplicationHandler = dBusHandlerApp; + handlerInfo.possibleApplicationHandlers.appendElement(dBusHandlerApp); + gHandlerService.store(handlerInfo); + + await unloadHandlerStore(); + + let actualHandlerInfo = HandlerServiceTestUtils.getHandlerInfo("example/new"); + HandlerServiceTestUtils.assertHandlerInfoMatches(actualHandlerInfo, { + type: "example/new", + preferredAction: Ci.nsIHandlerInfo.saveToDisk, + alwaysAskBeforeHandling: false, + preferredApplicationHandler: expectedDBusHandlerApp, + possibleApplicationHandlers: [expectedDBusHandlerApp], + }); +}); + +/** + * Tests that it is possible to save an nsIHandlerInfo instance with a + * "preferredApplicationHandler" and no "possibleApplicationHandlers", but the + * former is always included in the latter list when reloading. + */ +add_task( + async function test_store_possibleApplicationHandlers_includes_preferred() { + await deleteHandlerStore(); + + let handlerInfo = getKnownHandlerInfo("example/new"); + handlerInfo.preferredApplicationHandler = localHandlerApp; + gHandlerService.store(handlerInfo); + + await unloadHandlerStore(); + + let actualHandlerInfo = + HandlerServiceTestUtils.getHandlerInfo("example/new"); + HandlerServiceTestUtils.assertHandlerInfoMatches(actualHandlerInfo, { + type: "example/new", + preferredAction: Ci.nsIHandlerInfo.saveToDisk, + alwaysAskBeforeHandling: false, + preferredApplicationHandler: expectedLocalHandlerApp, + possibleApplicationHandlers: [expectedLocalHandlerApp], + }); + } +); + +/** + * Tests that it is possible to save an nsIHandlerInfo instance with a + * "preferredApplicationHandler" that is not the first element in + * "possibleApplicationHandlers", but the former is always included as the first + * element of the latter list when reloading. + */ +add_task( + async function test_store_possibleApplicationHandlers_preferred_first() { + await deleteHandlerStore(); + + let handlerInfo = getKnownHandlerInfo("example/new"); + handlerInfo.preferredApplicationHandler = webHandlerApp; + // The preferred handler is appended after the other one. + handlerInfo.possibleApplicationHandlers.appendElement(localHandlerApp); + handlerInfo.possibleApplicationHandlers.appendElement(webHandlerApp); + gHandlerService.store(handlerInfo); + + await unloadHandlerStore(); + + let actualHandlerInfo = + HandlerServiceTestUtils.getHandlerInfo("example/new"); + HandlerServiceTestUtils.assertHandlerInfoMatches(actualHandlerInfo, { + type: "example/new", + preferredAction: Ci.nsIHandlerInfo.saveToDisk, + alwaysAskBeforeHandling: false, + preferredApplicationHandler: expectedWebHandlerApp, + possibleApplicationHandlers: [ + expectedWebHandlerApp, + expectedLocalHandlerApp, + ], + }); + } +); + +/** + * Tests that it is possible to save an nsIHandlerInfo instance with an + * uppercase file extension, but it is converted to lowercase when reloading. + */ +add_task(async function test_store_fileExtensions_lowercase() { + await deleteHandlerStore(); + + let handlerInfo = getKnownHandlerInfo("example/new"); + handlerInfo.appendExtension("extension_test1"); + handlerInfo.appendExtension("EXTENSION_test2"); + gHandlerService.store(handlerInfo); + + await unloadHandlerStore(); + + let actualHandlerInfo = HandlerServiceTestUtils.getHandlerInfo("example/new"); + HandlerServiceTestUtils.assertHandlerInfoMatches(actualHandlerInfo, { + type: "example/new", + preferredAction: Ci.nsIHandlerInfo.saveToDisk, + alwaysAskBeforeHandling: false, + fileExtensions: ["extension_test1", "extension_test2"], + }); +}); + +/** + * Tests that appendExtension doesn't add duplicates, and that anyway duplicates + * from possibleApplicationHandlers are removed when saving and reloading. + */ +add_task(async function test_store_no_duplicates() { + await deleteHandlerStore(); + + let handlerInfo = getKnownHandlerInfo("example/new"); + handlerInfo.preferredApplicationHandler = webHandlerApp; + handlerInfo.possibleApplicationHandlers.appendElement(webHandlerApp); + handlerInfo.possibleApplicationHandlers.appendElement(localHandlerApp); + handlerInfo.possibleApplicationHandlers.appendElement(localHandlerApp); + handlerInfo.possibleApplicationHandlers.appendElement(webHandlerApp); + handlerInfo.appendExtension("extension_test1"); + handlerInfo.appendExtension("extension_test2"); + handlerInfo.appendExtension("extension_test1"); + handlerInfo.appendExtension("EXTENSION_test1"); + Assert.deepEqual(Array.from(handlerInfo.getFileExtensions()), [ + "extension_test1", + "extension_test2", + ]); + gHandlerService.store(handlerInfo); + + await unloadHandlerStore(); + + let actualHandlerInfo = HandlerServiceTestUtils.getHandlerInfo("example/new"); + HandlerServiceTestUtils.assertHandlerInfoMatches(actualHandlerInfo, { + type: "example/new", + preferredAction: Ci.nsIHandlerInfo.saveToDisk, + alwaysAskBeforeHandling: false, + preferredApplicationHandler: expectedWebHandlerApp, + possibleApplicationHandlers: [ + expectedWebHandlerApp, + expectedLocalHandlerApp, + ], + fileExtensions: ["extension_test1", "extension_test2"], + }); +}); + +/** + * Tests that setFileExtensions doesn't add duplicates. + */ +add_task(async function test_setFileExtensions_no_duplicates() { + await deleteHandlerStore(); + + let handlerInfo = getKnownHandlerInfo("example/new"); + handlerInfo.setFileExtensions("a,b,A,b,c,a"); + let expected = ["a", "b", "c"]; + Assert.deepEqual(Array.from(handlerInfo.getFileExtensions()), expected); + // Test empty extensions, also at begin and end. + handlerInfo.setFileExtensions(",a,,b,A,c,"); + Assert.deepEqual(Array.from(handlerInfo.getFileExtensions()), expected); +}); + +/** + * Tests that "store" deletes properties that have their default values from + * the data store. + * + * File extensions are never deleted once they have been associated. + */ +add_task(async function test_store_deletes_properties_except_extensions() { + await deleteHandlerStore(); + + // Prepare an nsIHandlerInfo instance with all the properties set to values + // that will result in deletions. The preferredAction is also set to a defined + // value so we can more easily verify it later. + let handlerInfo = HandlerServiceTestUtils.getBlankHandlerInfo( + "example/type.savetodisk" + ); + handlerInfo.preferredAction = Ci.nsIHandlerInfo.saveToDisk; + handlerInfo.alwaysAskBeforeHandling = false; + + // All the properties for "example/type.savetodisk" are present in the test + // data, so we load the data before overwriting their values. + await copyTestDataToHandlerStore(); + gHandlerService.store(handlerInfo); + + // Now we can reload the data and verify that no extra values have been kept. + await unloadHandlerStore(); + let actualHandlerInfo = HandlerServiceTestUtils.getHandlerInfo( + "example/type.savetodisk" + ); + HandlerServiceTestUtils.assertHandlerInfoMatches(actualHandlerInfo, { + type: "example/type.savetodisk", + preferredAction: Ci.nsIHandlerInfo.saveToDisk, + alwaysAskBeforeHandling: false, + fileExtensions: ["example_two", "example_three"], + }); +}); + +/** + * Tests the "overrideType" argument of "fillHandlerInfo". + */ +add_task(async function test_fillHandlerInfo_overrideType() { + // Test both MIME types and protocols. + for (let type of [ + "example/type.usesystemdefault", + "examplescheme.usesystemdefault", + ]) { + await deleteHandlerStore(); + + // Create new nsIHandlerInfo instances before loading the test data. + let handlerInfoAbsent = HandlerServiceTestUtils.getHandlerInfo(type + "2"); + + // Fill the nsIHandlerInfo instance using the type that actually exists. + await copyTestDataToHandlerStore(); + gHandlerService.fillHandlerInfo(handlerInfoAbsent, type); + HandlerServiceTestUtils.assertHandlerInfoMatches(handlerInfoAbsent, { + // While the data is populated from another type, the type is unchanged. + type: type + "2", + preferredAction: Ci.nsIHandlerInfo.useSystemDefault, + alwaysAskBeforeHandling: false, + possibleApplicationHandlers: [ + { + name: "Example Possible Handler", + uriTemplate: "http://www.example.com/?url=%s", + }, + ], + }); + } +}); + +/** + * Tests "getTypeFromExtension" including unknown extensions. + */ +add_task(async function test_getTypeFromExtension() { + await copyTestDataToHandlerStore(); + + Assert.equal(gHandlerService.getTypeFromExtension(""), ""); + Assert.equal(gHandlerService.getTypeFromExtension("example_unknown"), ""); + Assert.equal( + gHandlerService.getTypeFromExtension("example_one"), + "example/type.handleinternally" + ); + Assert.equal( + gHandlerService.getTypeFromExtension("EXAMPLE_one"), + "example/type.handleinternally" + ); +}); + +/** + * Checks that the information stored in the handler service instance under + * testing matches the default handlers for the English locale. + */ +function assertAllHandlerInfosMatchDefaultHandlers() { + let handlerInfos = HandlerServiceTestUtils.getAllHandlerInfos(); + + HandlerServiceTestUtils.assertHandlerInfoMatches(handlerInfos.shift(), { + type: "mailto", + preferredActionOSDependent: true, + possibleApplicationHandlers: [ + { + name: "Gmail", + uriTemplate: "https://mail.google.com/mail/?extsrc=mailto&url=%s", + }, + ], + }); + + Assert.equal(handlerInfos.length, 0); +} + +/** + * Tests the default protocol handlers imported from the locale-specific data. + */ +add_task( + { skip_if: () => AppConstants.MOZ_APP_NAME == "thunderbird" }, + async function test_default_protocol_handlers() { + if ( + !Services.prefs.getPrefType("gecko.handlerService.defaultHandlersVersion") + ) { + info("This platform or locale does not have default handlers."); + return; + } + + // This will inject the default protocol handlers for the current locale. + await deleteHandlerStore(); + + await assertAllHandlerInfosMatchDefaultHandlers(); + } +); + +/** + * Tests that the default protocol handlers are not imported again from the + * locale-specific data if they already exist. + */ +add_task( + { skip_if: () => AppConstants.MOZ_APP_NAME == "thunderbird" }, + async function test_default_protocol_handlers_no_duplicates() { + if ( + !Services.prefs.getPrefType("gecko.handlerService.defaultHandlersVersion") + ) { + info("This platform or locale does not have default handlers."); + return; + } + + // This will inject the default protocol handlers for the current locale. + await deleteHandlerStore(); + + // Clear the preference to force injecting again. + Services.prefs.clearUserPref("gecko.handlerService.defaultHandlersVersion"); + + await unloadHandlerStore(); + + // There should be no duplicate handlers in the protocols. + assertAllHandlerInfosMatchDefaultHandlers(); + } +); + +/** + * Ensures forward compatibility by checking that the "store" method preserves + * unknown properties in the test data. + */ +add_task(async function test_store_keeps_unknown_properties() { + // Create a new nsIHandlerInfo instance before loading the test data. + await deleteHandlerStore(); + let handlerInfo = HandlerServiceTestUtils.getHandlerInfo( + "example/type.handleinternally" + ); + + await copyTestDataToHandlerStore(); + gHandlerService.store(handlerInfo); + + await unloadHandlerStore(); + let data = await IOUtils.readJSON(jsonPath); + Assert.equal( + data.mimeTypes["example/type.handleinternally"].unknownProperty, + "preserved" + ); +}); + +/** + * Runs the asyncInit method, ensuring that it successfully inits the store + * and calls the handlersvc-store-initialized topic. + */ +add_task(async function test_async_init() { + await deleteHandlerStore(); + await copyTestDataToHandlerStore(); + gHandlerService.asyncInit(); + await TestUtils.topicObserved("handlersvc-store-initialized"); + await assertAllHandlerInfosMatchTestData(); + + await unloadHandlerStore(); +}); + +/** + * Races the asyncInit method against the sync init (implicit in enumerate), + * to ensure that the store will be synchronously initialized without any + * ill effects. + */ +add_task(async function test_race_async_init() { + await deleteHandlerStore(); + await copyTestDataToHandlerStore(); + let storeInitialized = false; + // Pass a callback to synchronously observe the topic, as a promise would + // resolve asynchronously + TestUtils.topicObserved("handlersvc-store-initialized", () => { + storeInitialized = true; + return true; + }); + gHandlerService.asyncInit(); + Assert.ok(!storeInitialized); + gHandlerService.enumerate(); + Assert.ok(storeInitialized); + await assertAllHandlerInfosMatchTestData(); + + await unloadHandlerStore(); +}); + +/** + * Test saving and reloading an instance of nsIGIOMimeApp. + */ +add_task(async function test_store_gioHandlerApp() { + if (!("@mozilla.org/gio-service;1" in Cc)) { + info("Skipping test because it does not apply to this platform."); + return; + } + + // Create dummy exec file that following won't fail because file not found error + let dummyHandlerFile = FileUtils.getFile("TmpD", ["dummyHandler"]); + dummyHandlerFile.createUnique( + Ci.nsIFile.NORMAL_FILE_TYPE, + parseInt("777", 8) + ); + + // Set up an nsIGIOMimeApp instance for testing. + let handlerApp = Cc["@mozilla.org/gio-service;1"] + .getService(Ci.nsIGIOService) + .createAppFromCommand(dummyHandlerFile.path, "Dummy GIO handler"); + let expectedGIOMimeHandlerApp = { + name: handlerApp.name, + command: handlerApp.command, + }; + + await deleteHandlerStore(); + + let handlerInfo = getKnownHandlerInfo("example/new"); + handlerInfo.preferredApplicationHandler = handlerApp; + handlerInfo.possibleApplicationHandlers.appendElement(handlerApp); + handlerInfo.possibleApplicationHandlers.appendElement(webHandlerApp); + gHandlerService.store(handlerInfo); + + await unloadHandlerStore(); + + let actualHandlerInfo = HandlerServiceTestUtils.getHandlerInfo("example/new"); + HandlerServiceTestUtils.assertHandlerInfoMatches(actualHandlerInfo, { + type: "example/new", + preferredAction: Ci.nsIHandlerInfo.saveToDisk, + alwaysAskBeforeHandling: false, + preferredApplicationHandler: expectedGIOMimeHandlerApp, + possibleApplicationHandlers: [expectedGIOMimeHandlerApp, webHandlerApp], + }); + + await IOUtils.remove(dummyHandlerFile.path); + + // After removing dummyHandlerFile, the handler should disappear from the + // list of possibleApplicationHandlers and preferredAppHandler should be null. + actualHandlerInfo = HandlerServiceTestUtils.getHandlerInfo("example/new"); + HandlerServiceTestUtils.assertHandlerInfoMatches(actualHandlerInfo, { + type: "example/new", + preferredAction: Ci.nsIHandlerInfo.saveToDisk, + alwaysAskBeforeHandling: false, + preferredApplicationHandler: null, + possibleApplicationHandlers: [webHandlerApp], + }); +}); -- cgit v1.2.3