michael@0: /* Any copyright is dedicated to the Public Domain. michael@0: http://creativecommons.org/publicdomain/zero/1.0/ */ michael@0: michael@0: Cu.import("resource://services-common/async.js"); michael@0: Cu.import("resource://testing-common/services-common/utils.js"); michael@0: michael@0: let provider = { michael@0: getFile: function(prop, persistent) { michael@0: persistent.value = true; michael@0: switch (prop) { michael@0: case "ExtPrefDL": michael@0: return [Services.dirsvc.get("CurProcD", Ci.nsIFile)]; michael@0: default: michael@0: throw Cr.NS_ERROR_FAILURE; michael@0: } michael@0: }, michael@0: QueryInterface: XPCOMUtils.generateQI([Ci.nsIDirectoryServiceProvider]) michael@0: }; michael@0: Services.dirsvc.QueryInterface(Ci.nsIDirectoryService).registerProvider(provider); michael@0: michael@0: // This is needed for loadAddonTestFunctions(). michael@0: let gGlobalScope = this; michael@0: michael@0: function ExtensionsTestPath(path) { michael@0: if (path[0] != "/") { michael@0: throw Error("Path must begin with '/': " + path); michael@0: } michael@0: michael@0: return "../../../../toolkit/mozapps/extensions/test/xpcshell" + path; michael@0: } michael@0: michael@0: /** michael@0: * Loads the AddonManager test functions by importing its test file. michael@0: * michael@0: * This should be called in the global scope of any test file needing to michael@0: * interface with the AddonManager. It should only be called once, or the michael@0: * universe will end. michael@0: */ michael@0: function loadAddonTestFunctions() { michael@0: const path = ExtensionsTestPath("/head_addons.js"); michael@0: let file = do_get_file(path); michael@0: let uri = Services.io.newFileURI(file); michael@0: Services.scriptloader.loadSubScript(uri.spec, gGlobalScope); michael@0: createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); michael@0: } michael@0: michael@0: function getAddonInstall(name) { michael@0: let f = do_get_file(ExtensionsTestPath("/addons/" + name + ".xpi")); michael@0: let cb = Async.makeSyncCallback(); michael@0: AddonManager.getInstallForFile(f, cb); michael@0: michael@0: return Async.waitForSyncCallback(cb); michael@0: } michael@0: michael@0: /** michael@0: * Obtains an addon from the add-on manager by id. michael@0: * michael@0: * This is merely a synchronous wrapper. michael@0: * michael@0: * @param id michael@0: * ID of add-on to fetch michael@0: * @return addon object on success or undefined or null on failure michael@0: */ michael@0: function getAddonFromAddonManagerByID(id) { michael@0: let cb = Async.makeSyncCallback(); michael@0: AddonManager.getAddonByID(id, cb); michael@0: return Async.waitForSyncCallback(cb); michael@0: } michael@0: michael@0: /** michael@0: * Installs an add-on synchronously from an addonInstall michael@0: * michael@0: * @param install addonInstall instance to install michael@0: */ michael@0: function installAddonFromInstall(install) { michael@0: let cb = Async.makeSyncCallback(); michael@0: let listener = {onInstallEnded: cb}; michael@0: AddonManager.addInstallListener(listener); michael@0: install.install(); michael@0: Async.waitForSyncCallback(cb); michael@0: AddonManager.removeAddonListener(listener); michael@0: michael@0: do_check_neq(null, install.addon); michael@0: do_check_neq(null, install.addon.syncGUID); michael@0: michael@0: return install.addon; michael@0: } michael@0: michael@0: /** michael@0: * Convenience function to install an add-on from the extensions unit tests. michael@0: * michael@0: * @param name michael@0: * String name of add-on to install. e.g. test_install1 michael@0: * @return addon object that was installed michael@0: */ michael@0: function installAddon(name) { michael@0: let install = getAddonInstall(name); michael@0: do_check_neq(null, install); michael@0: return installAddonFromInstall(install); michael@0: } michael@0: michael@0: /** michael@0: * Convenience function to uninstall an add-on synchronously. michael@0: * michael@0: * @param addon michael@0: * Addon instance to uninstall michael@0: */ michael@0: function uninstallAddon(addon) { michael@0: let cb = Async.makeSyncCallback(); michael@0: let listener = {onUninstalled: function(uninstalled) { michael@0: if (uninstalled.id == addon.id) { michael@0: AddonManager.removeAddonListener(listener); michael@0: cb(uninstalled); michael@0: } michael@0: }}; michael@0: michael@0: AddonManager.addAddonListener(listener); michael@0: addon.uninstall(); michael@0: Async.waitForSyncCallback(cb); michael@0: } michael@0: michael@0: function generateNewKeys(collectionKeys, collections=null) { michael@0: let wbo = collectionKeys.generateNewKeysWBO(collections); michael@0: let modified = new_timestamp(); michael@0: collectionKeys.setContents(wbo.cleartext, modified); michael@0: } michael@0: michael@0: // Helpers for testing open tabs. michael@0: // These reflect part of the internal structure of TabEngine, michael@0: // and stub part of Service.wm. michael@0: michael@0: function mockShouldSkipWindow (win) { michael@0: return win.closed || michael@0: win.mockIsPrivate; michael@0: } michael@0: michael@0: function mockGetTabState (tab) { michael@0: return tab; michael@0: } michael@0: michael@0: function mockGetWindowEnumerator(url, numWindows, numTabs) { michael@0: let elements = []; michael@0: for (let w = 0; w < numWindows; ++w) { michael@0: let tabs = []; michael@0: let win = { michael@0: closed: false, michael@0: mockIsPrivate: false, michael@0: gBrowser: { michael@0: tabs: tabs, michael@0: }, michael@0: }; michael@0: elements.push(win); michael@0: michael@0: for (let t = 0; t < numTabs; ++t) { michael@0: tabs.push(TestingUtils.deepCopy({ michael@0: index: 1, michael@0: entries: [{ michael@0: url: ((typeof url == "string") ? url : url()), michael@0: title: "title" michael@0: }], michael@0: attributes: { michael@0: image: "image" michael@0: }, michael@0: lastAccessed: 1499 michael@0: })); michael@0: } michael@0: } michael@0: michael@0: // Always include a closed window and a private window. michael@0: elements.push({ michael@0: closed: true, michael@0: mockIsPrivate: false, michael@0: gBrowser: { michael@0: tabs: [], michael@0: }, michael@0: }); michael@0: michael@0: elements.push({ michael@0: closed: false, michael@0: mockIsPrivate: true, michael@0: gBrowser: { michael@0: tabs: [], michael@0: }, michael@0: }); michael@0: michael@0: return { michael@0: hasMoreElements: function () { michael@0: return elements.length; michael@0: }, michael@0: getNext: function () { michael@0: return elements.shift(); michael@0: }, michael@0: }; michael@0: }