1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/services/sync/tests/unit/head_helpers.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,194 @@ 1.4 +/* Any copyright is dedicated to the Public Domain. 1.5 + http://creativecommons.org/publicdomain/zero/1.0/ */ 1.6 + 1.7 +Cu.import("resource://services-common/async.js"); 1.8 +Cu.import("resource://testing-common/services-common/utils.js"); 1.9 + 1.10 +let provider = { 1.11 + getFile: function(prop, persistent) { 1.12 + persistent.value = true; 1.13 + switch (prop) { 1.14 + case "ExtPrefDL": 1.15 + return [Services.dirsvc.get("CurProcD", Ci.nsIFile)]; 1.16 + default: 1.17 + throw Cr.NS_ERROR_FAILURE; 1.18 + } 1.19 + }, 1.20 + QueryInterface: XPCOMUtils.generateQI([Ci.nsIDirectoryServiceProvider]) 1.21 +}; 1.22 +Services.dirsvc.QueryInterface(Ci.nsIDirectoryService).registerProvider(provider); 1.23 + 1.24 +// This is needed for loadAddonTestFunctions(). 1.25 +let gGlobalScope = this; 1.26 + 1.27 +function ExtensionsTestPath(path) { 1.28 + if (path[0] != "/") { 1.29 + throw Error("Path must begin with '/': " + path); 1.30 + } 1.31 + 1.32 + return "../../../../toolkit/mozapps/extensions/test/xpcshell" + path; 1.33 +} 1.34 + 1.35 +/** 1.36 + * Loads the AddonManager test functions by importing its test file. 1.37 + * 1.38 + * This should be called in the global scope of any test file needing to 1.39 + * interface with the AddonManager. It should only be called once, or the 1.40 + * universe will end. 1.41 + */ 1.42 +function loadAddonTestFunctions() { 1.43 + const path = ExtensionsTestPath("/head_addons.js"); 1.44 + let file = do_get_file(path); 1.45 + let uri = Services.io.newFileURI(file); 1.46 + Services.scriptloader.loadSubScript(uri.spec, gGlobalScope); 1.47 + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); 1.48 +} 1.49 + 1.50 +function getAddonInstall(name) { 1.51 + let f = do_get_file(ExtensionsTestPath("/addons/" + name + ".xpi")); 1.52 + let cb = Async.makeSyncCallback(); 1.53 + AddonManager.getInstallForFile(f, cb); 1.54 + 1.55 + return Async.waitForSyncCallback(cb); 1.56 +} 1.57 + 1.58 +/** 1.59 + * Obtains an addon from the add-on manager by id. 1.60 + * 1.61 + * This is merely a synchronous wrapper. 1.62 + * 1.63 + * @param id 1.64 + * ID of add-on to fetch 1.65 + * @return addon object on success or undefined or null on failure 1.66 + */ 1.67 +function getAddonFromAddonManagerByID(id) { 1.68 + let cb = Async.makeSyncCallback(); 1.69 + AddonManager.getAddonByID(id, cb); 1.70 + return Async.waitForSyncCallback(cb); 1.71 +} 1.72 + 1.73 +/** 1.74 + * Installs an add-on synchronously from an addonInstall 1.75 + * 1.76 + * @param install addonInstall instance to install 1.77 + */ 1.78 +function installAddonFromInstall(install) { 1.79 + let cb = Async.makeSyncCallback(); 1.80 + let listener = {onInstallEnded: cb}; 1.81 + AddonManager.addInstallListener(listener); 1.82 + install.install(); 1.83 + Async.waitForSyncCallback(cb); 1.84 + AddonManager.removeAddonListener(listener); 1.85 + 1.86 + do_check_neq(null, install.addon); 1.87 + do_check_neq(null, install.addon.syncGUID); 1.88 + 1.89 + return install.addon; 1.90 +} 1.91 + 1.92 +/** 1.93 + * Convenience function to install an add-on from the extensions unit tests. 1.94 + * 1.95 + * @param name 1.96 + * String name of add-on to install. e.g. test_install1 1.97 + * @return addon object that was installed 1.98 + */ 1.99 +function installAddon(name) { 1.100 + let install = getAddonInstall(name); 1.101 + do_check_neq(null, install); 1.102 + return installAddonFromInstall(install); 1.103 +} 1.104 + 1.105 +/** 1.106 + * Convenience function to uninstall an add-on synchronously. 1.107 + * 1.108 + * @param addon 1.109 + * Addon instance to uninstall 1.110 + */ 1.111 +function uninstallAddon(addon) { 1.112 + let cb = Async.makeSyncCallback(); 1.113 + let listener = {onUninstalled: function(uninstalled) { 1.114 + if (uninstalled.id == addon.id) { 1.115 + AddonManager.removeAddonListener(listener); 1.116 + cb(uninstalled); 1.117 + } 1.118 + }}; 1.119 + 1.120 + AddonManager.addAddonListener(listener); 1.121 + addon.uninstall(); 1.122 + Async.waitForSyncCallback(cb); 1.123 +} 1.124 + 1.125 +function generateNewKeys(collectionKeys, collections=null) { 1.126 + let wbo = collectionKeys.generateNewKeysWBO(collections); 1.127 + let modified = new_timestamp(); 1.128 + collectionKeys.setContents(wbo.cleartext, modified); 1.129 +} 1.130 + 1.131 +// Helpers for testing open tabs. 1.132 +// These reflect part of the internal structure of TabEngine, 1.133 +// and stub part of Service.wm. 1.134 + 1.135 +function mockShouldSkipWindow (win) { 1.136 + return win.closed || 1.137 + win.mockIsPrivate; 1.138 +} 1.139 + 1.140 +function mockGetTabState (tab) { 1.141 + return tab; 1.142 +} 1.143 + 1.144 +function mockGetWindowEnumerator(url, numWindows, numTabs) { 1.145 + let elements = []; 1.146 + for (let w = 0; w < numWindows; ++w) { 1.147 + let tabs = []; 1.148 + let win = { 1.149 + closed: false, 1.150 + mockIsPrivate: false, 1.151 + gBrowser: { 1.152 + tabs: tabs, 1.153 + }, 1.154 + }; 1.155 + elements.push(win); 1.156 + 1.157 + for (let t = 0; t < numTabs; ++t) { 1.158 + tabs.push(TestingUtils.deepCopy({ 1.159 + index: 1, 1.160 + entries: [{ 1.161 + url: ((typeof url == "string") ? url : url()), 1.162 + title: "title" 1.163 + }], 1.164 + attributes: { 1.165 + image: "image" 1.166 + }, 1.167 + lastAccessed: 1499 1.168 + })); 1.169 + } 1.170 + } 1.171 + 1.172 + // Always include a closed window and a private window. 1.173 + elements.push({ 1.174 + closed: true, 1.175 + mockIsPrivate: false, 1.176 + gBrowser: { 1.177 + tabs: [], 1.178 + }, 1.179 + }); 1.180 + 1.181 + elements.push({ 1.182 + closed: false, 1.183 + mockIsPrivate: true, 1.184 + gBrowser: { 1.185 + tabs: [], 1.186 + }, 1.187 + }); 1.188 + 1.189 + return { 1.190 + hasMoreElements: function () { 1.191 + return elements.length; 1.192 + }, 1.193 + getNext: function () { 1.194 + return elements.shift(); 1.195 + }, 1.196 + }; 1.197 +}