test_Chrome_extensions.js (5027B)
1 /* Any copyright is dedicated to the Public Domain. 2 * http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 const { AMBrowserExtensionsImport, AddonManager } = ChromeUtils.importESModule( 7 "resource://gre/modules/AddonManager.sys.mjs" 8 ); 9 const { AddonTestUtils } = ChromeUtils.importESModule( 10 "resource://testing-common/AddonTestUtils.sys.mjs" 11 ); 12 const { ChromeMigrationUtils } = ChromeUtils.importESModule( 13 "resource:///modules/ChromeMigrationUtils.sys.mjs" 14 ); 15 const { ChromeProfileMigrator } = ChromeUtils.importESModule( 16 "resource:///modules/ChromeProfileMigrator.sys.mjs" 17 ); 18 19 AddonTestUtils.init(this); 20 AddonTestUtils.overrideCertDB(); 21 AddonTestUtils.createAppInfo( 22 "xpcshell@tests.mozilla.org", 23 "XPCShell", 24 "42", 25 "42" 26 ); 27 28 const TEST_SERVER = AddonTestUtils.createHttpServer({ hosts: ["example.com"] }); 29 30 const PROFILE = { 31 id: "Default", 32 name: "Person 1", 33 }; 34 35 const IMPORTED_ADDON_1 = { 36 name: "A Firefox extension", 37 version: "1.0", 38 browser_specific_settings: { gecko: { id: "some-ff@extension" } }, 39 }; 40 41 // Setup chrome user data path for all platforms. 42 ChromeMigrationUtils.getDataPath = () => { 43 return Promise.resolve( 44 do_get_file("Library/Application Support/Google/Chrome/").path 45 ); 46 }; 47 48 const mockAddonRepository = ({ addons = [] } = {}) => { 49 return { 50 async getMappedAddons(browserID, extensionIDs) { 51 Assert.equal(browserID, "chrome", "expected browser ID"); 52 // Sort extension IDs to have a predictable order. 53 extensionIDs.sort(); 54 Assert.deepEqual( 55 extensionIDs, 56 ["fake-extension-1", "fake-extension-2"], 57 "expected an array of 2 extension IDs" 58 ); 59 return Promise.resolve({ 60 addons, 61 matchedIDs: [], 62 unmatchedIDs: [], 63 }); 64 }, 65 }; 66 }; 67 68 add_setup(async function setup() { 69 await AddonTestUtils.promiseStartupManager(); 70 71 // Create a Firefox XPI that we can use during the import. 72 const xpi = AddonTestUtils.createTempWebExtensionFile({ 73 manifest: IMPORTED_ADDON_1, 74 }); 75 TEST_SERVER.registerFile(`/addons/addon-1.xpi`, xpi); 76 77 // Override the `AddonRepository` in `AMBrowserExtensionsImport` with our own 78 // mock so that we control the add-ons that are mapped to the list of Chrome 79 // extension IDs. 80 const addons = [ 81 { 82 id: IMPORTED_ADDON_1.browser_specific_settings.gecko.id, 83 name: IMPORTED_ADDON_1.name, 84 version: IMPORTED_ADDON_1.version, 85 sourceURI: Services.io.newURI(`http://example.com/addons/addon-1.xpi`), 86 icons: {}, 87 }, 88 ]; 89 AMBrowserExtensionsImport._addonRepository = mockAddonRepository({ addons }); 90 91 registerCleanupFunction(() => { 92 // Clear the add-on repository override. 93 AMBrowserExtensionsImport._addonRepository = null; 94 }); 95 }); 96 97 add_task( 98 { pref_set: [["browser.migrate.chrome.extensions.enabled", true]] }, 99 async function test_import_extensions() { 100 const migrator = await MigrationUtils.getMigrator("chrome"); 101 Assert.ok( 102 await migrator.isSourceAvailable(), 103 "Sanity check the source exists" 104 ); 105 106 let promiseTopic = TestUtils.topicObserved( 107 "webextension-imported-addons-pending" 108 ); 109 await promiseMigration( 110 migrator, 111 MigrationUtils.resourceTypes.EXTENSIONS, 112 PROFILE, 113 true 114 ); 115 await promiseTopic; 116 // When this property is `true`, the UI should show a badge on the appmenu 117 // button, and the user can finalize the import later. 118 Assert.ok( 119 AMBrowserExtensionsImport.canCompleteOrCancelInstalls, 120 "expected some add-ons to have been imported" 121 ); 122 123 // Let's actually complete the import programatically below. 124 promiseTopic = TestUtils.topicObserved( 125 "webextension-imported-addons-complete" 126 ); 127 await AMBrowserExtensionsImport.completeInstalls(); 128 await Promise.all([ 129 AddonTestUtils.promiseInstallEvent("onInstallEnded"), 130 promiseTopic, 131 ]); 132 133 // The add-on should be installed and therefore it can be uninstalled. 134 const addon = await AddonManager.getAddonByID( 135 IMPORTED_ADDON_1.browser_specific_settings.gecko.id 136 ); 137 await addon.uninstall(); 138 } 139 ); 140 141 /** 142 * Test that, for now at least, the extension resource type is only made 143 * available for Chrome and none of the derivitive browsers. 144 */ 145 add_task( 146 { pref_set: [["browser.migrate.chrome.extensions.enabled", true]] }, 147 async function test_only_chrome_migrates_extensions() { 148 for (const key of MigrationUtils.availableMigratorKeys) { 149 let migrator = await MigrationUtils.getMigrator(key); 150 151 if (migrator instanceof ChromeProfileMigrator && key != "chrome") { 152 info("Testing migrator with key " + key); 153 Assert.ok( 154 await migrator.isSourceAvailable(), 155 "First check the source exists" 156 ); 157 let resourceTypes = await migrator.getMigrateData(PROFILE); 158 Assert.ok( 159 !(resourceTypes & MigrationUtils.resourceTypes.EXTENSIONS), 160 "Should not offer the extension resource type" 161 ); 162 } 163 } 164 } 165 );