diff options
Diffstat (limited to 'toolkit/mozapps/extensions')
624 files changed, 16155 insertions, 37342 deletions
diff --git a/toolkit/mozapps/extensions/.eslintrc.js b/toolkit/mozapps/extensions/.eslintrc.js deleted file mode 100644 index 2b90bd053..000000000 --- a/toolkit/mozapps/extensions/.eslintrc.js +++ /dev/null @@ -1,8 +0,0 @@ -"use strict"; - -module.exports = { // eslint-disable-line no-undef - "rules": { - // No using undeclared variables - "no-undef": "error", - } -}; diff --git a/toolkit/mozapps/extensions/AddonContentPolicy.cpp b/toolkit/mozapps/extensions/AddonContentPolicy.cpp deleted file mode 100644 index 90e53b2ea..000000000 --- a/toolkit/mozapps/extensions/AddonContentPolicy.cpp +++ /dev/null @@ -1,478 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* 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/. */ - -#include "AddonContentPolicy.h" - -#include "mozilla/dom/nsCSPUtils.h" -#include "nsCOMPtr.h" -#include "nsContentPolicyUtils.h" -#include "nsContentTypeParser.h" -#include "nsContentUtils.h" -#include "nsIConsoleService.h" -#include "nsIContentSecurityPolicy.h" -#include "nsIContent.h" -#include "nsIDocument.h" -#include "nsIEffectiveTLDService.h" -#include "nsIScriptError.h" -#include "nsIStringBundle.h" -#include "nsIUUIDGenerator.h" -#include "nsIURI.h" -#include "nsNetCID.h" -#include "nsNetUtil.h" - -using namespace mozilla; - -/* Enforces content policies for WebExtension scopes. Currently: - * - * - Prevents loading scripts with a non-default JavaScript version. - * - Checks custom content security policies for sufficiently stringent - * script-src and object-src directives. - */ - -#define VERSIONED_JS_BLOCKED_MESSAGE \ - u"Versioned JavaScript is a non-standard, deprecated extension, and is " \ - u"not supported in WebExtension code. For alternatives, please see: " \ - u"https://developer.mozilla.org/Add-ons/WebExtensions/Tips" - -AddonContentPolicy::AddonContentPolicy() -{ -} - -AddonContentPolicy::~AddonContentPolicy() -{ -} - -NS_IMPL_ISUPPORTS(AddonContentPolicy, nsIContentPolicy, nsIAddonContentPolicy) - -static nsresult -GetWindowIDFromContext(nsISupports* aContext, uint64_t *aResult) -{ - NS_ENSURE_TRUE(aContext, NS_ERROR_FAILURE); - - nsCOMPtr<nsIContent> content = do_QueryInterface(aContext); - NS_ENSURE_TRUE(content, NS_ERROR_FAILURE); - - nsCOMPtr<nsIDocument> document = content->OwnerDoc(); - NS_ENSURE_TRUE(document, NS_ERROR_FAILURE); - - nsCOMPtr<nsPIDOMWindowInner> window = document->GetInnerWindow(); - NS_ENSURE_TRUE(window, NS_ERROR_FAILURE); - - *aResult = window->WindowID(); - return NS_OK; -} - -static nsresult -LogMessage(const nsAString &aMessage, nsIURI* aSourceURI, const nsAString &aSourceSample, - nsISupports* aContext) -{ - nsCOMPtr<nsIScriptError> error = do_CreateInstance(NS_SCRIPTERROR_CONTRACTID); - NS_ENSURE_TRUE(error, NS_ERROR_OUT_OF_MEMORY); - - nsCString sourceName = aSourceURI->GetSpecOrDefault(); - - uint64_t windowID = 0; - GetWindowIDFromContext(aContext, &windowID); - - nsresult rv = - error->InitWithWindowID(aMessage, NS_ConvertUTF8toUTF16(sourceName), - aSourceSample, 0, 0, nsIScriptError::errorFlag, - "JavaScript", windowID); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr<nsIConsoleService> console = do_GetService(NS_CONSOLESERVICE_CONTRACTID); - NS_ENSURE_TRUE(console, NS_ERROR_OUT_OF_MEMORY); - - console->LogMessage(error); - return NS_OK; -} - - -// Content policy enforcement: - -NS_IMETHODIMP -AddonContentPolicy::ShouldLoad(uint32_t aContentType, - nsIURI* aContentLocation, - nsIURI* aRequestOrigin, - nsISupports* aContext, - const nsACString& aMimeTypeGuess, - nsISupports* aExtra, - nsIPrincipal* aRequestPrincipal, - int16_t* aShouldLoad) -{ - MOZ_ASSERT(aContentType == nsContentUtils::InternalContentPolicyTypeToExternal(aContentType), - "We should only see external content policy types here."); - - *aShouldLoad = nsIContentPolicy::ACCEPT; - - if (!aRequestOrigin) { - return NS_OK; - } - - // Only apply this policy to requests from documents loaded from - // moz-extension URLs, or to resources being loaded from moz-extension URLs. - bool equals; - if (!((NS_SUCCEEDED(aContentLocation->SchemeIs("moz-extension", &equals)) && equals) || - (NS_SUCCEEDED(aRequestOrigin->SchemeIs("moz-extension", &equals)) && equals))) { - return NS_OK; - } - - if (aContentType == nsIContentPolicy::TYPE_SCRIPT) { - NS_ConvertUTF8toUTF16 typeString(aMimeTypeGuess); - nsContentTypeParser mimeParser(typeString); - - // Reject attempts to load JavaScript scripts with a non-default version. - nsAutoString mimeType, version; - if (NS_SUCCEEDED(mimeParser.GetType(mimeType)) && - nsContentUtils::IsJavascriptMIMEType(mimeType) && - NS_SUCCEEDED(mimeParser.GetParameter("version", version))) { - *aShouldLoad = nsIContentPolicy::REJECT_REQUEST; - - LogMessage(NS_MULTILINE_LITERAL_STRING(VERSIONED_JS_BLOCKED_MESSAGE), - aRequestOrigin, typeString, aContext); - return NS_OK; - } - } - - return NS_OK; -} - -NS_IMETHODIMP -AddonContentPolicy::ShouldProcess(uint32_t aContentType, - nsIURI* aContentLocation, - nsIURI* aRequestOrigin, - nsISupports* aRequestingContext, - const nsACString& aMimeTypeGuess, - nsISupports* aExtra, - nsIPrincipal* aRequestPrincipal, - int16_t* aShouldProcess) -{ - MOZ_ASSERT(aContentType == nsContentUtils::InternalContentPolicyTypeToExternal(aContentType), - "We should only see external content policy types here."); - - *aShouldProcess = nsIContentPolicy::ACCEPT; - return NS_OK; -} - - -// CSP Validation: - -static const char* allowedSchemes[] = { - "blob", - "filesystem", - nullptr -}; - -static const char* allowedHostSchemes[] = { - "https", - "moz-extension", - nullptr -}; - -/** - * Validates a CSP directive to ensure that it is sufficiently stringent. - * In particular, ensures that: - * - * - No remote sources are allowed other than from https: schemes - * - * - No remote sources specify host wildcards for generic domains - * (*.blogspot.com, *.com, *) - * - * - All remote sources and local extension sources specify a host - * - * - No scheme sources are allowed other than blob:, filesystem:, - * moz-extension:, and https: - * - * - No keyword sources are allowed other than 'none', 'self', 'unsafe-eval', - * and hash sources. - */ -class CSPValidator final : public nsCSPSrcVisitor { - public: - CSPValidator(nsAString& aURL, CSPDirective aDirective, bool aDirectiveRequired = true) : - mURL(aURL), - mDirective(CSP_CSPDirectiveToString(aDirective)), - mFoundSelf(false) - { - // Start with the default error message for a missing directive, since no - // visitors will be called if the directive isn't present. - if (aDirectiveRequired) { - FormatError("csp.error.missing-directive"); - } - } - - // Visitors - - bool visitSchemeSrc(const nsCSPSchemeSrc& src) override - { - nsAutoString scheme; - src.getScheme(scheme); - - if (SchemeInList(scheme, allowedHostSchemes)) { - FormatError("csp.error.missing-host", scheme); - return false; - } - if (!SchemeInList(scheme, allowedSchemes)) { - FormatError("csp.error.illegal-protocol", scheme); - return false; - } - return true; - }; - - bool visitHostSrc(const nsCSPHostSrc& src) override - { - nsAutoString scheme, host; - - src.getScheme(scheme); - src.getHost(host); - - if (scheme.LowerCaseEqualsLiteral("https")) { - if (!HostIsAllowed(host)) { - FormatError("csp.error.illegal-host-wildcard", scheme); - return false; - } - } else if (scheme.LowerCaseEqualsLiteral("moz-extension")) { - // The CSP parser silently converts 'self' keywords to the origin - // URL, so we need to reconstruct the URL to see if it was present. - if (!mFoundSelf) { - nsAutoString url(u"moz-extension://"); - url.Append(host); - - mFoundSelf = url.Equals(mURL); - } - - if (host.IsEmpty() || host.EqualsLiteral("*")) { - FormatError("csp.error.missing-host", scheme); - return false; - } - } else if (!SchemeInList(scheme, allowedSchemes)) { - FormatError("csp.error.illegal-protocol", scheme); - return false; - } - - return true; - }; - - bool visitKeywordSrc(const nsCSPKeywordSrc& src) override - { - switch (src.getKeyword()) { - case CSP_NONE: - case CSP_SELF: - case CSP_UNSAFE_EVAL: - return true; - - default: - NS_ConvertASCIItoUTF16 keyword(CSP_EnumToKeyword(src.getKeyword())); - - FormatError("csp.error.illegal-keyword", keyword); - return false; - } - }; - - bool visitNonceSrc(const nsCSPNonceSrc& src) override - { - FormatError("csp.error.illegal-keyword", NS_LITERAL_STRING("'nonce-*'")); - return false; - }; - - bool visitHashSrc(const nsCSPHashSrc& src) override - { - return true; - }; - - // Accessors - - inline nsAString& GetError() - { - return mError; - }; - - inline bool FoundSelf() - { - return mFoundSelf; - }; - - - // Formatters - - template <typename... T> - inline void FormatError(const char* aName, const T ...aParams) - { - const char16_t* params[] = { mDirective.get(), aParams.get()... }; - FormatErrorParams(aName, params, MOZ_ARRAY_LENGTH(params)); - }; - - private: - // Validators - - bool HostIsAllowed(nsAString& host) - { - if (host.First() == '*') { - if (host.EqualsLiteral("*") || host[1] != '.') { - return false; - } - - host.Cut(0, 2); - - nsCOMPtr<nsIEffectiveTLDService> tldService = - do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID); - - if (!tldService) { - return false; - } - - NS_ConvertUTF16toUTF8 cHost(host); - nsAutoCString publicSuffix; - - nsresult rv = tldService->GetPublicSuffixFromHost(cHost, publicSuffix); - - return NS_SUCCEEDED(rv) && !cHost.Equals(publicSuffix); - } - - return true; - }; - - bool SchemeInList(nsAString& scheme, const char** schemes) - { - for (; *schemes; schemes++) { - if (scheme.LowerCaseEqualsASCII(*schemes)) { - return true; - } - } - return false; - }; - - - // Formatters - - already_AddRefed<nsIStringBundle> - GetStringBundle() - { - nsCOMPtr<nsIStringBundleService> sbs = - mozilla::services::GetStringBundleService(); - NS_ENSURE_TRUE(sbs, nullptr); - - nsCOMPtr<nsIStringBundle> stringBundle; - sbs->CreateBundle("chrome://global/locale/extensions.properties", - getter_AddRefs(stringBundle)); - - return stringBundle.forget(); - }; - - void FormatErrorParams(const char* aName, const char16_t** aParams, int32_t aLength) - { - nsresult rv = NS_ERROR_FAILURE; - - nsCOMPtr<nsIStringBundle> stringBundle = GetStringBundle(); - - if (stringBundle) { - NS_ConvertASCIItoUTF16 name(aName); - - rv = stringBundle->FormatStringFromName(name.get(), aParams, aLength, - getter_Copies(mError)); - } - - if (NS_WARN_IF(NS_FAILED(rv))) { - mError.AssignLiteral("An unexpected error occurred"); - } - }; - - - // Data members - - nsAutoString mURL; - NS_ConvertASCIItoUTF16 mDirective; - nsXPIDLString mError; - - bool mFoundSelf; -}; - -/** - * Validates a custom content security policy string for use by an add-on. - * In particular, ensures that: - * - * - Both object-src and script-src directives are present, and meet - * the policies required by the CSPValidator class - * - * - The script-src directive includes the source 'self' - */ -NS_IMETHODIMP -AddonContentPolicy::ValidateAddonCSP(const nsAString& aPolicyString, - nsAString& aResult) -{ - nsresult rv; - - // Validate against a randomly-generated extension origin. - // There is no add-on-specific behavior in the CSP code, beyond the ability - // for add-ons to specify a custom policy, but the parser requires a valid - // origin in order to operate correctly. - nsAutoString url(u"moz-extension://"); - { - nsCOMPtr<nsIUUIDGenerator> uuidgen = services::GetUUIDGenerator(); - NS_ENSURE_TRUE(uuidgen, NS_ERROR_FAILURE); - - nsID id; - rv = uuidgen->GenerateUUIDInPlace(&id); - NS_ENSURE_SUCCESS(rv, rv); - - char idString[NSID_LENGTH]; - id.ToProvidedString(idString); - - MOZ_RELEASE_ASSERT(idString[0] == '{' && idString[NSID_LENGTH - 2] == '}', - "UUID generator did not return a valid UUID"); - - url.AppendASCII(idString + 1, NSID_LENGTH - 3); - } - - - RefPtr<BasePrincipal> principal = - BasePrincipal::CreateCodebasePrincipal(NS_ConvertUTF16toUTF8(url)); - - nsCOMPtr<nsIContentSecurityPolicy> csp; - rv = principal->EnsureCSP(nullptr, getter_AddRefs(csp)); - NS_ENSURE_SUCCESS(rv, rv); - - - csp->AppendPolicy(aPolicyString, false, false); - - const nsCSPPolicy* policy = csp->GetPolicy(0); - if (!policy) { - CSPValidator validator(url, nsIContentSecurityPolicy::SCRIPT_SRC_DIRECTIVE); - aResult.Assign(validator.GetError()); - return NS_OK; - } - - bool haveValidDefaultSrc = false; - { - CSPDirective directive = nsIContentSecurityPolicy::DEFAULT_SRC_DIRECTIVE; - CSPValidator validator(url, directive); - - haveValidDefaultSrc = policy->visitDirectiveSrcs(directive, &validator); - } - - aResult.SetIsVoid(true); - { - CSPDirective directive = nsIContentSecurityPolicy::SCRIPT_SRC_DIRECTIVE; - CSPValidator validator(url, directive, !haveValidDefaultSrc); - - if (!policy->visitDirectiveSrcs(directive, &validator)) { - aResult.Assign(validator.GetError()); - } else if (!validator.FoundSelf()) { - validator.FormatError("csp.error.missing-source", NS_LITERAL_STRING("'self'")); - aResult.Assign(validator.GetError()); - } - } - - if (aResult.IsVoid()) { - CSPDirective directive = nsIContentSecurityPolicy::OBJECT_SRC_DIRECTIVE; - CSPValidator validator(url, directive, !haveValidDefaultSrc); - - if (!policy->visitDirectiveSrcs(directive, &validator)) { - aResult.Assign(validator.GetError()); - } - } - - return NS_OK; -} diff --git a/toolkit/mozapps/extensions/AddonContentPolicy.h b/toolkit/mozapps/extensions/AddonContentPolicy.h deleted file mode 100644 index 4c8af4828..000000000 --- a/toolkit/mozapps/extensions/AddonContentPolicy.h +++ /dev/null @@ -1,22 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* 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/. */ - -#include "nsIContentPolicy.h" -#include "nsIAddonPolicyService.h" - -class AddonContentPolicy : public nsIContentPolicy, - public nsIAddonContentPolicy -{ -protected: - virtual ~AddonContentPolicy(); - -public: - AddonContentPolicy(); - - NS_DECL_ISUPPORTS - NS_DECL_NSICONTENTPOLICY - NS_DECL_NSIADDONCONTENTPOLICY -}; diff --git a/toolkit/mozapps/extensions/AddonManager.jsm b/toolkit/mozapps/extensions/AddonManager.jsm index c5cb80091..3913c2088 100644 --- a/toolkit/mozapps/extensions/AddonManager.jsm +++ b/toolkit/mozapps/extensions/AddonManager.jsm @@ -21,9 +21,6 @@ if ("@mozilla.org/xre/app-info;1" in Cc) { } } -Cu.import("resource://gre/modules/AppConstants.jsm"); - -const MOZ_COMPATIBILITY_NIGHTLY = !['aurora', 'beta', 'release', 'esr'].includes(AppConstants.MOZ_UPDATE_CHANNEL); const PREF_BLOCKLIST_PINGCOUNTVERSION = "extensions.blocklist.pingCountVersion"; const PREF_DEFAULT_PROVIDERS_ENABLED = "extensions.defaultProviders.enabled"; @@ -36,18 +33,10 @@ const PREF_EM_CHECK_UPDATE_SECURITY = "extensions.checkUpdateSecurity"; const PREF_EM_UPDATE_BACKGROUND_URL = "extensions.update.background.url"; const PREF_APP_UPDATE_ENABLED = "app.update.enabled"; const PREF_APP_UPDATE_AUTO = "app.update.auto"; -const PREF_EM_HOTFIX_ID = "extensions.hotfix.id"; -const PREF_EM_HOTFIX_LASTVERSION = "extensions.hotfix.lastVersion"; -const PREF_EM_HOTFIX_URL = "extensions.hotfix.url"; -const PREF_EM_CERT_CHECKATTRIBUTES = "extensions.hotfix.cert.checkAttributes"; -const PREF_EM_HOTFIX_CERTS = "extensions.hotfix.certs."; const PREF_MATCH_OS_LOCALE = "intl.locale.matchOS"; const PREF_SELECTED_LOCALE = "general.useragent.locale"; const UNKNOWN_XPCOM_ABI = "unknownABI"; -const PREF_MIN_WEBEXT_PLATFORM_VERSION = "extensions.webExtensionsMinPlatformVersion"; -const PREF_WEBAPI_TESTING = "extensions.webapi.testing"; - const UPDATE_REQUEST_VERSION = 2; const CATEGORY_UPDATE_PARAMS = "extension-update-params"; @@ -59,21 +48,12 @@ const FILE_BLOCKLIST = "blocklist.xml"; const BRANCH_REGEXP = /^([^\.]+\.[0-9]+[a-z]*).*/gi; const PREF_EM_CHECK_COMPATIBILITY_BASE = "extensions.checkCompatibility"; -var PREF_EM_CHECK_COMPATIBILITY = MOZ_COMPATIBILITY_NIGHTLY ? - PREF_EM_CHECK_COMPATIBILITY_BASE + ".nightly" : - undefined; +var PREF_EM_CHECK_COMPATIBILITY; const TOOLKIT_ID = "toolkit@mozilla.org"; const VALID_TYPES_REGEXP = /^[\w\-]+$/; -const WEBAPI_INSTALL_HOSTS = ["addons.mozilla.org", "testpilot.firefox.com"]; -const WEBAPI_TEST_INSTALL_HOSTS = [ - "addons.allizom.org", "addons-dev.allizom.org", - "testpilot.stage.mozaws.net", "testpilot.dev.mozaws.net", - "example.com", -]; - Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/AsyncShutdown.jsm"); @@ -84,18 +64,15 @@ XPCOMUtils.defineLazyModuleGetter(this, "Promise", "resource://gre/modules/Promise.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "AddonRepository", "resource://gre/modules/addons/AddonRepository.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "Extension", - "resource://gre/modules/Extension.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "FileUtils", "resource://gre/modules/FileUtils.jsm"); -XPCOMUtils.defineLazyGetter(this, "CertUtils", function() { +XPCOMUtils.defineLazyGetter(this, "CertUtils", function certUtilsLazyGetter() { let certUtils = {}; Components.utils.import("resource://gre/modules/CertUtils.jsm", certUtils); return certUtils; }); -const INTEGER = /^[1-9]\d*$/; this.EXPORTED_SYMBOLS = [ "AddonManager", "AddonManagerPrivate" ]; @@ -147,13 +124,13 @@ function providerName(aProvider) { * parent 'addons' level logger accordingly. */ var PrefObserver = { - init: function() { + init: function PrefObserver_init() { Services.prefs.addObserver(PREF_LOGGING_ENABLED, this, false); Services.obs.addObserver(this, "xpcom-shutdown", false); this.observe(null, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, PREF_LOGGING_ENABLED); }, - observe: function(aSubject, aTopic, aData) { + observe: function PrefObserver_observe(aSubject, aTopic, aData) { if (aTopic == "xpcom-shutdown") { Services.prefs.removeObserver(PREF_LOGGING_ENABLED, this); Services.obs.removeObserver(this, "xpcom-shutdown"); @@ -194,19 +171,6 @@ function safeCall(aCallback, ...aArgs) { } /** - * Creates a function that will call the passed callback catching and logging - * any exceptions. - * - * @param aCallback - * The callback method to call - */ -function makeSafe(aCallback) { - return function(...aArgs) { - safeCall(aCallback, ...aArgs); - } -} - -/** * Report an exception thrown by a provider API method. */ function reportProviderError(aProvider, aMethod, aError) { @@ -258,7 +222,7 @@ function callProviderAsync(aProvider, aMethod, ...aArgs) { let callback = aArgs[aArgs.length - 1]; if (!(aMethod in aProvider)) { callback(undefined); - return undefined; + return; } try { return aProvider[aMethod].apply(aProvider, aArgs); @@ -266,31 +230,11 @@ function callProviderAsync(aProvider, aMethod, ...aArgs) { catch (e) { reportProviderError(aProvider, aMethod, e); callback(undefined); - return undefined; + return; } } /** - * Calls a method on a provider if it exists and consumes any thrown exception. - * Parameters after aMethod are passed to aProvider.aMethod() and an additional - * callback is added for the provider to return a result to. - * - * @param aProvider - * The provider to call - * @param aMethod - * The method name to call - * @return {Promise} - * @resolves The result the provider returns, or |undefined| if the provider - * does not implement the method or the method throws. - * @rejects Never - */ -function promiseCallProvider(aProvider, aMethod, ...aArgs) { - return new Promise(resolve => { - callProviderAsync(aProvider, aMethod, ...aArgs, resolve); - }); -} - -/** * Gets the currently selected locale for display. * @return the selected locale or "en-US" if none is selected */ @@ -317,28 +261,35 @@ function getLocale() { return "en-US"; } -function webAPIForAddon(addon) { - if (!addon) { - return null; - } +/** + * Previously the APIs for installing add-ons from webpages accepted nsIURI + * arguments for the installing page. They now take an nsIPrincipal but for now + * maintain backwards compatibility by converting an nsIURI to an nsIPrincipal. + * + * @param aPrincipalOrURI + * The argument passed to the API function. Can be null, an nsIURI or + * an nsIPrincipal. + * @return an nsIPrincipal. + */ +function ensurePrincipal(principalOrURI) { + if (principalOrURI instanceof Ci.nsIPrincipal) + return principalOrURI; - let result = {}; + logger.warn("Deprecated API call, please pass a non-null nsIPrincipal instead of an nsIURI"); - // By default just pass through any plain property, the webidl will - // control access. Also filter out private properties, regular Addon - // objects are okay but MockAddon used in tests has non-serializable - // private properties. - for (let prop in addon) { - if (prop[0] != "_" && typeof(addon[prop]) != "function") { - result[prop] = addon[prop]; - } + // Previously a null installing URI meant allowing the install regardless. + if (!principalOrURI) { + return Services.scriptSecurityManager.getSystemPrincipal(); } - // A few properties are computed for a nicer API - result.isEnabled = !addon.userDisabled; - result.canUninstall = Boolean(addon.permissions & AddonManager.PERM_CAN_UNINSTALL); + if (principalOrURI instanceof Ci.nsIURI) { + return Services.scriptSecurityManager.createCodebasePrincipal(principalOrURI, { + inBrowser: true + }); + } - return result; + // Just return whatever we have, the API method will log an error about it. + return principalOrURI; } /** @@ -373,7 +324,7 @@ AsyncObjectCaller.prototype = { * Passes the next object to the listener or calls noMoreObjects if there * are none left. */ - callNext: function() { + callNext: function AOC_callNext() { if (this.objects.length == 0) { this.listener.noMoreObjects(this); return; @@ -398,7 +349,7 @@ function BrowserListener(aBrowser, aInstallingPrincipal, aInstalls) { this.installCount = aInstalls.length; aBrowser.addProgressListener(this, Ci.nsIWebProgress.NOTIFY_LOCATION); - Services.obs.addObserver(this, "message-manager-close", true); + Services.obs.addObserver(this, "message-manager-disconnect", true); for (let install of this.installs) install.addListener(this); @@ -417,7 +368,7 @@ BrowserListener.prototype = { return; this.registered = false; - Services.obs.removeObserver(this, "message-manager-close"); + Services.obs.removeObserver(this, "message-manager-disconnect"); // The browser may have already been detached if (this.browser.removeProgressListener) this.browser.removeProgressListener(this); @@ -499,7 +450,7 @@ AddonAuthor.prototype = { url: null, // Returns the author's name, defaulting to the empty string - toString: function() { + toString: function AddonAuthor_toString() { return this.name || ""; } } @@ -543,7 +494,7 @@ AddonScreenshot.prototype = { caption: null, // Returns the screenshot URL, defaulting to the empty string - toString: function() { + toString: function AddonScreenshot_toString() { return this.url || ""; } } @@ -649,9 +600,11 @@ function AddonType(aID, aLocaleURI, aLocaleKey, aViewType, aUIPriority, aFlags) this.flags = aFlags; if (aLocaleURI) { - XPCOMUtils.defineLazyGetter(this, "name", () => { + this.__defineGetter__("name", function nameGetter() { + delete this.name; let bundle = Services.strings.createBundle(aLocaleURI); - return bundle.GetStringFromName(aLocaleKey.replace("%ID%", aID)); + this.name = bundle.GetStringFromName(aLocaleKey.replace("%ID%", aID)); + return this.name; }); } else { @@ -667,12 +620,9 @@ var gCheckUpdateSecurityDefault = true; var gCheckUpdateSecurity = gCheckUpdateSecurityDefault; var gUpdateEnabled = true; var gAutoUpdateDefault = true; -var gHotfixID = null; -var gWebExtensionsMinPlatformVersion = null; var gShutdownBarrier = null; var gRepoShutdownState = ""; var gShutdownInProgress = false; -var gPluginPageListener = null; /** * This is the real manager, kept here rather than in AddonManager to keep its @@ -690,13 +640,12 @@ var AddonManagerInternal = { startupChanges: {}, // Store telemetry details per addon provider telemetryDetails: {}, - upgradeListeners: new Map(), - recordTimestamp: function(name, value) { + recordTimestamp: function AMI_recordTimestamp(name, value) { this.TelemetryTimestamps.add(name, value); }, - validateBlocklist: function() { + validateBlocklist: function AMI_validateBlocklist() { let appBlocklist = FileUtils.getFile(KEY_APPDIR, [FILE_BLOCKLIST]); // If there is no application shipped blocklist then there is nothing to do @@ -819,19 +768,11 @@ var AddonManagerInternal = { logger.debug(`Provider finished startup: ${providerName(aProvider)}`); }, - _getProviderByName(aName) { - for (let provider of this.providers) { - if (providerName(provider) == aName) - return provider; - } - return undefined; - }, - /** * Initializes the AddonManager, loading any known providers and initializing * them. */ - startup: function() { + startup: function AMI_startup() { try { if (gStarted) return; @@ -851,8 +792,6 @@ var AddonManagerInternal = { } catch (e) { } - Extension.browserUpdated = appChanged; - let oldPlatformVersion = null; try { oldPlatformVersion = Services.prefs.getCharPref(PREF_EM_LAST_PLATFORM_VERSION); @@ -870,10 +809,8 @@ var AddonManagerInternal = { this.validateBlocklist(); } - if (!MOZ_COMPATIBILITY_NIGHTLY) { - PREF_EM_CHECK_COMPATIBILITY = PREF_EM_CHECK_COMPATIBILITY_BASE + "." + - Services.appinfo.version.replace(BRANCH_REGEXP, "$1"); - } + PREF_EM_CHECK_COMPATIBILITY = PREF_EM_CHECK_COMPATIBILITY_BASE + "." + + Services.appinfo.version.replace(BRANCH_REGEXP, "$1"); try { gCheckCompatibility = Services.prefs.getBoolPref(PREF_EM_CHECK_COMPATIBILITY); @@ -888,7 +825,7 @@ var AddonManagerInternal = { try { let defaultBranch = Services.prefs.getDefaultBranch(""); gCheckUpdateSecurityDefault = defaultBranch.getBoolPref(PREF_EM_CHECK_UPDATE_SECURITY); - } catch (e) {} + } catch(e) {} try { gCheckUpdateSecurity = Services.prefs.getBoolPref(PREF_EM_CHECK_UPDATE_SECURITY); @@ -905,16 +842,6 @@ var AddonManagerInternal = { } catch (e) {} Services.prefs.addObserver(PREF_EM_AUTOUPDATE_DEFAULT, this, false); - try { - gHotfixID = Services.prefs.getCharPref(PREF_EM_HOTFIX_ID); - } catch (e) {} - Services.prefs.addObserver(PREF_EM_HOTFIX_ID, this, false); - - try { - gWebExtensionsMinPlatformVersion = Services.prefs.getCharPref(PREF_MIN_WEBEXT_PLATFORM_VERSION); - } catch (e) {} - Services.prefs.addObserver(PREF_MIN_WEBEXT_PLATFORM_VERSION, this, false); - let defaultProvidersEnabled = true; try { defaultProvidersEnabled = Services.prefs.getBoolPref(PREF_DEFAULT_PROVIDERS_ENABLED); @@ -941,7 +868,7 @@ var AddonManagerInternal = { AddonManagerPrivate.recordException("AMI", "provider " + url + " load failed", e); logger.error("Exception loading default provider \"" + url + "\"", e); } - } + }; } // Load any providers registered in the category manager @@ -982,13 +909,6 @@ var AddonManagerInternal = { delete this.startupChanges[type]; } - // Support for remote about:plugins. Note that this module isn't loaded - // at the top because Services.appinfo is defined late in tests. - let { RemotePages } = Cu.import("resource://gre/modules/RemotePageManager.jsm", {}); - - gPluginPageListener = new RemotePages("about:plugins"); - gPluginPageListener.addMessageListener("RequestPlugins", this.requestPlugins); - gStartupComplete = true; this.recordTimestamp("AMI_startup_end"); } @@ -1009,7 +929,7 @@ var AddonManagerInternal = { * @param aTypes * An optional array of add-on types */ - registerProvider: function(aProvider, aTypes) { + registerProvider: function AMI_registerProvider(aProvider, aTypes) { if (!aProvider || typeof aProvider != "object") throw Components.Exception("aProvider must be specified", Cr.NS_ERROR_INVALID_ARG); @@ -1021,26 +941,29 @@ var AddonManagerInternal = { this.pendingProviders.add(aProvider); if (aTypes) { - for (let type of aTypes) { - if (!(type.id in this.types)) { - if (!VALID_TYPES_REGEXP.test(type.id)) { - logger.warn("Ignoring invalid type " + type.id); + aTypes.forEach(function(aType) { + if (!(aType.id in this.types)) { + if (!VALID_TYPES_REGEXP.test(aType.id)) { + logger.warn("Ignoring invalid type " + aType.id); return; } - this.types[type.id] = { - type: type, + this.types[aType.id] = { + type: aType, providers: [aProvider] }; let typeListeners = this.typeListeners.slice(0); - for (let listener of typeListeners) - safeCall(() => listener.onTypeAdded(type)); + for (let listener of typeListeners) { + safeCall(function listenerSafeCall() { + listener.onTypeAdded(aType); + }); + } } else { - this.types[type.id].providers.push(aProvider); + this.types[aType.id].providers.push(aProvider); } - } + }, this); } // If we're registering after startup call this provider's startup. @@ -1058,7 +981,7 @@ var AddonManagerInternal = { * For providers that have async shutdown methods returning Promises, * the caller should wait for that Promise to resolve. */ - unregisterProvider: function(aProvider) { + unregisterProvider: function AMI_unregisterProvider(aProvider) { if (!aProvider || typeof aProvider != "object") throw Components.Exception("aProvider must be specified", Cr.NS_ERROR_INVALID_ARG); @@ -1070,14 +993,17 @@ var AddonManagerInternal = { this.pendingProviders.delete(aProvider); for (let type in this.types) { - this.types[type].providers = this.types[type].providers.filter(p => p != aProvider); + this.types[type].providers = this.types[type].providers.filter(function filterProvider(p) p != aProvider); if (this.types[type].providers.length == 0) { let oldType = this.types[type].type; delete this.types[type]; let typeListeners = this.typeListeners.slice(0); - for (let listener of typeListeners) - safeCall(() => listener.onTypeRemoved(oldType)); + for (let listener of typeListeners) { + safeCall(function listenerSafeCall() { + listener.onTypeRemoved(oldType); + }); + } } } @@ -1110,7 +1036,7 @@ var AddonManagerInternal = { * * @param aProvider Provider object to mark safe */ - markProviderSafe: function(aProvider) { + markProviderSafe: function AMI_markProviderSafe(aProvider) { if (!gStarted) { throw Components.Exception("AddonManager is not initialized", Cr.NS_ERROR_NOT_INITIALIZED); @@ -1140,7 +1066,7 @@ var AddonManagerInternal = { * The method name to call * @see callProvider */ - callProviders: function(aMethod, ...aArgs) { + callProviders: function AMI_callProviders(aMethod, ...aArgs) { if (!aMethod || typeof aMethod != "string") throw Components.Exception("aMethod must be a non-empty string", Cr.NS_ERROR_INVALID_ARG); @@ -1152,7 +1078,7 @@ var AddonManagerInternal = { provider[aMethod].apply(provider, aArgs); } catch (e) { - reportProviderError(provider, aMethod, e); + reportProviderError(aProvider, aMethod, e); } } }, @@ -1181,7 +1107,7 @@ var AddonManagerInternal = { * @return Promise{null} that resolves when all providers and dependent modules * have finished shutting down */ - shutdownManager: Task.async(function*() { + shutdownManager: Task.async(function* () { logger.debug("shutdown"); this.callManagerListeners("onShutdown"); @@ -1193,9 +1119,6 @@ var AddonManagerInternal = { Services.prefs.removeObserver(PREF_EM_CHECK_UPDATE_SECURITY, this); Services.prefs.removeObserver(PREF_EM_UPDATE_ENABLED, this); Services.prefs.removeObserver(PREF_EM_AUTOUPDATE_DEFAULT, this); - Services.prefs.removeObserver(PREF_EM_HOTFIX_ID, this); - gPluginPageListener.destroy(); - gPluginPageListener = null; let savedError = null; // Only shut down providers if they've been started. @@ -1203,7 +1126,7 @@ var AddonManagerInternal = { try { yield gShutdownBarrier.wait(); } - catch (err) { + catch(err) { savedError = err; logger.error("Failure during wait for shutdown barrier", err); AddonManagerPrivate.recordException("AMI", "Async shutdown of AddonManager providers", err); @@ -1216,7 +1139,7 @@ var AddonManagerInternal = { yield AddonRepository.shutdown(); gRepoShutdownState = "done"; } - catch (err) { + catch(err) { savedError = err; logger.error("Failure during AddonRepository shutdown", err); AddonManagerPrivate.recordException("AMI", "Async shutdown of AddonRepository", err); @@ -1239,36 +1162,18 @@ var AddonManagerInternal = { } }), - requestPlugins: function({ target: port }) { - // Lists all the properties that plugins.html needs - const NEEDED_PROPS = ["name", "pluginLibraries", "pluginFullpath", "version", - "isActive", "blocklistState", "description", - "pluginMimeTypes"]; - function filterProperties(plugin) { - let filtered = {}; - for (let prop of NEEDED_PROPS) { - filtered[prop] = plugin[prop]; - } - return filtered; - } - - AddonManager.getAddonsByTypes(["plugin"], function(aPlugins) { - port.sendAsyncMessage("PluginList", aPlugins.map(filterProperties)); - }); - }, - /** * Notified when a preference we're interested in has changed. * * @see nsIObserver */ - observe: function(aSubject, aTopic, aData) { + observe: function AMI_observe(aSubject, aTopic, aData) { switch (aData) { case PREF_EM_CHECK_COMPATIBILITY: { let oldValue = gCheckCompatibility; try { gCheckCompatibility = Services.prefs.getBoolPref(PREF_EM_CHECK_COMPATIBILITY); - } catch (e) { + } catch(e) { gCheckCompatibility = true; } @@ -1283,7 +1188,7 @@ var AddonManagerInternal = { let oldValue = gStrictCompatibility; try { gStrictCompatibility = Services.prefs.getBoolPref(PREF_EM_STRICT_COMPATIBILITY); - } catch (e) { + } catch(e) { gStrictCompatibility = true; } @@ -1298,7 +1203,7 @@ var AddonManagerInternal = { let oldValue = gCheckUpdateSecurity; try { gCheckUpdateSecurity = Services.prefs.getBoolPref(PREF_EM_CHECK_UPDATE_SECURITY); - } catch (e) { + } catch(e) { gCheckUpdateSecurity = true; } @@ -1313,7 +1218,7 @@ var AddonManagerInternal = { let oldValue = gUpdateEnabled; try { gUpdateEnabled = Services.prefs.getBoolPref(PREF_EM_UPDATE_ENABLED); - } catch (e) { + } catch(e) { gUpdateEnabled = true; } @@ -1324,25 +1229,13 @@ var AddonManagerInternal = { let oldValue = gAutoUpdateDefault; try { gAutoUpdateDefault = Services.prefs.getBoolPref(PREF_EM_AUTOUPDATE_DEFAULT); - } catch (e) { + } catch(e) { gAutoUpdateDefault = true; } this.callManagerListeners("onUpdateModeChanged"); break; } - case PREF_EM_HOTFIX_ID: { - try { - gHotfixID = Services.prefs.getCharPref(PREF_EM_HOTFIX_ID); - } catch (e) { - gHotfixID = null; - } - break; - } - case PREF_MIN_WEBEXT_PLATFORM_VERSION: { - gWebExtensionsMinPlatformVersion = Services.prefs.getCharPref(PREF_MIN_WEBEXT_PLATFORM_VERSION); - break; - } } }, @@ -1358,7 +1251,7 @@ var AddonManagerInternal = { * The optional application version to use for %APP_VERSION% * @return The appropriately escaped URI. */ - escapeAddonURI: function(aAddon, aUri, aAppVersion) + escapeAddonURI: function AMI_escapeAddonURI(aAddon, aUri, aAppVersion) { if (!aAddon || typeof aAddon != "object") throw Components.Exception("aAddon must be an Addon object", @@ -1403,7 +1296,7 @@ var AddonManagerInternal = { // Replace custom parameters (names of custom parameters must have at // least 3 characters to prevent lookups for something like %D0%C8) var catMan = null; - uri = uri.replace(/%(\w{3,})%/g, function(aMatch, aParam) { + uri = uri.replace(/%(\w{3,})%/g, function parameterReplace(aMatch, aParam) { if (!catMan) { catMan = Cc["@mozilla.org/categorymanager;1"]. getService(Ci.nsICategoryManager); @@ -1414,7 +1307,7 @@ var AddonManagerInternal = { var paramHandler = Cc[contractID].getService(Ci.nsIPropertyBag2); return paramHandler.getPropertyAsAString(aParam); } - catch (e) { + catch(e) { return aMatch; } }); @@ -1429,18 +1322,12 @@ var AddonManagerInternal = { * @return Promise{null} Resolves when the background update check is complete * (the resulting addon installations may still be in progress). */ - backgroundUpdateCheck: function() { + backgroundUpdateCheck: function AMI_backgroundUpdateCheck() { if (!gStarted) throw Components.Exception("AddonManager is not initialized", Cr.NS_ERROR_NOT_INITIALIZED); - let buPromise = Task.spawn(function*() { - let hotfixID = this.hotfixID; - - let appUpdateEnabled = Services.prefs.getBoolPref(PREF_APP_UPDATE_ENABLED) && - Services.prefs.getBoolPref(PREF_APP_UPDATE_AUTO); - let checkHotfix = hotfixID && appUpdateEnabled; - + let buPromise = Task.spawn(function* backgroundUpdateTask() { logger.debug("Background update check beginning"); Services.obs.notifyObservers(null, "addons-background-update-start", null); @@ -1460,15 +1347,11 @@ var AddonManagerInternal = { let updates = []; for (let addon of allAddons) { - if (addon.id == hotfixID) { - continue; - } - // Check all add-ons for updates so that any compatibility updates will // be applied updates.push(new Promise((resolve, reject) => { addon.findUpdates({ - onUpdateAvailable: function(aAddon, aInstall) { + onUpdateAvailable: function BUC_onUpdateAvailable(aAddon, aInstall) { // Start installing updates when the add-on can be updated and // background updates should be applied. logger.debug("Found update for add-on ${id}", aAddon); @@ -1476,7 +1359,7 @@ var AddonManagerInternal = { AddonManager.shouldAutoUpdate(aAddon)) { // XXX we really should resolve when this install is done, // not when update-available check completes, no? - logger.debug(`Starting upgrade install of ${aAddon.id}`); + logger.debug("Starting install of ${id}", aAddon); aInstall.install(); } }, @@ -1488,113 +1371,6 @@ var AddonManagerInternal = { yield Promise.all(updates); } - if (checkHotfix) { - var hotfixVersion = ""; - try { - hotfixVersion = Services.prefs.getCharPref(PREF_EM_HOTFIX_LASTVERSION); - } - catch (e) { } - - let url = null; - if (Services.prefs.getPrefType(PREF_EM_HOTFIX_URL) == Ci.nsIPrefBranch.PREF_STRING) - url = Services.prefs.getCharPref(PREF_EM_HOTFIX_URL); - else - url = Services.prefs.getCharPref(PREF_EM_UPDATE_BACKGROUND_URL); - - // Build the URI from a fake add-on data. - url = AddonManager.escapeAddonURI({ - id: hotfixID, - version: hotfixVersion, - userDisabled: false, - appDisabled: false - }, url); - - Components.utils.import("resource://gre/modules/addons/AddonUpdateChecker.jsm"); - let update = null; - try { - let foundUpdates = yield new Promise((resolve, reject) => { - AddonUpdateChecker.checkForUpdates(hotfixID, null, url, { - onUpdateCheckComplete: resolve, - onUpdateCheckError: reject - }); - }); - update = AddonUpdateChecker.getNewestCompatibleUpdate(foundUpdates); - } catch (e) { - // AUC.checkForUpdates already logged the error - } - - // Check that we have a hotfix update, and it's newer than the one we already - // have installed (if any) - if (update) { - if (Services.vc.compare(hotfixVersion, update.version) < 0) { - logger.debug("Downloading hotfix version " + update.version); - let aInstall = yield new Promise((resolve, reject) => - AddonManager.getInstallForURL(update.updateURL, resolve, - "application/x-xpinstall", update.updateHash, null, - null, update.version)); - - aInstall.addListener({ - onDownloadEnded: function(aInstall) { - if (aInstall.addon.id != hotfixID) { - logger.warn("The downloaded hotfix add-on did not have the " + - "expected ID and so will not be installed."); - aInstall.cancel(); - return; - } - - // If XPIProvider has reported the hotfix as properly signed then - // there is nothing more to do here - if (aInstall.addon.signedState == AddonManager.SIGNEDSTATE_SIGNED) - return; - - try { - if (!Services.prefs.getBoolPref(PREF_EM_CERT_CHECKATTRIBUTES)) - return; - } - catch (e) { - // By default don't do certificate checks. - return; - } - - try { - CertUtils.validateCert(aInstall.certificate, - CertUtils.readCertPrefs(PREF_EM_HOTFIX_CERTS)); - } - catch (e) { - logger.warn("The hotfix add-on was not signed by the expected " + - "certificate and so will not be installed.", e); - aInstall.cancel(); - } - }, - - onInstallEnded: function(aInstall) { - // Remember the last successfully installed version. - Services.prefs.setCharPref(PREF_EM_HOTFIX_LASTVERSION, - aInstall.version); - }, - - onInstallCancelled: function(aInstall) { - // Revert to the previous version if the installation was - // cancelled. - Services.prefs.setCharPref(PREF_EM_HOTFIX_LASTVERSION, - hotfixVersion); - } - }); - - aInstall.install(); - } - } - } - - if (appUpdateEnabled) { - try { - yield AddonManagerInternal._getProviderByName("XPIProvider").updateSystemAddons(); - } - catch (e) { - logger.warn("Failed to update system addons", e); - } - } - logger.debug("Background update check complete"); Services.obs.notifyObservers(null, "addons-background-update-complete", @@ -1617,7 +1393,7 @@ var AddonManagerInternal = { * @param aID * The ID of the add-on */ - addStartupChange: function(aType, aID) { + addStartupChange: function AMI_addStartupChange(aType, aID) { if (!aType || typeof aType != "string") throw Components.Exception("aType must be a non-empty string", Cr.NS_ERROR_INVALID_ARG); @@ -1628,7 +1404,6 @@ var AddonManagerInternal = { if (gStartupComplete) return; - logger.debug("Registering startup change '" + aType + "' for " + aID); // Ensure that an ID is only listed in one type of change for (let type in this.startupChanges) @@ -1647,7 +1422,7 @@ var AddonManagerInternal = { * @param aID * The ID of the add-on */ - removeStartupChange: function(aType, aID) { + removeStartupChange: function AMI_removeStartupChange(aType, aID) { if (!aType || typeof aType != "string") throw Components.Exception("aType must be a non-empty string", Cr.NS_ERROR_INVALID_ARG); @@ -1662,7 +1437,8 @@ var AddonManagerInternal = { if (!(aType in this.startupChanges)) return; - this.startupChanges[aType] = this.startupChanges[aType].filter(aItem => aItem != aID); + this.startupChanges[aType] = this.startupChanges[aType].filter( + function filterItem(aItem) aItem != aID); }, /** @@ -1672,7 +1448,7 @@ var AddonManagerInternal = { * @param aMethod * The method on the listeners to call */ - callManagerListeners: function(aMethod, ...aArgs) { + callManagerListeners: function AMI_callManagerListeners(aMethod, ...aArgs) { if (!gStarted) throw Components.Exception("AddonManager is not initialized", Cr.NS_ERROR_NOT_INITIALIZED); @@ -1703,7 +1479,7 @@ var AddonManagerInternal = { * An optional array of extra InstallListeners to also call * @return false if any of the listeners returned false, true otherwise */ - callInstallListeners: function(aMethod, + callInstallListeners: function AMI_callInstallListeners(aMethod, aExtraListeners, ...aArgs) { if (!gStarted) throw Components.Exception("AddonManager is not initialized", @@ -1745,7 +1521,7 @@ var AddonManagerInternal = { * @param aMethod * The method on the listeners to call */ - callAddonListeners: function(aMethod, ...aArgs) { + callAddonListeners: function AMI_callAddonListeners(aMethod, ...aArgs) { if (!gStarted) throw Components.Exception("AddonManager is not initialized", Cr.NS_ERROR_NOT_INITIALIZED); @@ -1779,7 +1555,7 @@ var AddonManagerInternal = { * A boolean indicating if the change will only take place the next * time the application is restarted */ - notifyAddonChanged: function(aID, aType, aPendingRestart) { + notifyAddonChanged: function AMI_notifyAddonChanged(aID, aType, aPendingRestart) { if (!gStarted) throw Components.Exception("AddonManager is not initialized", Cr.NS_ERROR_NOT_INITIALIZED); @@ -1816,7 +1592,7 @@ var AddonManagerInternal = { * their add-ons in response to an application change such as a blocklist * update. */ - updateAddonAppDisabledStates: function() { + updateAddonAppDisabledStates: function AMI_updateAddonAppDisabledStates() { if (!gStarted) throw Components.Exception("AddonManager is not initialized", Cr.NS_ERROR_NOT_INITIALIZED); @@ -1831,7 +1607,7 @@ var AddonManagerInternal = { * @param aCallback * Function to call when operation is complete. */ - updateAddonRepositoryData: function(aCallback) { + updateAddonRepositoryData: function AMI_updateAddonRepositoryData(aCallback) { if (!gStarted) throw Components.Exception("AddonManager is not initialized", Cr.NS_ERROR_NOT_INITIALIZED); @@ -1841,11 +1617,11 @@ var AddonManagerInternal = { Cr.NS_ERROR_INVALID_ARG); new AsyncObjectCaller(this.providers, "updateAddonRepositoryData", { - nextObject: function(aCaller, aProvider) { + nextObject: function updateAddonRepositoryData_nextObject(aCaller, aProvider) { callProviderAsync(aProvider, "updateAddonRepositoryData", aCaller.callNext.bind(aCaller)); }, - noMoreObjects: function(aCaller) { + noMoreObjects: function updateAddonRepositoryData_noMoreObjects(aCaller) { safeCall(aCallback); // only tests should care about this Services.obs.notifyObservers(null, "TEST:addon-repository-data-updated", null); @@ -1874,7 +1650,7 @@ var AddonManagerInternal = { * An optional nsILoadGroup to associate any network requests with * @throws if the aUrl, aCallback or aMimetype arguments are not specified */ - getInstallForURL: function(aUrl, aCallback, aMimetype, + getInstallForURL: function AMI_getInstallForURL(aUrl, aCallback, aMimetype, aHash, aName, aIcons, aVersion, aBrowser) { if (!gStarted) @@ -1944,7 +1720,7 @@ var AddonManagerInternal = { * An optional mimetype hint for the add-on * @throws if the aFile or aCallback arguments are not specified */ - getInstallForFile: function(aFile, aCallback, aMimetype) { + getInstallForFile: function AMI_getInstallForFile(aFile, aCallback, aMimetype) { if (!gStarted) throw Components.Exception("AddonManager is not initialized", Cr.NS_ERROR_NOT_INITIALIZED); @@ -1962,9 +1738,9 @@ var AddonManagerInternal = { Cr.NS_ERROR_INVALID_ARG); new AsyncObjectCaller(this.providers, "getInstallForFile", { - nextObject: function(aCaller, aProvider) { + nextObject: function getInstallForFile_nextObject(aCaller, aProvider) { callProviderAsync(aProvider, "getInstallForFile", aFile, - function(aInstall) { + function getInstallForFile_safeCall(aInstall) { if (aInstall) safeCall(aCallback, aInstall); else @@ -1972,7 +1748,7 @@ var AddonManagerInternal = { }); }, - noMoreObjects: function(aCaller) { + noMoreObjects: function getInstallForFile_noMoreObjects(aCaller) { safeCall(aCallback, null); } }); @@ -1988,7 +1764,7 @@ var AddonManagerInternal = { * A callback which will be passed an array of AddonInstalls * @throws If the aCallback argument is not specified */ - getInstallsByTypes: function(aTypes, aCallback) { + getInstallsByTypes: function AMI_getInstallsByTypes(aTypes, aCallback) { if (!gStarted) throw Components.Exception("AddonManager is not initialized", Cr.NS_ERROR_NOT_INITIALIZED); @@ -2004,9 +1780,9 @@ var AddonManagerInternal = { let installs = []; new AsyncObjectCaller(this.providers, "getInstallsByTypes", { - nextObject: function(aCaller, aProvider) { + nextObject: function getInstallsByTypes_nextObject(aCaller, aProvider) { callProviderAsync(aProvider, "getInstallsByTypes", aTypes, - function(aProviderInstalls) { + function getInstallsByTypes_safeCall(aProviderInstalls) { if (aProviderInstalls) { installs = installs.concat(aProviderInstalls); } @@ -2014,7 +1790,7 @@ var AddonManagerInternal = { }); }, - noMoreObjects: function(aCaller) { + noMoreObjects: function getInstallsByTypes_noMoreObjects(aCaller) { safeCall(aCallback, installs); } }); @@ -2026,7 +1802,7 @@ var AddonManagerInternal = { * @param aCallback * A callback which will be passed an array of AddonInstalls */ - getAllInstalls: function(aCallback) { + getAllInstalls: function AMI_getAllInstalls(aCallback) { if (!gStarted) throw Components.Exception("AddonManager is not initialized", Cr.NS_ERROR_NOT_INITIALIZED); @@ -2046,7 +1822,7 @@ var AddonManagerInternal = { * @return string containing the Addon ID or null * @see amIAddonManager.mapURIToAddonID */ - mapURIToAddonID: function(aURI) { + mapURIToAddonID: function AMI_mapURIToAddonID(aURI) { if (!(aURI instanceof Ci.nsIURI)) { throw Components.Exception("aURI is not a nsIURI", Cr.NS_ERROR_INVALID_ARG); @@ -2071,7 +1847,7 @@ var AddonManagerInternal = { * The mimetype to check * @return true if installation is enabled for the mimetype */ - isInstallEnabled: function(aMimetype) { + isInstallEnabled: function AMI_isInstallEnabled(aMimetype) { if (!gStarted) throw Components.Exception("AddonManager is not initialized", Cr.NS_ERROR_NOT_INITIALIZED); @@ -2099,7 +1875,7 @@ var AddonManagerInternal = { * The nsIPrincipal that initiated the install * @return true if the source is allowed to install this mimetype */ - isInstallAllowed: function(aMimetype, aInstallingPrincipal) { + isInstallAllowed: function AMI_isInstallAllowed(aMimetype, aInstallingPrincipal) { if (!gStarted) throw Components.Exception("AddonManager is not initialized", Cr.NS_ERROR_NOT_INITIALIZED); @@ -2134,8 +1910,10 @@ var AddonManagerInternal = { * @param aInstalls * The array of AddonInstalls to be installed */ - installAddonsFromWebpage: function(aMimetype, aBrowser, - aInstallingPrincipal, aInstalls) { + installAddonsFromWebpage: function AMI_installAddonsFromWebpage(aMimetype, + aBrowser, + aInstallingPrincipal, + aInstalls) { if (!gStarted) throw Components.Exception("AddonManager is not initialized", Cr.NS_ERROR_NOT_INITIALIZED); @@ -2158,8 +1936,9 @@ var AddonManagerInternal = { if (!("@mozilla.org/addons/web-install-listener;1" in Cc)) { logger.warn("No web installer available, cancelling all installs"); - for (let install of aInstalls) - install.cancel(); + aInstalls.forEach(function(aInstall) { + aInstall.cancel(); + }); return; } @@ -2207,14 +1986,16 @@ var AddonManagerInternal = { if (!this.isInstallAllowed(aMimetype, aInstallingPrincipal)) { if (weblistener.onWebInstallBlocked(topBrowser, aInstallingPrincipal.URI, aInstalls, aInstalls.length)) { - for (let install of aInstalls) - install.install(); + aInstalls.forEach(function(aInstall) { + aInstall.install(); + }); } } else if (weblistener.onWebInstallRequested(topBrowser, aInstallingPrincipal.URI, aInstalls, aInstalls.length)) { - for (let install of aInstalls) - install.install(); + aInstalls.forEach(function(aInstall) { + aInstall.install(); + }); } } catch (e) { @@ -2222,8 +2003,9 @@ var AddonManagerInternal = { // calling onWebInstallBlocked or onWebInstallRequested all of the // installs should get cancelled. logger.warn("Failure calling web installer", e); - for (let install of aInstalls) - install.cancel(); + aInstalls.forEach(function(aInstall) { + aInstall.cancel(); + }); } }, @@ -2233,12 +2015,12 @@ var AddonManagerInternal = { * @param aListener * The InstallListener to add */ - addInstallListener: function(aListener) { + addInstallListener: function AMI_addInstallListener(aListener) { if (!aListener || typeof aListener != "object") throw Components.Exception("aListener must be a InstallListener object", Cr.NS_ERROR_INVALID_ARG); - if (!this.installListeners.some(function(i) { + if (!this.installListeners.some(function addInstallListener_matchListener(i) { return i == aListener; })) this.installListeners.push(aListener); }, @@ -2249,7 +2031,7 @@ var AddonManagerInternal = { * @param aListener * The InstallListener to remove */ - removeInstallListener: function(aListener) { + removeInstallListener: function AMI_removeInstallListener(aListener) { if (!aListener || typeof aListener != "object") throw Components.Exception("aListener must be a InstallListener object", Cr.NS_ERROR_INVALID_ARG); @@ -2262,199 +2044,17 @@ var AddonManagerInternal = { pos++; } }, - /* - * Adds new or overrides existing UpgradeListener. - * - * @param aInstanceID - * The instance ID of an addon to register a listener for. - * @param aCallback - * The callback to invoke when updates are available for this addon. - * @throws if there is no addon matching the instanceID - */ - addUpgradeListener: function(aInstanceID, aCallback) { - if (!aInstanceID || typeof aInstanceID != "symbol") - throw Components.Exception("aInstanceID must be a symbol", - Cr.NS_ERROR_INVALID_ARG); - - if (!aCallback || typeof aCallback != "function") - throw Components.Exception("aCallback must be a function", - Cr.NS_ERROR_INVALID_ARG); - - this.getAddonByInstanceID(aInstanceID).then(wrapper => { - if (!wrapper) { - throw Error("No addon matching instanceID:", aInstanceID.toString()); - } - let addonId = wrapper.addonId(); - logger.debug(`Registering upgrade listener for ${addonId}`); - this.upgradeListeners.set(addonId, aCallback); - }); - }, - - /** - * Removes an UpgradeListener if the listener is registered. - * - * @param aInstanceID - * The instance ID of the addon to remove - */ - removeUpgradeListener: function(aInstanceID) { - if (!aInstanceID || typeof aInstanceID != "symbol") - throw Components.Exception("aInstanceID must be a symbol", - Cr.NS_ERROR_INVALID_ARG); - - this.getAddonByInstanceID(aInstanceID).then(addon => { - if (!addon) { - throw Error("No addon for instanceID:", aInstanceID.toString()); - } - if (this.upgradeListeners.has(addon.id)) { - this.upgradeListeners.delete(addon.id); - } else { - throw Error("No upgrade listener registered for addon ID:", addon.id); - } - }); - }, - - /** - * Installs a temporary add-on from a local file or directory. - * @param aFile - * An nsIFile for the file or directory of the add-on to be - * temporarily installed. - * @return a Promise that rejects if the add-on is not a valid restartless - * add-on or if the same ID is already temporarily installed. - */ - installTemporaryAddon: function(aFile) { - if (!gStarted) - throw Components.Exception("AddonManager is not initialized", - Cr.NS_ERROR_NOT_INITIALIZED); - - if (!(aFile instanceof Ci.nsIFile)) - throw Components.Exception("aFile must be a nsIFile", - Cr.NS_ERROR_INVALID_ARG); - - return AddonManagerInternal._getProviderByName("XPIProvider") - .installTemporaryAddon(aFile); - }, - - installAddonFromSources: function(aFile) { - if (!gStarted) - throw Components.Exception("AddonManager is not initialized", - Cr.NS_ERROR_NOT_INITIALIZED); - - if (!(aFile instanceof Ci.nsIFile)) - throw Components.Exception("aFile must be a nsIFile", - Cr.NS_ERROR_INVALID_ARG); - - return AddonManagerInternal._getProviderByName("XPIProvider") - .installAddonFromSources(aFile); - }, - - /** - * Returns an Addon corresponding to an instance ID. - * @param aInstanceID - * An Addon Instance ID symbol - * @return {Promise} - * @resolves The found Addon or null if no such add-on exists. - * @rejects Never - * @throws if the aInstanceID argument is not specified - * or the AddonManager is not initialized - */ - getAddonByInstanceID: function(aInstanceID) { - if (!gStarted) - throw Components.Exception("AddonManager is not initialized", - Cr.NS_ERROR_NOT_INITIALIZED); - - if (!aInstanceID || typeof aInstanceID != "symbol") - throw Components.Exception("aInstanceID must be a Symbol()", - Cr.NS_ERROR_INVALID_ARG); - - return AddonManagerInternal._getProviderByName("XPIProvider") - .getAddonByInstanceID(aInstanceID); - }, - - /** - * Gets an icon from the icon set provided by the add-on - * that is closest to the specified size. - * - * The optional window parameter will be used to determine - * the screen resolution and select a more appropriate icon. - * Calling this method with 48px on retina screens will try to - * match an icon of size 96px. - * - * @param aAddon - * An addon object, meaning: - * An object with either an icons property that is a key-value - * list of icon size and icon URL, or an object having an iconURL - * and icon64URL property. - * @param aSize - * Ideal icon size in pixels - * @param aWindow - * Optional window object for determining the correct scale. - * @return {String} The absolute URL of the icon or null if the addon doesn't have icons - */ - getPreferredIconURL: function(aAddon, aSize, aWindow = undefined) { - if (aWindow && aWindow.devicePixelRatio) { - aSize *= aWindow.devicePixelRatio; - } - - let icons = aAddon.icons; - - // certain addon-types only have iconURLs - if (!icons) { - icons = {}; - if (aAddon.iconURL) { - icons[32] = aAddon.iconURL; - icons[48] = aAddon.iconURL; - } - if (aAddon.icon64URL) { - icons[64] = aAddon.icon64URL; - } - } - - // quick return if the exact size was found - if (icons[aSize]) { - return icons[aSize]; - } - - let bestSize = null; - - for (let size of Object.keys(icons)) { - if (!INTEGER.test(size)) { - throw Components.Exception("Invalid icon size, must be an integer", - Cr.NS_ERROR_ILLEGAL_VALUE); - } - - size = parseInt(size, 10); - - if (!bestSize) { - bestSize = size; - continue; - } - - if (size > aSize && bestSize > aSize) { - // If both best size and current size are larger than the wanted size then choose - // the one closest to the wanted size - bestSize = Math.min(bestSize, size); - } - else { - // Otherwise choose the largest of the two so we'll prefer sizes as close to below aSize - // or above aSize - bestSize = Math.max(bestSize, size); - } - } - - return icons[bestSize] || null; - }, /** * Asynchronously gets an add-on with a specific ID. * * @param aID * The ID of the add-on to retrieve - * @return {Promise} - * @resolves The found Addon or null if no such add-on exists. - * @rejects Never - * @throws if the aID argument is not specified + * @param aCallback + * The callback to pass the retrieved add-on to + * @throws if the aID or aCallback arguments are not specified */ - getAddonByID: function(aID) { + getAddonByID: function AMI_getAddonByID(aID, aCallback) { if (!gStarted) throw Components.Exception("AddonManager is not initialized", Cr.NS_ERROR_NOT_INITIALIZED); @@ -2463,10 +2063,24 @@ var AddonManagerInternal = { throw Components.Exception("aID must be a non-empty string", Cr.NS_ERROR_INVALID_ARG); - let promises = Array.from(this.providers, - p => promiseCallProvider(p, "getAddonByID", aID)); - return Promise.all(promises).then(aAddons => { - return aAddons.find(a => !!a) || null; + if (typeof aCallback != "function") + throw Components.Exception("aCallback must be a function", + Cr.NS_ERROR_INVALID_ARG); + + new AsyncObjectCaller(this.providers, "getAddonByID", { + nextObject: function getAddonByID_nextObject(aCaller, aProvider) { + callProviderAsync(aProvider, "getAddonByID", aID, + function getAddonByID_safeCall(aAddon) { + if (aAddon) + safeCall(aCallback, aAddon); + else + aCaller.callNext(); + }); + }, + + noMoreObjects: function getAddonByID_noMoreObjects(aCaller) { + safeCall(aCallback, null); + } }); }, @@ -2479,7 +2093,7 @@ var AddonManagerInternal = { * The callback to pass the retrieved add-on to. * @throws if the aGUID or aCallback arguments are not specified */ - getAddonBySyncGUID: function(aGUID, aCallback) { + getAddonBySyncGUID: function AMI_getAddonBySyncGUID(aGUID, aCallback) { if (!gStarted) throw Components.Exception("AddonManager is not initialized", Cr.NS_ERROR_NOT_INITIALIZED); @@ -2493,9 +2107,9 @@ var AddonManagerInternal = { Cr.NS_ERROR_INVALID_ARG); new AsyncObjectCaller(this.providers, "getAddonBySyncGUID", { - nextObject: function(aCaller, aProvider) { + nextObject: function getAddonBySyncGUID_nextObject(aCaller, aProvider) { callProviderAsync(aProvider, "getAddonBySyncGUID", aGUID, - function(aAddon) { + function getAddonBySyncGUID_safeCall(aAddon) { if (aAddon) { safeCall(aCallback, aAddon); } else { @@ -2504,7 +2118,7 @@ var AddonManagerInternal = { }); }, - noMoreObjects: function(aCaller) { + noMoreObjects: function getAddonBySyncGUID_noMoreObjects(aCaller) { safeCall(aCallback, null); } }); @@ -2515,12 +2129,11 @@ var AddonManagerInternal = { * * @param aIDs * The array of IDs to retrieve - * @return {Promise} - * @resolves The array of found add-ons. - * @rejects Never - * @throws if the aIDs argument is not specified + * @param aCallback + * The callback to pass an array of Addons to + * @throws if the aID or aCallback arguments are not specified */ - getAddonsByIDs: function(aIDs) { + getAddonsByIDs: function AMI_getAddonsByIDs(aIDs, aCallback) { if (!gStarted) throw Components.Exception("AddonManager is not initialized", Cr.NS_ERROR_NOT_INITIALIZED); @@ -2529,8 +2142,25 @@ var AddonManagerInternal = { throw Components.Exception("aIDs must be an array", Cr.NS_ERROR_INVALID_ARG); - let promises = aIDs.map(a => AddonManagerInternal.getAddonByID(a)); - return Promise.all(promises); + if (typeof aCallback != "function") + throw Components.Exception("aCallback must be a function", + Cr.NS_ERROR_INVALID_ARG); + + let addons = []; + + new AsyncObjectCaller(aIDs, null, { + nextObject: function getAddonsByIDs_nextObject(aCaller, aID) { + AddonManagerInternal.getAddonByID(aID, + function getAddonsByIDs_getAddonByID(aAddon) { + addons.push(aAddon); + aCaller.callNext(); + }); + }, + + noMoreObjects: function getAddonsByIDs_noMoreObjects(aCaller) { + safeCall(aCallback, addons); + } + }); }, /** @@ -2542,7 +2172,7 @@ var AddonManagerInternal = { * The callback to pass an array of Addons to. * @throws if the aCallback argument is not specified */ - getAddonsByTypes: function(aTypes, aCallback) { + getAddonsByTypes: function AMI_getAddonsByTypes(aTypes, aCallback) { if (!gStarted) throw Components.Exception("AddonManager is not initialized", Cr.NS_ERROR_NOT_INITIALIZED); @@ -2558,9 +2188,9 @@ var AddonManagerInternal = { let addons = []; new AsyncObjectCaller(this.providers, "getAddonsByTypes", { - nextObject: function(aCaller, aProvider) { + nextObject: function getAddonsByTypes_nextObject(aCaller, aProvider) { callProviderAsync(aProvider, "getAddonsByTypes", aTypes, - function(aProviderAddons) { + function getAddonsByTypes_concatAddons(aProviderAddons) { if (aProviderAddons) { addons = addons.concat(aProviderAddons); } @@ -2568,7 +2198,7 @@ var AddonManagerInternal = { }); }, - noMoreObjects: function(aCaller) { + noMoreObjects: function getAddonsByTypes_noMoreObjects(aCaller) { safeCall(aCallback, addons); } }); @@ -2580,7 +2210,7 @@ var AddonManagerInternal = { * @param aCallback * A callback which will be passed an array of Addons */ - getAllAddons: function(aCallback) { + getAllAddons: function AMI_getAllAddons(aCallback) { if (!gStarted) throw Components.Exception("AddonManager is not initialized", Cr.NS_ERROR_NOT_INITIALIZED); @@ -2602,7 +2232,8 @@ var AddonManagerInternal = { * The callback to pass the array of Addons to * @throws if the aCallback argument is not specified */ - getAddonsWithOperationsByTypes: function(aTypes, aCallback) { + getAddonsWithOperationsByTypes: + function AMI_getAddonsWithOperationsByTypes(aTypes, aCallback) { if (!gStarted) throw Components.Exception("AddonManager is not initialized", Cr.NS_ERROR_NOT_INITIALIZED); @@ -2630,7 +2261,7 @@ var AddonManagerInternal = { }); }, - noMoreObjects: function(caller) { + noMoreObjects: function getAddonsWithOperationsByTypes_noMoreObjects(caller) { safeCall(aCallback, addons); } }); @@ -2642,12 +2273,13 @@ var AddonManagerInternal = { * @param aListener * The listener to add */ - addManagerListener: function(aListener) { + addManagerListener: function AMI_addManagerListener(aListener) { if (!aListener || typeof aListener != "object") throw Components.Exception("aListener must be an AddonManagerListener object", Cr.NS_ERROR_INVALID_ARG); - if (!this.managerListeners.some(i => i == aListener)) + if (!this.managerListeners.some(function addManagerListener_matchListener(i) { + return i == aListener; })) this.managerListeners.push(aListener); }, @@ -2657,7 +2289,7 @@ var AddonManagerInternal = { * @param aListener * The listener to remove */ - removeManagerListener: function(aListener) { + removeManagerListener: function AMI_removeManagerListener(aListener) { if (!aListener || typeof aListener != "object") throw Components.Exception("aListener must be an AddonManagerListener object", Cr.NS_ERROR_INVALID_ARG); @@ -2677,12 +2309,13 @@ var AddonManagerInternal = { * @param aListener * The AddonListener to add */ - addAddonListener: function(aListener) { + addAddonListener: function AMI_addAddonListener(aListener) { if (!aListener || typeof aListener != "object") throw Components.Exception("aListener must be an AddonListener object", Cr.NS_ERROR_INVALID_ARG); - if (!this.addonListeners.some(i => i == aListener)) + if (!this.addonListeners.some(function addAddonListener_matchListener(i) { + return i == aListener; })) this.addonListeners.push(aListener); }, @@ -2692,7 +2325,7 @@ var AddonManagerInternal = { * @param aListener * The AddonListener to remove */ - removeAddonListener: function(aListener) { + removeAddonListener: function AMI_removeAddonListener(aListener) { if (!aListener || typeof aListener != "object") throw Components.Exception("aListener must be an AddonListener object", Cr.NS_ERROR_INVALID_ARG); @@ -2712,12 +2345,13 @@ var AddonManagerInternal = { * @param aListener * The TypeListener to add */ - addTypeListener: function(aListener) { + addTypeListener: function AMI_addTypeListener(aListener) { if (!aListener || typeof aListener != "object") throw Components.Exception("aListener must be a TypeListener object", Cr.NS_ERROR_INVALID_ARG); - if (!this.typeListeners.some(i => i == aListener)) + if (!this.typeListeners.some(function addTypeListener_matchListener(i) { + return i == aListener; })) this.typeListeners.push(aListener); }, @@ -2727,7 +2361,7 @@ var AddonManagerInternal = { * @param aListener * The TypeListener to remove */ - removeTypeListener: function(aListener) { + removeTypeListener: function AMI_removeTypeListener(aListener) { if (!aListener || typeof aListener != "object") throw Components.Exception("aListener must be a TypeListener object", Cr.NS_ERROR_INVALID_ARG); @@ -2857,169 +2491,6 @@ var AddonManagerInternal = { Services.prefs.setBoolPref(PREF_EM_UPDATE_ENABLED, aValue); return aValue; }, - - get hotfixID() { - return gHotfixID; - }, - - webAPI: { - // installs maps integer ids to AddonInstall instances. - installs: new Map(), - nextInstall: 0, - - sendEvent: null, - setEventHandler(fn) { - this.sendEvent = fn; - }, - - getAddonByID(target, id) { - return new Promise(resolve => { - AddonManager.getAddonByID(id, (addon) => { - resolve(webAPIForAddon(addon)); - }); - }); - }, - - // helper to copy (and convert) the properties we care about - copyProps(install, obj) { - obj.state = AddonManager.stateToString(install.state); - obj.error = AddonManager.errorToString(install.error); - obj.progress = install.progress; - obj.maxProgress = install.maxProgress; - }, - - makeListener(id, mm) { - const events = [ - "onDownloadStarted", - "onDownloadProgress", - "onDownloadEnded", - "onDownloadCancelled", - "onDownloadFailed", - "onInstallStarted", - "onInstallEnded", - "onInstallCancelled", - "onInstallFailed", - ]; - - let listener = {}; - events.forEach(event => { - listener[event] = (install) => { - let data = {event, id}; - AddonManager.webAPI.copyProps(install, data); - this.sendEvent(mm, data); - } - }); - return listener; - }, - - forgetInstall(id) { - let info = this.installs.get(id); - if (!info) { - throw new Error(`forgetInstall cannot find ${id}`); - } - info.install.removeListener(info.listener); - this.installs.delete(id); - }, - - createInstall(target, options) { - // Throw an appropriate error if the given URL is not valid - // as an installation source. Return silently if it is okay. - function checkInstallUrl(url) { - let host = Services.io.newURI(options.url, null, null).host; - if (WEBAPI_INSTALL_HOSTS.includes(host)) { - return; - } - if (Services.prefs.getBoolPref(PREF_WEBAPI_TESTING) - && WEBAPI_TEST_INSTALL_HOSTS.includes(host)) { - return; - } - - throw new Error(`Install from ${host} not permitted`); - } - - return new Promise((resolve, reject) => { - try { - checkInstallUrl(options.url); - } catch (err) { - reject({message: err.message}); - return; - } - - let newInstall = install => { - let id = this.nextInstall++; - let listener = this.makeListener(id, target.messageManager); - install.addListener(listener); - - this.installs.set(id, {install, target, listener}); - - let result = {id}; - this.copyProps(install, result); - resolve(result); - }; - AddonManager.getInstallForURL(options.url, newInstall, "application/x-xpinstall", options.hash); - }); - }, - - addonUninstall(target, id) { - return new Promise(resolve => { - AddonManager.getAddonByID(id, addon => { - if (!addon) { - resolve(false); - } - - try { - addon.uninstall(); - resolve(true); - } catch (err) { - Cu.reportError(err); - resolve(false); - } - }); - }); - }, - - addonSetEnabled(target, id, value) { - return new Promise((resolve, reject) => { - AddonManager.getAddonByID(id, addon => { - if (!addon) { - reject({message: `No such addon ${id}`}); - } - addon.userDisabled = !value; - resolve(); - }); - }); - }, - - addonInstallDoInstall(target, id) { - let state = this.installs.get(id); - if (!state) { - return Promise.reject(`invalid id ${id}`); - } - return Promise.resolve(state.install.install()); - }, - - addonInstallCancel(target, id) { - let state = this.installs.get(id); - if (!state) { - return Promise.reject(`invalid id ${id}`); - } - return Promise.resolve(state.install.cancel()); - }, - - clearInstalls(ids) { - for (let id of ids) { - this.forgetInstall(id); - } - }, - - clearInstallsFrom(mm) { - for (let [id, info] of this.installs) { - if (info.target.messageManager == mm) { - this.forgetInstall(id); - } - } - }, - }, }; /** @@ -3029,33 +2500,29 @@ var AddonManagerInternal = { * subject to change at any time. */ this.AddonManagerPrivate = { - startup: function() { + startup: function AMP_startup() { AddonManagerInternal.startup(); }, - registerProvider: function(aProvider, aTypes) { + registerProvider: function AMP_registerProvider(aProvider, aTypes) { AddonManagerInternal.registerProvider(aProvider, aTypes); }, - unregisterProvider: function(aProvider) { + unregisterProvider: function AMP_unregisterProvider(aProvider) { AddonManagerInternal.unregisterProvider(aProvider); }, - markProviderSafe: function(aProvider) { + markProviderSafe: function AMP_markProviderSafe(aProvider) { AddonManagerInternal.markProviderSafe(aProvider); }, - backgroundUpdateCheck: function() { + backgroundUpdateCheck: function AMP_backgroundUpdateCheck() { return AddonManagerInternal.backgroundUpdateCheck(); }, backgroundUpdateTimerHandler() { // Don't call through to the real update check if no checks are enabled. - let checkHotfix = AddonManagerInternal.hotfixID && - Services.prefs.getBoolPref(PREF_APP_UPDATE_ENABLED) && - Services.prefs.getBoolPref(PREF_APP_UPDATE_AUTO); - - if (!AddonManagerInternal.updateEnabled && !checkHotfix) { + if (!AddonManagerInternal.updateEnabled) { logger.info("Skipping background update check"); return; } @@ -3063,32 +2530,32 @@ this.AddonManagerPrivate = { AddonManagerInternal.backgroundUpdateCheck(); }, - addStartupChange: function(aType, aID) { + addStartupChange: function AMP_addStartupChange(aType, aID) { AddonManagerInternal.addStartupChange(aType, aID); }, - removeStartupChange: function(aType, aID) { + removeStartupChange: function AMP_removeStartupChange(aType, aID) { AddonManagerInternal.removeStartupChange(aType, aID); }, - notifyAddonChanged: function(aID, aType, aPendingRestart) { + notifyAddonChanged: function AMP_notifyAddonChanged(aID, aType, aPendingRestart) { AddonManagerInternal.notifyAddonChanged(aID, aType, aPendingRestart); }, - updateAddonAppDisabledStates: function() { + updateAddonAppDisabledStates: function AMP_updateAddonAppDisabledStates() { AddonManagerInternal.updateAddonAppDisabledStates(); }, - updateAddonRepositoryData: function(aCallback) { + updateAddonRepositoryData: function AMP_updateAddonRepositoryData(aCallback) { AddonManagerInternal.updateAddonRepositoryData(aCallback); }, - callInstallListeners: function(...aArgs) { + callInstallListeners: function AMP_callInstallListeners(...aArgs) { return AddonManagerInternal.callInstallListeners.apply(AddonManagerInternal, aArgs); }, - callAddonListeners: function(...aArgs) { + callAddonListeners: function AMP_callAddonListeners(...aArgs) { AddonManagerInternal.callAddonListeners.apply(AddonManagerInternal, aArgs); }, @@ -3100,16 +2567,16 @@ this.AddonManagerPrivate = { AddonType: AddonType, - recordTimestamp: function(name, value) { + recordTimestamp: function AMP_recordTimestamp(name, value) { AddonManagerInternal.recordTimestamp(name, value); }, _simpleMeasures: {}, - recordSimpleMeasure: function(name, value) { + recordSimpleMeasure: function AMP_recordSimpleMeasure(name, value) { this._simpleMeasures[name] = value; }, - recordException: function(aModule, aContext, aException) { + recordException: function AMP_recordException(aModule, aContext, aException) { let report = { module: aModule, context: aContext @@ -3129,15 +2596,15 @@ this.AddonManagerPrivate = { this._simpleMeasures.exception = report; }, - getSimpleMeasures: function() { + getSimpleMeasures: function AMP_getSimpleMeasures() { return this._simpleMeasures; }, - getTelemetryDetails: function() { + getTelemetryDetails: function AMP_getTelemetryDetails() { return AddonManagerInternal.telemetryDetails; }, - setTelemetryDetails: function(aProvider, aDetails) { + setTelemetryDetails: function AMP_setTelemetryDetails(aProvider, aDetails) { AddonManagerInternal.telemetryDetails[aProvider] = aDetails; }, @@ -3156,7 +2623,7 @@ this.AddonManagerPrivate = { * This can be used as an implementation for Addon.findUpdates() when * no update mechanism is available. */ - callNoUpdateListeners: function(addon, listener, reason, appVersion, platformVersion) { + callNoUpdateListeners: function (addon, listener, reason, appVersion, platformVersion) { if ("onNoCompatibilityUpdateAvailable" in listener) { safeCall(listener.onNoCompatibilityUpdateAvailable.bind(listener), addon); } @@ -3167,18 +2634,6 @@ this.AddonManagerPrivate = { safeCall(listener.onUpdateFinished.bind(listener), addon); } }, - - get webExtensionsMinPlatformVersion() { - return gWebExtensionsMinPlatformVersion; - }, - - hasUpgradeListener: function(aId) { - return AddonManagerInternal.upgradeListeners.has(aId); - }, - - getUpgradeListener: function(aId) { - return AddonManagerInternal.upgradeListeners.get(aId); - }, }; /** @@ -3187,49 +2642,37 @@ this.AddonManagerPrivate = { */ this.AddonManager = { // Constants for the AddonInstall.state property - // These will show up as AddonManager.STATE_* (eg, STATE_AVAILABLE) - _states: new Map([ - // The install is available for download. - ["STATE_AVAILABLE", 0], - // The install is being downloaded. - ["STATE_DOWNLOADING", 1], - // The install is checking for compatibility information. - ["STATE_CHECKING", 2], - // The install is downloaded and ready to install. - ["STATE_DOWNLOADED", 3], - // The download failed. - ["STATE_DOWNLOAD_FAILED", 4], - // The install has been postponed. - ["STATE_POSTPONED", 5], - // The add-on is being installed. - ["STATE_INSTALLING", 6], - // The add-on has been installed. - ["STATE_INSTALLED", 7], - // The install failed. - ["STATE_INSTALL_FAILED", 8], - // The install has been cancelled. - ["STATE_CANCELLED", 9], - ]), + // The install is available for download. + STATE_AVAILABLE: 0, + // The install is being downloaded. + STATE_DOWNLOADING: 1, + // The install is checking for compatibility information. + STATE_CHECKING: 2, + // The install is downloaded and ready to install. + STATE_DOWNLOADED: 3, + // The download failed. + STATE_DOWNLOAD_FAILED: 4, + // The add-on is being installed. + STATE_INSTALLING: 5, + // The add-on has been installed. + STATE_INSTALLED: 6, + // The install failed. + STATE_INSTALL_FAILED: 7, + // The install has been cancelled. + STATE_CANCELLED: 8, // Constants representing different types of errors while downloading an // add-on. - // These will show up as AddonManager.ERROR_* (eg, ERROR_NETWORK_FAILURE) - _errors: new Map([ - // The download failed due to network problems. - ["ERROR_NETWORK_FAILURE", -1], - // The downloaded file did not match the provided hash. - ["ERROR_INCORRECT_HASH", -2], - // The downloaded file seems to be corrupted in some way. - ["ERROR_CORRUPT_FILE", -3], - // An error occured trying to write to the filesystem. - ["ERROR_FILE_ACCESS", -4], - // The add-on must be signed and isn't. - ["ERROR_SIGNEDSTATE_REQUIRED", -5], - // The downloaded add-on had a different type than expected. - ["ERROR_UNEXPECTED_ADDON_TYPE", -6], - // The addon did not have the expected ID - ["ERROR_INCORRECT_ID", -7], - ]), + // The download failed due to network problems. + ERROR_NETWORK_FAILURE: -1, + // The downloaded file did not match the provided hash. + ERROR_INCORRECT_HASH: -2, + // The downloaded file seems to be corrupted in some way. + ERROR_CORRUPT_FILE: -3, + // An error occured trying to write to the filesystem. + ERROR_FILE_ACCESS: -4, + // The downloaded file seems to be WebExtension. + ERROR_WEBEXT_FILE: -9, // These must be kept in sync with AddonUpdateChecker. // No error was encountered. @@ -3307,10 +2750,8 @@ this.AddonManager = { SCOPE_APPLICATION: 4, // Installed for all users of the computer. SCOPE_SYSTEM: 8, - // Installed temporarily - SCOPE_TEMPORARY: 16, // The combination of all scopes. - SCOPE_ALL: 31, + SCOPE_ALL: 15, // Add-on type is expected to be displayed in the UI in a list. VIEW_TYPE_LIST: "list", @@ -3348,10 +2789,6 @@ this.AddonManager = { // Same as OPTIONS_TYPE_INLINE, but no Preferences button will be shown. // Used to indicate that only non-interactive information will be shown. OPTIONS_TYPE_INLINE_INFO: 4, - // Similar to OPTIONS_TYPE_INLINE, but rather than generating inline - // options from a specially-formatted XUL file, the contents of the - // file are simply displayed in an inline <browser> element. - OPTIONS_TYPE_INLINE_BROWSER: 5, // Constants for displayed or hidden options notifications // Options notification will be displayed @@ -3379,67 +2816,30 @@ this.AddonManager = { // add-ons that were pending being enabled the last time the application ran. STARTUP_CHANGE_ENABLED: "enabled", - // Constants for Addon.signedState. Any states that should cause an add-on - // to be unusable in builds that require signing should have negative values. - // Add-on signing is not required, e.g. because the pref is disabled. - SIGNEDSTATE_NOT_REQUIRED: undefined, - // Add-on is signed but signature verification has failed. - SIGNEDSTATE_BROKEN: -2, - // Add-on may be signed but by an certificate that doesn't chain to our - // our trusted certificate. - SIGNEDSTATE_UNKNOWN: -1, - // Add-on is unsigned. - SIGNEDSTATE_MISSING: 0, - // Add-on is preliminarily reviewed. - SIGNEDSTATE_PRELIMINARY: 1, - // Add-on is fully reviewed. - SIGNEDSTATE_SIGNED: 2, - // Add-on is system add-on. - SIGNEDSTATE_SYSTEM: 3, - // Constants for the Addon.userDisabled property // Indicates that the userDisabled state of this add-on is currently // ask-to-activate. That is, it can be conditionally enabled on a // case-by-case basis. STATE_ASK_TO_ACTIVATE: "askToActivate", +#ifdef MOZ_EM_DEBUG get __AddonManagerInternal__() { - return AppConstants.DEBUG ? AddonManagerInternal : undefined; + return AddonManagerInternal; }, +#endif get isReady() { return gStartupComplete && !gShutdownInProgress; }, - init() { - this._stateToString = new Map(); - for (let [name, value] of this._states) { - this[name] = value; - this._stateToString.set(value, name); - } - this._errorToString = new Map(); - for (let [name, value] of this._errors) { - this[name] = value; - this._errorToString.set(value, name); - } - }, - - stateToString(state) { - return this._stateToString.get(state); - }, - - errorToString(err) { - return err ? this._errorToString.get(err) : null; - }, - - getInstallForURL: function(aUrl, aCallback, aMimetype, + getInstallForURL: function AM_getInstallForURL(aUrl, aCallback, aMimetype, aHash, aName, aIcons, aVersion, aBrowser) { AddonManagerInternal.getInstallForURL(aUrl, aCallback, aMimetype, aHash, aName, aIcons, aVersion, aBrowser); }, - getInstallForFile: function(aFile, aCallback, aMimetype) { + getInstallForFile: function AM_getInstallForFile(aFile, aCallback, aMimetype) { AddonManagerInternal.getInstallForFile(aFile, aCallback, aMimetype); }, @@ -3450,128 +2850,94 @@ this.AddonManager = { * The type of startup change to get * @return An array of add-on IDs */ - getStartupChanges: function(aType) { + getStartupChanges: function AM_getStartupChanges(aType) { if (!(aType in AddonManagerInternal.startupChanges)) return []; return AddonManagerInternal.startupChanges[aType].slice(0); }, - getAddonByID: function(aID, aCallback) { - if (typeof aCallback != "function") - throw Components.Exception("aCallback must be a function", - Cr.NS_ERROR_INVALID_ARG); - - AddonManagerInternal.getAddonByID(aID) - .then(makeSafe(aCallback)) - .catch(logger.error); + getAddonByID: function AM_getAddonByID(aID, aCallback) { + AddonManagerInternal.getAddonByID(aID, aCallback); }, - getAddonBySyncGUID: function(aGUID, aCallback) { + getAddonBySyncGUID: function AM_getAddonBySyncGUID(aGUID, aCallback) { AddonManagerInternal.getAddonBySyncGUID(aGUID, aCallback); }, - getAddonsByIDs: function(aIDs, aCallback) { - if (typeof aCallback != "function") - throw Components.Exception("aCallback must be a function", - Cr.NS_ERROR_INVALID_ARG); - - AddonManagerInternal.getAddonsByIDs(aIDs) - .then(makeSafe(aCallback)) - .catch(logger.error); + getAddonsByIDs: function AM_getAddonsByIDs(aIDs, aCallback) { + AddonManagerInternal.getAddonsByIDs(aIDs, aCallback); }, - getAddonsWithOperationsByTypes: function(aTypes, aCallback) { + getAddonsWithOperationsByTypes: + function AM_getAddonsWithOperationsByTypes(aTypes, aCallback) { AddonManagerInternal.getAddonsWithOperationsByTypes(aTypes, aCallback); }, - getAddonsByTypes: function(aTypes, aCallback) { + getAddonsByTypes: function AM_getAddonsByTypes(aTypes, aCallback) { AddonManagerInternal.getAddonsByTypes(aTypes, aCallback); }, - getAllAddons: function(aCallback) { + getAllAddons: function AM_getAllAddons(aCallback) { AddonManagerInternal.getAllAddons(aCallback); }, - getInstallsByTypes: function(aTypes, aCallback) { + getInstallsByTypes: function AM_getInstallsByTypes(aTypes, aCallback) { AddonManagerInternal.getInstallsByTypes(aTypes, aCallback); }, - getAllInstalls: function(aCallback) { + getAllInstalls: function AM_getAllInstalls(aCallback) { AddonManagerInternal.getAllInstalls(aCallback); }, - mapURIToAddonID: function(aURI) { + mapURIToAddonID: function AM_mapURIToAddonID(aURI) { return AddonManagerInternal.mapURIToAddonID(aURI); }, - isInstallEnabled: function(aType) { + isInstallEnabled: function AM_isInstallEnabled(aType) { return AddonManagerInternal.isInstallEnabled(aType); }, - isInstallAllowed: function(aType, aInstallingPrincipal) { - return AddonManagerInternal.isInstallAllowed(aType, aInstallingPrincipal); + isInstallAllowed: function AM_isInstallAllowed(aType, aInstallingPrincipal) { + return AddonManagerInternal.isInstallAllowed(aType, ensurePrincipal(aInstallingPrincipal)); }, - installAddonsFromWebpage: function(aType, aBrowser, aInstallingPrincipal, - aInstalls) { + installAddonsFromWebpage: function AM_installAddonsFromWebpage(aType, aBrowser, + aInstallingPrincipal, + aInstalls) { AddonManagerInternal.installAddonsFromWebpage(aType, aBrowser, - aInstallingPrincipal, + ensurePrincipal(aInstallingPrincipal), aInstalls); }, - installTemporaryAddon: function(aDirectory) { - return AddonManagerInternal.installTemporaryAddon(aDirectory); - }, - - installAddonFromSources: function(aDirectory) { - return AddonManagerInternal.installAddonFromSources(aDirectory); - }, - - getAddonByInstanceID: function(aInstanceID) { - return AddonManagerInternal.getAddonByInstanceID(aInstanceID); - }, - - addManagerListener: function(aListener) { + addManagerListener: function AM_addManagerListener(aListener) { AddonManagerInternal.addManagerListener(aListener); }, - removeManagerListener: function(aListener) { + removeManagerListener: function AM_removeManagerListener(aListener) { AddonManagerInternal.removeManagerListener(aListener); }, - addInstallListener: function(aListener) { + addInstallListener: function AM_addInstallListener(aListener) { AddonManagerInternal.addInstallListener(aListener); }, - removeInstallListener: function(aListener) { + removeInstallListener: function AM_removeInstallListener(aListener) { AddonManagerInternal.removeInstallListener(aListener); }, - getUpgradeListener: function(aId) { - return AddonManagerInternal.upgradeListeners.get(aId); - }, - - addUpgradeListener: function(aInstanceID, aCallback) { - AddonManagerInternal.addUpgradeListener(aInstanceID, aCallback); - }, - - removeUpgradeListener: function(aInstanceID) { - AddonManagerInternal.removeUpgradeListener(aInstanceID); - }, - - addAddonListener: function(aListener) { + addAddonListener: function AM_addAddonListener(aListener) { AddonManagerInternal.addAddonListener(aListener); }, - removeAddonListener: function(aListener) { + removeAddonListener: function AM_removeAddonListener(aListener) { AddonManagerInternal.removeAddonListener(aListener); }, - addTypeListener: function(aListener) { + addTypeListener: function AM_addTypeListener(aListener) { AddonManagerInternal.addTypeListener(aListener); }, - removeTypeListener: function(aListener) { + removeTypeListener: function AM_removeTypeListener(aListener) { AddonManagerInternal.removeTypeListener(aListener); }, @@ -3586,7 +2952,7 @@ this.AddonManager = { * The Addon representing the add-on * @return true if the addon should auto-update, false otherwise. */ - shouldAutoUpdate: function(aAddon) { + shouldAutoUpdate: function AM_shouldAutoUpdate(aAddon) { if (!aAddon || typeof aAddon != "object") throw Components.Exception("aAddon must be specified", Cr.NS_ERROR_INVALID_ARG); @@ -3644,29 +3010,15 @@ this.AddonManager = { AddonManagerInternal.autoUpdateDefault = aValue; }, - get hotfixID() { - return AddonManagerInternal.hotfixID; - }, - - escapeAddonURI: function(aAddon, aUri, aAppVersion) { + escapeAddonURI: function AM_escapeAddonURI(aAddon, aUri, aAppVersion) { return AddonManagerInternal.escapeAddonURI(aAddon, aUri, aAppVersion); }, - getPreferredIconURL: function(aAddon, aSize, aWindow = undefined) { - return AddonManagerInternal.getPreferredIconURL(aAddon, aSize, aWindow); - }, - - get webAPI() { - return AddonManagerInternal.webAPI; - }, - get shutdown() { return gShutdownBarrier.client; }, }; -this.AddonManager.init(); - // load the timestamps module into AddonManagerInternal Cu.import("resource://gre/modules/TelemetryTimestamps.jsm", AddonManagerInternal); Object.freeze(AddonManagerInternal); diff --git a/toolkit/mozapps/extensions/AddonManagerWebAPI.cpp b/toolkit/mozapps/extensions/AddonManagerWebAPI.cpp deleted file mode 100644 index 3f2a7a529..000000000 --- a/toolkit/mozapps/extensions/AddonManagerWebAPI.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* 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/. */ - -#include "AddonManagerWebAPI.h" - -#include "mozilla/dom/Navigator.h" -#include "mozilla/dom/NavigatorBinding.h" - -#include "mozilla/Preferences.h" -#include "nsGlobalWindow.h" - -#include "nsIDocShell.h" -#include "nsIScriptObjectPrincipal.h" - -namespace mozilla { -using namespace mozilla::dom; - -static bool -IsValidHost(const nsACString& host) { - // This is ugly, but Preferences.h doesn't have support - // for default prefs or locked prefs - nsCOMPtr<nsIPrefService> prefService (do_GetService(NS_PREFSERVICE_CONTRACTID)); - nsCOMPtr<nsIPrefBranch> prefs; - if (prefService) { - prefService->GetDefaultBranch(nullptr, getter_AddRefs(prefs)); - bool isEnabled; - if (NS_SUCCEEDED(prefs->GetBoolPref("xpinstall.enabled", &isEnabled)) && !isEnabled) { - bool isLocked; - prefs->PrefIsLocked("xpinstall.enabled", &isLocked); - if (isLocked) { - return false; - } - } - } - - if (host.Equals("addons.mozilla.org") || - host.Equals("discovery.addons.mozilla.org") || - host.Equals("testpilot.firefox.com")) { - return true; - } - - // When testing allow access to the developer sites. - if (Preferences::GetBool("extensions.webapi.testing", false)) { - if (host.LowerCaseEqualsLiteral("addons.allizom.org") || - host.LowerCaseEqualsLiteral("discovery.addons.allizom.org") || - host.LowerCaseEqualsLiteral("addons-dev.allizom.org") || - host.LowerCaseEqualsLiteral("discovery.addons-dev.allizom.org") || - host.LowerCaseEqualsLiteral("testpilot.stage.mozaws.net") || - host.LowerCaseEqualsLiteral("testpilot.dev.mozaws.net") || - host.LowerCaseEqualsLiteral("example.com")) { - return true; - } - } - - return false; -} - -// Checks if the given uri is secure and matches one of the hosts allowed to -// access the API. -bool -AddonManagerWebAPI::IsValidSite(nsIURI* uri) -{ - if (!uri) { - return false; - } - - bool isSecure; - nsresult rv = uri->SchemeIs("https", &isSecure); - if (NS_FAILED(rv) || !isSecure) { - return false; - } - - nsAutoCString host; - rv = uri->GetHost(host); - if (NS_FAILED(rv)) { - return false; - } - - return IsValidHost(host); -} - -bool -AddonManagerWebAPI::IsAPIEnabled(JSContext* cx, JSObject* obj) -{ - nsGlobalWindow* global = xpc::WindowGlobalOrNull(obj); - if (!global) { - return false; - } - - nsCOMPtr<nsPIDOMWindowInner> win = global->AsInner(); - if (!win) { - return false; - } - - // Check that the current window and all parent frames are allowed access to - // the API. - while (win) { - nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(win); - if (!sop) { - return false; - } - - nsCOMPtr<nsIPrincipal> principal = sop->GetPrincipal(); - if (!principal) { - return false; - } - - // Reaching a window with a system principal means we have reached - // privileged UI of some kind so stop at this point and allow access. - if (principal->GetIsSystemPrincipal()) { - return true; - } - - nsCOMPtr<nsIDocShell> docShell = win->GetDocShell(); - if (!docShell) { - // This window has been torn down so don't allow access to the API. - return false; - } - - if (!IsValidSite(win->GetDocumentURI())) { - return false; - } - - // Checks whether there is a parent frame of the same type. This won't cross - // mozbrowser or chrome boundaries. - nsCOMPtr<nsIDocShellTreeItem> parent; - nsresult rv = docShell->GetSameTypeParent(getter_AddRefs(parent)); - if (NS_FAILED(rv)) { - return false; - } - - if (!parent) { - // No parent means we've hit a mozbrowser or chrome boundary so allow - // access to the API. - return true; - } - - nsIDocument* doc = win->GetDoc(); - if (!doc) { - return false; - } - - doc = doc->GetParentDocument(); - if (!doc) { - // Getting here means something has been torn down so fail safe. - return false; - } - - - win = doc->GetInnerWindow(); - } - - // Found a document with no inner window, don't grant access to the API. - return false; -} - -namespace dom { - -bool -AddonManagerPermissions::IsHostPermitted(const GlobalObject& /*unused*/, const nsAString& host) -{ - return IsValidHost(NS_ConvertUTF16toUTF8(host)); -} - -} // namespace mozilla::dom - - -} // namespace mozilla diff --git a/toolkit/mozapps/extensions/AddonManagerWebAPI.h b/toolkit/mozapps/extensions/AddonManagerWebAPI.h deleted file mode 100644 index 6830bc91f..000000000 --- a/toolkit/mozapps/extensions/AddonManagerWebAPI.h +++ /dev/null @@ -1,33 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* 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/. */ - -#ifndef addonmanagerwebapi_h_ -#define addonmanagerwebapi_h_ - -#include "nsPIDOMWindow.h" - -namespace mozilla { - -class AddonManagerWebAPI { -public: - static bool IsAPIEnabled(JSContext* cx, JSObject* obj); - -private: - static bool IsValidSite(nsIURI* uri); -}; - -namespace dom { - -class AddonManagerPermissions { -public: - static bool IsHostPermitted(const GlobalObject&, const nsAString& host); -}; - -} // namespace mozilla::dom - -} // namespace mozilla - -#endif // addonmanagerwebapi_h_ diff --git a/toolkit/mozapps/extensions/AddonPathService.cpp b/toolkit/mozapps/extensions/AddonPathService.cpp index 8a405c0ea..ddfdbe817 100644 --- a/toolkit/mozapps/extensions/AddonPathService.cpp +++ b/toolkit/mozapps/extensions/AddonPathService.cpp @@ -14,7 +14,6 @@ #include "nsThreadUtils.h" #include "nsIIOService.h" #include "nsNetUtil.h" -#include "nsIAddonPolicyService.h" #include "nsIFileURL.h" #include "nsIResProtocolHandler.h" #include "nsIChromeRegistry.h" @@ -218,22 +217,8 @@ MapURIToAddonID(nsIURI* aURI) return nullptr; } - bool equals; - nsresult rv; - if (NS_SUCCEEDED(aURI->SchemeIs("moz-extension", &equals)) && equals) { - nsCOMPtr<nsIAddonPolicyService> service = do_GetService("@mozilla.org/addons/policy-service;1"); - if (service) { - nsString addonId; - rv = service->ExtensionURIToAddonId(aURI, addonId); - if (NS_FAILED(rv)) - return nullptr; - - return ConvertAddonId(addonId); - } - } - nsAutoString filePath; - rv = ResolveURI(aURI, filePath); + nsresult rv = ResolveURI(aURI, filePath); if (NS_FAILED(rv)) return nullptr; @@ -255,4 +240,4 @@ MapURIToAddonID(nsIURI* aURI) return AddonPathService::FindAddonId(filePath); } -} // namespace mozilla +} diff --git a/toolkit/mozapps/extensions/ChromeManifestParser.jsm b/toolkit/mozapps/extensions/ChromeManifestParser.jsm index 63f1db785..9a77c5429 100644 --- a/toolkit/mozapps/extensions/ChromeManifestParser.jsm +++ b/toolkit/mozapps/extensions/ChromeManifestParser.jsm @@ -45,7 +45,7 @@ this.ChromeManifestParser = { * @return Array of objects describing each manifest instruction, in the form: * { type: instruction-type, baseURI: string-uri, args: [arguments] } **/ - parseSync: function(aURI) { + parseSync: function CMP_parseSync(aURI) { function parseLine(aLine) { let line = aLine.trim(); if (line.length == 0 || line.charAt(0) == '#') @@ -80,14 +80,14 @@ this.ChromeManifestParser = { lines.forEach(parseLine.bind(this)); return data; }, - - _readFromJar: function(aURI) { + + _readFromJar: function CMP_readFromJar(aURI) { let data = ""; let entries = []; let readers = []; - + try { - // Deconstrict URI, which can be nested jar: URIs. + // Deconstrict URI, which can be nested jar: URIs. let uri = aURI.clone(); while (uri instanceof Ci.nsIJARURI) { entries.push(uri.JAREntry); @@ -99,7 +99,7 @@ this.ChromeManifestParser = { createInstance(Ci.nsIZipReader); reader.open(uri.QueryInterface(Ci.nsIFileURL).file); readers.push(reader); - + // Open the nested jars. for (let i = entries.length - 1; i > 0; i--) { let innerReader = Cc["@mozilla.org/libjar/zip-reader;1"]. @@ -108,7 +108,7 @@ this.ChromeManifestParser = { readers.push(innerReader); reader = innerReader; } - + // First entry is the actual file we want to read. let zis = reader.getInputStream(entries[0]); data = NetUtil.readInputStreamToString(zis, zis.available()); @@ -120,15 +120,15 @@ this.ChromeManifestParser = { flushJarCache(readers[i].file); } } - + return data; }, - - _readFromFile: function(aURI) { + + _readFromFile: function CMP_readFromFile(aURI) { let file = aURI.QueryInterface(Ci.nsIFileURL).file; if (!file.exists() || !file.isFile()) return ""; - + let data = ""; let fis = Cc["@mozilla.org/network/file-input-stream;1"]. createInstance(Ci.nsIFileInputStream); @@ -151,7 +151,9 @@ this.ChromeManifestParser = { * Instruction type to filter by. * @return True if any matching instructions were found in the manifest. */ - hasType: function(aManifest, aType) { - return aManifest.some(entry => entry.type == aType); + hasType: function CMP_hasType(aManifest, aType) { + return aManifest.some(function hasType_matchEntryType(aEntry) { + return aEntry.type == aType; + }); } }; diff --git a/toolkit/mozapps/extensions/DeferredSave.jsm b/toolkit/mozapps/extensions/DeferredSave.jsm index 89f82b265..7587ce83b 100644 --- a/toolkit/mozapps/extensions/DeferredSave.jsm +++ b/toolkit/mozapps/extensions/DeferredSave.jsm @@ -9,7 +9,6 @@ const Cc = Components.classes; const Ci = Components.interfaces; Cu.import("resource://gre/modules/osfile.jsm"); -/* globals OS*/ Cu.import("resource://gre/modules/Promise.jsm"); // Make it possible to mock out timers for testing @@ -21,26 +20,26 @@ this.EXPORTED_SYMBOLS = ["DeferredSave"]; const DEFAULT_SAVE_DELAY_MS = 50; Cu.import("resource://gre/modules/Log.jsm"); -// Configure a logger at the parent 'DeferredSave' level to format -// messages for all the modules under DeferredSave.* +//Configure a logger at the parent 'DeferredSave' level to format +//messages for all the modules under DeferredSave.* const DEFERREDSAVE_PARENT_LOGGER_ID = "DeferredSave"; var parentLogger = Log.repository.getLogger(DEFERREDSAVE_PARENT_LOGGER_ID); parentLogger.level = Log.Level.Warn; var formatter = new Log.BasicFormatter(); -// Set parent logger (and its children) to append to -// the Javascript section of the Browser Console +//Set parent logger (and its children) to append to +//the Javascript section of the Browser Console parentLogger.addAppender(new Log.ConsoleAppender(formatter)); -// Set parent logger (and its children) to -// also append to standard out +//Set parent logger (and its children) to +//also append to standard out parentLogger.addAppender(new Log.DumpAppender(formatter)); -// Provide the ability to enable/disable logging -// messages at runtime. -// If the "extensions.logging.enabled" preference is -// missing or 'false', messages at the WARNING and higher -// severity should be logged to the JS console and standard error. -// If "extensions.logging.enabled" is set to 'true', messages -// at DEBUG and higher should go to JS console and standard error. +//Provide the ability to enable/disable logging +//messages at runtime. +//If the "extensions.logging.enabled" preference is +//missing or 'false', messages at the WARNING and higher +//severity should be logged to the JS console and standard error. +//If "extensions.logging.enabled" is set to 'true', messages +//at DEBUG and higher should go to JS console and standard error. Cu.import("resource://gre/modules/Services.jsm"); const PREF_LOGGING_ENABLED = "extensions.logging.enabled"; @@ -52,13 +51,13 @@ const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed"; * parent 'addons' level logger accordingly. */ var PrefObserver = { - init: function() { + init: function PrefObserver_init() { Services.prefs.addObserver(PREF_LOGGING_ENABLED, this, false); Services.obs.addObserver(this, "xpcom-shutdown", false); this.observe(null, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, PREF_LOGGING_ENABLED); }, - observe: function(aSubject, aTopic, aData) { + observe: function PrefObserver_observe(aSubject, aTopic, aData) { if (aTopic == "xpcom-shutdown") { Services.prefs.removeObserver(PREF_LOGGING_ENABLED, this); Services.obs.removeObserver(this, "xpcom-shutdown"); @@ -104,7 +103,7 @@ PrefObserver.init(); * that marks the data as needing to be saved, and when the DeferredSave * begins writing the data to disk. Default 50 milliseconds. */ -this.DeferredSave = function(aPath, aDataProvider, aDelay) { +this.DeferredSave = function (aPath, aDataProvider, aDelay) { // Create a new logger (child of 'DeferredSave' logger) // for use by this particular instance of DeferredSave object let leafName = OS.Path.basename(aPath); @@ -208,7 +207,7 @@ this.DeferredSave.prototype = { try { toSave = this._dataProvider(); } - catch (e) { + catch(e) { this.logger.error("Deferred save dataProvider failed", e); writing.then(null, error => {}) .then(count => { @@ -217,7 +216,7 @@ this.DeferredSave.prototype = { return; } - writing.then(null, error => { return 0; }) + writing.then(null, error => {return 0;}) .then(count => { this.logger.debug("Starting write"); this.totalSaves++; diff --git a/toolkit/mozapps/extensions/LightweightThemeManager.jsm b/toolkit/mozapps/extensions/LightweightThemeManager.jsm index 5dd41831d..5856bfa91 100644 --- a/toolkit/mozapps/extensions/LightweightThemeManager.jsm +++ b/toolkit/mozapps/extensions/LightweightThemeManager.jsm @@ -11,7 +11,6 @@ const Ci = Components.interfaces; Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); Components.utils.import("resource://gre/modules/AddonManager.jsm"); -/* globals AddonManagerPrivate*/ Components.utils.import("resource://gre/modules/Services.jsm"); const ID_SUFFIX = "@personas.mozilla.org"; @@ -42,31 +41,26 @@ const PERSIST_FILES = { XPCOMUtils.defineLazyModuleGetter(this, "LightweightThemeImageOptimizer", "resource://gre/modules/addons/LightweightThemeImageOptimizer.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "ServiceRequest", - "resource://gre/modules/ServiceRequest.jsm"); - -XPCOMUtils.defineLazyGetter(this, "_prefs", () => { - return Services.prefs.getBranch("lightweightThemes."); +this.__defineGetter__("_prefs", function prefsGetter() { + delete this._prefs; + return this._prefs = Services.prefs.getBranch("lightweightThemes."); }); -Object.defineProperty(this, "_maxUsedThemes", { - get: function() { - delete this._maxUsedThemes; - try { - this._maxUsedThemes = _prefs.getIntPref("maxUsedThemes"); - } - catch (e) { - this._maxUsedThemes = DEFAULT_MAX_USED_THEMES_COUNT; - } - return this._maxUsedThemes; - }, +this.__defineGetter__("_maxUsedThemes", function maxUsedThemesGetter() { + delete this._maxUsedThemes; + try { + this._maxUsedThemes = _prefs.getIntPref("maxUsedThemes"); + } + catch (e) { + this._maxUsedThemes = DEFAULT_MAX_USED_THEMES_COUNT; + } + return this._maxUsedThemes; +}); - set: function(val) { - delete this._maxUsedThemes; - return this._maxUsedThemes = val; - }, - configurable: true, +this.__defineSetter__("_maxUsedThemes", function maxUsedThemesSetter(aVal) { + delete this._maxUsedThemes; + return this._maxUsedThemes = aVal; }); // Holds the ID of the theme being enabled or disabled while sending out the @@ -75,60 +69,25 @@ Object.defineProperty(this, "_maxUsedThemes", { var _themeIDBeingEnabled = null; var _themeIDBeingDisabled = null; -// Convert from the old storage format (in which the order of usedThemes -// was combined with isThemeSelected to determine which theme was selected) -// to the new one (where a selectedThemeID determines which theme is selected). -(function() { - let wasThemeSelected = false; - try { - wasThemeSelected = _prefs.getBoolPref("isThemeSelected"); - } catch (e) { } - - if (wasThemeSelected) { - _prefs.clearUserPref("isThemeSelected"); - let themes = []; - try { - themes = JSON.parse(_prefs.getComplexValue("usedThemes", - Ci.nsISupportsString).data); - } catch (e) { } - - if (Array.isArray(themes) && themes[0]) { - _prefs.setCharPref("selectedThemeID", themes[0].id); - } - } -})(); - this.LightweightThemeManager = { - get name() { - return "LightweightThemeManager"; - }, - - // Themes that can be added for an application. They can't be removed, and - // will always show up at the top of the list. - _builtInThemes: new Map(), + get name() "LightweightThemeManager", get usedThemes () { - let themes = []; try { - themes = JSON.parse(_prefs.getComplexValue("usedThemes", - Ci.nsISupportsString).data); - } catch (e) { } - - themes.push(...this._builtInThemes.values()); - return themes; + return JSON.parse(_prefs.getComplexValue("usedThemes", + Ci.nsISupportsString).data); + } catch (e) { + return []; + } }, get currentTheme () { - let selectedThemeID = null; try { - selectedThemeID = _prefs.getCharPref("selectedThemeID"); + if (_prefs.getBoolPref("isThemeSelected")) + var data = this.usedThemes[0]; } catch (e) {} - let data = null; - if (selectedThemeID) { - data = this.getUsedTheme(selectedThemeID); - } - return data; + return data || null; }, get currentThemeForDisplay () { @@ -151,11 +110,11 @@ this.LightweightThemeManager = { return _setCurrentTheme(aData, false); }, - setLocalTheme: function(aData) { + setLocalTheme: function LightweightThemeManager_setLocalTheme(aData) { _setCurrentTheme(aData, true); }, - getUsedTheme: function(aId) { + getUsedTheme: function LightweightThemeManager_getUsedTheme(aId) { var usedThemes = this.usedThemes; for (let usedTheme of usedThemes) { if (usedTheme.id == aId) @@ -164,9 +123,9 @@ this.LightweightThemeManager = { return null; }, - forgetUsedTheme: function(aId) { + forgetUsedTheme: function LightweightThemeManager_forgetUsedTheme(aId) { let theme = this.getUsedTheme(aId); - if (!theme || LightweightThemeManager._builtInThemes.has(theme.id)) + if (!theme) return; let wrapper = new AddonWrapper(theme); @@ -182,35 +141,7 @@ this.LightweightThemeManager = { AddonManagerPrivate.callAddonListeners("onUninstalled", wrapper); }, - addBuiltInTheme: function(theme) { - if (!theme || !theme.id || this.usedThemes.some(t => t.id == theme.id)) { - throw new Error("Trying to add invalid builtIn theme"); - } - - this._builtInThemes.set(theme.id, theme); - - if (_prefs.getCharPref("selectedThemeID") == theme.id) { - this.currentTheme = theme; - } - }, - - forgetBuiltInTheme: function(id) { - if (!this._builtInThemes.has(id)) { - let currentTheme = this.currentTheme; - if (currentTheme && currentTheme.id == id) { - this.currentTheme = null; - } - } - return this._builtInThemes.delete(id); - }, - - clearBuiltInThemes: function() { - for (let id of this._builtInThemes.keys()) { - this.forgetBuiltInTheme(id); - } - }, - - previewTheme: function(aData) { + previewTheme: function LightweightThemeManager_previewTheme(aData) { let cancel = Cc["@mozilla.org/supports-PRBool;1"].createInstance(Ci.nsISupportsPRBool); cancel.data = false; Services.obs.notifyObservers(cancel, "lightweight-theme-preview-requested", @@ -229,7 +160,7 @@ this.LightweightThemeManager = { _notifyWindows(aData); }, - resetPreview: function() { + resetPreview: function LightweightThemeManager_resetPreview() { if (_previewTimer) { _previewTimer.cancel(); _previewTimer = null; @@ -237,7 +168,7 @@ this.LightweightThemeManager = { } }, - parseTheme: function(aString, aBaseURI) { + parseTheme: function LightweightThemeManager_parseTheme(aString, aBaseURI) { try { return _sanitizeTheme(JSON.parse(aString), aBaseURI, false); } catch (e) { @@ -245,7 +176,7 @@ this.LightweightThemeManager = { } }, - updateCurrentTheme: function() { + updateCurrentTheme: function LightweightThemeManager_updateCurrentTheme() { try { if (!_prefs.getBoolPref("update.enabled")) return; @@ -257,7 +188,8 @@ this.LightweightThemeManager = { if (!theme || !theme.updateURL) return; - var req = new ServiceRequest(); + var req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"] + .createInstance(Ci.nsIXMLHttpRequest); req.mozBackgroundRequest = true; req.overrideMimeType("text/plain"); @@ -267,19 +199,20 @@ this.LightweightThemeManager = { // Prevent the request from writing to the cache. req.channel.loadFlags |= Ci.nsIRequest.INHIBIT_CACHING; - req.addEventListener("load", () => { + var self = this; + req.addEventListener("load", function loadEventListener() { if (req.status != 200) return; - let newData = this.parseTheme(req.responseText, theme.updateURL); + let newData = self.parseTheme(req.responseText, theme.updateURL); if (!newData || newData.id != theme.id || _version(newData) == _version(theme)) return; - var currentTheme = this.currentTheme; + var currentTheme = self.currentTheme; if (currentTheme && currentTheme.id == theme.id) - this.currentTheme = newData; + self.currentTheme = newData; }, false); req.send(null); @@ -291,7 +224,7 @@ this.LightweightThemeManager = { * @param aData * The lightweight theme to switch to */ - themeChanged: function(aData) { + themeChanged: function LightweightThemeManager_themeChanged(aData) { if (_previewTimer) { _previewTimer.cancel(); _previewTimer = null; @@ -303,17 +236,13 @@ this.LightweightThemeManager = { _updateUsedThemes(usedThemes); if (PERSIST_ENABLED) { LightweightThemeImageOptimizer.purge(); - _persistImages(aData, function() { + _persistImages(aData, function themeChanged_persistImages() { _notifyWindows(this.currentThemeForDisplay); }.bind(this)); } } - if (aData) - _prefs.setCharPref("selectedThemeID", aData.id); - else - _prefs.setCharPref("selectedThemeID", ""); - + _prefs.setBoolPref("isThemeSelected", aData != null); _notifyWindows(aData); Services.obs.notifyObservers(null, "lightweight-theme-changed", null); }, @@ -322,7 +251,7 @@ this.LightweightThemeManager = { * Starts the Addons provider and enables the new lightweight theme if * necessary. */ - startup: function() { + startup: function LightweightThemeManager_startup() { if (Services.prefs.prefHasUserValue(PREF_LWTHEME_TO_SELECT)) { let id = Services.prefs.getCharPref(PREF_LWTHEME_TO_SELECT); if (id) @@ -338,7 +267,7 @@ this.LightweightThemeManager = { /** * Shuts down the provider. */ - shutdown: function() { + shutdown: function LightweightThemeManager_shutdown() { _prefs.removeObserver("", _prefObserver); }, @@ -354,7 +283,7 @@ this.LightweightThemeManager = { * true if the newly enabled add-on will only become enabled after a * restart */ - addonChanged: function(aId, aType, aPendingRestart) { + addonChanged: function LightweightThemeManager_addonChanged(aId, aType, aPendingRestart) { if (aType != ADDON_TYPE) return; @@ -371,10 +300,12 @@ this.LightweightThemeManager = { AddonManagerPrivate.callAddonListeners("onOperationCancelled", new AddonWrapper(this.getUsedTheme(next))); } - else if (id == current.id) { - AddonManagerPrivate.callAddonListeners("onOperationCancelled", - new AddonWrapper(current)); - return; + else { + if (id == current.id) { + AddonManagerPrivate.callAddonListeners("onOperationCancelled", + new AddonWrapper(current)); + return; + } } } catch (e) { @@ -425,7 +356,7 @@ this.LightweightThemeManager = { * @param aCallback * A callback to pass the Addon to */ - getAddonByID: function(aId, aCallback) { + getAddonByID: function LightweightThemeManager_getAddonByID(aId, aCallback) { let id = _getInternalID(aId); if (!id) { aCallback(null); @@ -449,70 +380,72 @@ this.LightweightThemeManager = { * @param aCallback * A callback to pass an array of Addons to */ - getAddonsByTypes: function(aTypes, aCallback) { + getAddonsByTypes: function LightweightThemeManager_getAddonsByTypes(aTypes, aCallback) { if (aTypes && aTypes.indexOf(ADDON_TYPE) == -1) { aCallback([]); return; } - aCallback(this.usedThemes.map(a => new AddonWrapper(a))); + // Tycho: aCallback([new AddonWrapper(a) for each (a in this.usedThemes)]); + let result = []; + for each(let a in this.usedThemes) { + result.push(new AddonWrapper(a)); + } + + aCallback(result); }, }; -const wrapperMap = new WeakMap(); -let themeFor = wrapper => wrapperMap.get(wrapper); - /** * The AddonWrapper wraps lightweight theme to provide the data visible to * consumers of the AddonManager API. */ function AddonWrapper(aTheme) { - wrapperMap.set(this, aTheme); -} - -AddonWrapper.prototype = { - get id() { - return themeFor(this).id + ID_SUFFIX; - }, - - get type() { - return ADDON_TYPE; - }, - - get isActive() { + this.__defineGetter__("id", function AddonWrapper_idGetter() aTheme.id + ID_SUFFIX); + this.__defineGetter__("type", function AddonWrapper_typeGetter() ADDON_TYPE); + this.__defineGetter__("isActive", function AddonWrapper_isActiveGetter() { let current = LightweightThemeManager.currentTheme; if (current) - return themeFor(this).id == current.id; + return aTheme.id == current.id; return false; - }, + }); - get name() { - return themeFor(this).name; - }, + this.__defineGetter__("name", function AddonWrapper_nameGetter() aTheme.name); + this.__defineGetter__("version", function AddonWrapper_versionGetter() { + return "version" in aTheme ? aTheme.version : ""; + }); - get version() { - let theme = themeFor(this); - return "version" in theme ? theme.version : ""; - }, + ["description", "homepageURL", "iconURL"].forEach(function(prop) { + this.__defineGetter__(prop, function AddonWrapper_optionalPropGetter() { + return prop in aTheme ? aTheme[prop] : null; + }); + }, this); - get creator() { - let theme = themeFor(this); - return "author" in theme ? new AddonManagerPrivate.AddonAuthor(theme.author) : null; - }, + ["installDate", "updateDate"].forEach(function(prop) { + this.__defineGetter__(prop, function AddonWrapper_datePropGetter() { + return prop in aTheme ? new Date(aTheme[prop]) : null; + }); + }, this); - get screenshots() { - let url = themeFor(this).previewURL; + this.__defineGetter__("creator", function AddonWrapper_creatorGetter() { + return new AddonManagerPrivate.AddonAuthor(aTheme.author); + }); + + this.__defineGetter__("screenshots", function AddonWrapper_screenshotsGetter() { + let url = aTheme.previewURL; return [new AddonManagerPrivate.AddonScreenshot(url)]; - }, + }); - get pendingOperations() { + this.__defineGetter__("pendingOperations", + function AddonWrapper_pendingOperationsGetter() { let pending = AddonManager.PENDING_NONE; if (this.isActive == this.userDisabled) pending |= this.isActive ? AddonManager.PENDING_DISABLE : AddonManager.PENDING_ENABLE; return pending; - }, + }); - get operationsRequiringRestart() { + this.__defineGetter__("operationsRequiringRestart", + function AddonWrapper_operationsRequiringRestartGetter() { // If a non-default theme is in use then a restart will be required to // enable lightweight themes unless dynamic theme switching is enabled if (Services.prefs.prefHasUserValue(PREF_GENERAL_SKINS_SELECTEDSKIN)) { @@ -526,56 +459,65 @@ AddonWrapper.prototype = { } return AddonManager.OP_NEEDS_RESTART_NONE; - }, + }); - get size() { + this.__defineGetter__("size", function AddonWrapper_sizeGetter() { // The size changes depending on whether the theme is in use or not, this is // probably not worth exposing. return null; - }, - - get permissions() { - let permissions = 0; + }); - // Do not allow uninstall of builtIn themes. - if (!LightweightThemeManager._builtInThemes.has(themeFor(this).id)) - permissions = AddonManager.PERM_CAN_UNINSTALL; + this.__defineGetter__("permissions", function AddonWrapper_permissionsGetter() { + let permissions = AddonManager.PERM_CAN_UNINSTALL; if (this.userDisabled) permissions |= AddonManager.PERM_CAN_ENABLE; else permissions |= AddonManager.PERM_CAN_DISABLE; return permissions; - }, + }); - get userDisabled() { - let id = themeFor(this).id; - if (_themeIDBeingEnabled == id) + this.__defineGetter__("userDisabled", function AddonWrapper_userDisabledGetter() { + if (_themeIDBeingEnabled == aTheme.id) return false; - if (_themeIDBeingDisabled == id) + if (_themeIDBeingDisabled == aTheme.id) return true; try { let toSelect = Services.prefs.getCharPref(PREF_LWTHEME_TO_SELECT); - return id != toSelect; + return aTheme.id != toSelect; } catch (e) { let current = LightweightThemeManager.currentTheme; - return !current || current.id != id; + return !current || current.id != aTheme.id; } - }, + }); - set userDisabled(val) { + this.__defineSetter__("userDisabled", function AddonWrapper_userDisabledSetter(val) { if (val == this.userDisabled) return val; if (val) LightweightThemeManager.currentTheme = null; else - LightweightThemeManager.currentTheme = themeFor(this); + LightweightThemeManager.currentTheme = aTheme; return val; - }, + }); + + this.uninstall = function AddonWrapper_uninstall() { + LightweightThemeManager.forgetUsedTheme(aTheme.id); + }; + + this.cancelUninstall = function AddonWrapper_cancelUninstall() { + throw new Error("Theme is not marked to be uninstalled"); + }; + + this.findUpdates = function AddonWrapper_findUpdates(listener, reason, appVersion, platformVersion) { + AddonManagerPrivate.callNoUpdateListeners(this, listener, reason, appVersion, platformVersion); + }; +} +AddonWrapper.prototype = { // Lightweight themes are never disabled by the application get appDisabled() { return false; @@ -598,20 +540,8 @@ AddonWrapper.prototype = { return false; }, - uninstall: function() { - LightweightThemeManager.forgetUsedTheme(themeFor(this).id); - }, - - cancelUninstall: function() { - throw new Error("Theme is not marked to be uninstalled"); - }, - - findUpdates: function(listener, reason, appVersion, platformVersion) { - AddonManagerPrivate.callNoUpdateListeners(this, listener, reason, appVersion, platformVersion); - }, - // Lightweight themes are always compatible - isCompatibleWith: function(appVersion, platformVersion) { + isCompatibleWith: function AddonWrapper_isCompatibleWith(appVersion, platformVersion) { return true; }, @@ -626,26 +556,6 @@ AddonWrapper.prototype = { } }; -["description", "homepageURL", "iconURL"].forEach(function(prop) { - Object.defineProperty(AddonWrapper.prototype, prop, { - get: function() { - let theme = themeFor(this); - return prop in theme ? theme[prop] : null; - }, - enumarable: true, - }); -}); - -["installDate", "updateDate"].forEach(function(prop) { - Object.defineProperty(AddonWrapper.prototype, prop, { - get: function() { - let theme = themeFor(this); - return prop in theme ? new Date(theme[prop]) : null; - }, - enumarable: true, - }); -}); - /** * Converts the ID used by the public AddonManager API to an lightweight theme * ID. @@ -702,7 +612,7 @@ function _setCurrentTheme(aData, aLocal) { _updateUsedThemes(usedThemes); if (isInstall) - AddonManagerPrivate.callAddonListeners("onInstalled", wrapper); + AddonManagerPrivate.callAddonListeners("onInstalled", wrapper); } if (cancel.data) @@ -764,24 +674,17 @@ function _sanitizeTheme(aData, aBaseURI, aLocal) { return result; } -function _usedThemesExceptId(aId) { - return LightweightThemeManager.usedThemes.filter(function(t) { - return "id" in t && t.id != aId; - }); -} +function _usedThemesExceptId(aId) + LightweightThemeManager.usedThemes.filter( + function usedThemesExceptId_filterID(t) "id" in t && t.id != aId); -function _version(aThemeData) { - return aThemeData.version || ""; -} +function _version(aThemeData) + aThemeData.version || ""; -function _makeURI(aURL, aBaseURI) { - return Services.io.newURI(aURL, null, aBaseURI); -} +function _makeURI(aURL, aBaseURI) + Services.io.newURI(aURL, null, aBaseURI); function _updateUsedThemes(aList) { - // Remove app-specific themes before saving them to the usedThemes pref. - aList = aList.filter(theme => !LightweightThemeManager._builtInThemes.has(theme.id)); - // Send uninstall events for all themes that need to be removed. while (aList.length > _maxUsedThemes) { let wrapper = new AddonWrapper(aList[aList.length - 1]); @@ -805,7 +708,7 @@ function _notifyWindows(aThemeData) { var _previewTimer; var _previewTimerCallback = { - notify: function() { + notify: function _previewTimerCallback_notify() { LightweightThemeManager.resetPreview(); } }; @@ -829,17 +732,15 @@ function _prefObserver(aSubject, aTopic, aData) { } function _persistImages(aData, aCallback) { - function onSuccess(key) { - return function () { - let current = LightweightThemeManager.currentTheme; - if (current && current.id == aData.id) { - _prefs.setBoolPref("persisted." + key, true); - } - if (--numFilesToPersist == 0 && aCallback) { - aCallback(); - } - }; - } + function onSuccess(key) function () { + let current = LightweightThemeManager.currentTheme; + if (current && current.id == aData.id) { + _prefs.setBoolPref("persisted." + key, true); + } + if (--numFilesToPersist == 0 && aCallback) { + aCallback(); + } + }; let numFilesToPersist = 0; for (let key in PERSIST_FILES) { @@ -882,11 +783,11 @@ function _persistImage(sourceURL, localFileName, successCallback) { } function _persistProgressListener(successCallback) { - this.onLocationChange = function() {}; - this.onProgressChange = function() {}; - this.onStatusChange = function() {}; - this.onSecurityChange = function() {}; - this.onStateChange = function(aWebProgress, aRequest, aStateFlags, aStatus) { + this.onLocationChange = function persistProgressListener_onLocationChange() {}; + this.onProgressChange = function persistProgressListener_onProgressChange() {}; + this.onStatusChange = function persistProgressListener_onStatusChange() {}; + this.onSecurityChange = function persistProgressListener_onSecurityChange() {}; + this.onStateChange = function persistProgressListener_onStateChange(aWebProgress, aRequest, aStateFlags, aStatus) { if (aRequest && aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK && aStateFlags & Ci.nsIWebProgressListener.STATE_STOP) { diff --git a/toolkit/mozapps/extensions/addonManager.js b/toolkit/mozapps/extensions/addonManager.js index d34cbaf62..731e70c6c 100644 --- a/toolkit/mozapps/extensions/addonManager.js +++ b/toolkit/mozapps/extensions/addonManager.js @@ -12,6 +12,8 @@ const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; +const PREF_EM_UPDATE_INTERVAL = "extensions.update.interval"; + // The old XPInstall error codes const EXECUTION_ERROR = -203; const CANT_READ_ARCHIVE = -207; @@ -24,13 +26,6 @@ const MSG_INSTALL_ENABLED = "WebInstallerIsInstallEnabled"; const MSG_INSTALL_ADDONS = "WebInstallerInstallAddonsFromWebpage"; const MSG_INSTALL_CALLBACK = "WebInstallerInstallCallback"; -const MSG_PROMISE_REQUEST = "WebAPIPromiseRequest"; -const MSG_PROMISE_RESULT = "WebAPIPromiseResult"; -const MSG_INSTALL_EVENT = "WebAPIInstallEvent"; -const MSG_INSTALL_CLEANUP = "WebAPICleanup"; -const MSG_ADDON_EVENT_REQ = "WebAPIAddonEventRequest"; -const MSG_ADDON_EVENT = "WebAPIAddonEvent"; - const CHILD_SCRIPT = "resource://gre/modules/addons/Content.js"; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); @@ -38,44 +33,35 @@ Cu.import("resource://gre/modules/Services.jsm"); var gSingleton = null; +var gParentMM = null; + + function amManager() { Cu.import("resource://gre/modules/AddonManager.jsm"); - /* globals AddonManagerPrivate*/ - Services.mm.loadFrameScript(CHILD_SCRIPT, true); - Services.mm.addMessageListener(MSG_INSTALL_ENABLED, this); - Services.mm.addMessageListener(MSG_INSTALL_ADDONS, this); - Services.mm.addMessageListener(MSG_PROMISE_REQUEST, this); - Services.mm.addMessageListener(MSG_INSTALL_CLEANUP, this); - Services.mm.addMessageListener(MSG_ADDON_EVENT_REQ, this); + let globalMM = Cc["@mozilla.org/globalmessagemanager;1"] + .getService(Ci.nsIMessageListenerManager); + globalMM.loadFrameScript(CHILD_SCRIPT, true); + globalMM.addMessageListener(MSG_INSTALL_ADDONS, this); - Services.obs.addObserver(this, "message-manager-close", false); - Services.obs.addObserver(this, "message-manager-disconnect", false); - - AddonManager.webAPI.setEventHandler(this.sendEvent); + gParentMM = Cc["@mozilla.org/parentprocessmessagemanager;1"] + .getService(Ci.nsIMessageListenerManager); + gParentMM.addMessageListener(MSG_INSTALL_ENABLED, this); // Needed so receiveMessage can be called directly by JS callers this.wrappedJSObject = this; } amManager.prototype = { - observe: function(aSubject, aTopic, aData) { - switch (aTopic) { - case "addons-startup": - AddonManagerPrivate.startup(); - break; - - case "message-manager-close": - case "message-manager-disconnect": - this.childClosed(aSubject); - break; - } + observe: function AMC_observe(aSubject, aTopic, aData) { + if (aTopic == "addons-startup") + AddonManagerPrivate.startup(); }, /** * @see amIAddonManager.idl */ - mapURIToAddonID: function(uri, id) { + mapURIToAddonID: function AMC_mapURIToAddonID(uri, id) { id.value = AddonManager.mapURIToAddonID(uri); return !!id.value; }, @@ -83,15 +69,19 @@ amManager.prototype = { /** * @see amIWebInstaller.idl */ - isInstallEnabled: function(aMimetype, aReferer) { + isInstallEnabled: function AMC_isInstallEnabled(aMimetype, aReferer) { return AddonManager.isInstallEnabled(aMimetype); }, /** * @see amIWebInstaller.idl */ - installAddonsFromWebpage: function(aMimetype, aBrowser, aInstallingPrincipal, - aUris, aHashes, aNames, aIcons, aCallback) { + installAddonsFromWebpage: function AMC_installAddonsFromWebpage(aMimetype, + aBrowser, + aInstallingPrincipal, + aUris, aHashes, + aNames, aIcons, + aCallback) { if (aUris.length == 0) return false; @@ -108,7 +98,7 @@ amManager.prototype = { return; } let uri = aUris.shift(); - AddonManager.getInstallForURL(uri, function(aInstall) { + AddonManager.getInstallForURL(uri, function buildNextInstall_getInstallForURL(aInstall) { function callCallback(aUri, aStatus) { try { aCallback.onInstallEnded(aUri, aStatus); @@ -122,22 +112,22 @@ amManager.prototype = { installs.push(aInstall); if (aCallback) { aInstall.addListener({ - onDownloadCancelled: function(aInstall) { + onDownloadCancelled: function buildNextInstall_onDownloadCancelled(aInstall) { callCallback(uri, USER_CANCELLED); }, - onDownloadFailed: function(aInstall) { + onDownloadFailed: function buildNextInstall_onDownloadFailed(aInstall) { if (aInstall.error == AddonManager.ERROR_CORRUPT_FILE) callCallback(uri, CANT_READ_ARCHIVE); else callCallback(uri, DOWNLOAD_ERROR); }, - onInstallFailed: function(aInstall) { + onInstallFailed: function buildNextInstall_onInstallFailed(aInstall) { callCallback(uri, EXECUTION_ERROR); }, - onInstallEnded: function(aInstall, aStatus) { + onInstallEnded: function buildNextInstall_onInstallEnded(aInstall, aStatus) { callCallback(uri, SUCCESS); } }); @@ -154,49 +144,17 @@ amManager.prototype = { return retval; }, - notify: function(aTimer) { + notify: function AMC_notify(aTimer) { AddonManagerPrivate.backgroundUpdateTimerHandler(); }, - // Maps message manager instances for content processes to the associated - // AddonListener instances. - addonListeners: new Map(), - - _addAddonListener(target) { - if (!this.addonListeners.has(target)) { - let handler = (event, id, needsRestart) => { - target.sendAsyncMessage(MSG_ADDON_EVENT, {event, id, needsRestart}); - }; - let listener = { - onEnabling: (addon, needsRestart) => handler("onEnabling", addon.id, needsRestart), - onEnabled: (addon) => handler("onEnabled", addon.id, false), - onDisabling: (addon, needsRestart) => handler("onDisabling", addon.id, needsRestart), - onDisabled: (addon) => handler("onDisabled", addon.id, false), - onInstalling: (addon, needsRestart) => handler("onInstalling", addon.id, needsRestart), - onInstalled: (addon) => handler("onInstalled", addon.id, false), - onUninstalling: (addon, needsRestart) => handler("onUninstalling", addon.id, needsRestart), - onUninstalled: (addon) => handler("onUninstalled", addon.id, false), - onOperationCancelled: (addon) => handler("onOperationCancelled", addon.id, false), - }; - this.addonListeners.set(target, listener); - AddonManager.addAddonListener(listener); - } - }, - - _removeAddonListener(target) { - if (this.addonListeners.has(target)) { - AddonManager.removeAddonListener(this.addonListeners.get(target)); - this.addonListeners.delete(target); - } - }, - /** * messageManager callback function. * * Listens to requests from child processes for InstallTrigger * activity, and sends back callbacks. */ - receiveMessage: function(aMessage) { + receiveMessage: function AMC_receiveMessage(aMessage) { let payload = aMessage.data; switch (aMessage.name) { @@ -206,10 +164,9 @@ amManager.prototype = { case MSG_INSTALL_ADDONS: { let callback = null; if (payload.callbackID != -1) { - let mm = aMessage.target.messageManager; callback = { - onInstallEnded: function(url, status) { - mm.sendAsyncMessage(MSG_INSTALL_CALLBACK, { + onInstallEnded: function ITP_callback(url, status) { + gParentMM.broadcastAsyncMessage(MSG_INSTALL_CALLBACK, { callbackID: payload.callbackID, url: url, status: status @@ -222,61 +179,12 @@ amManager.prototype = { aMessage.target, payload.triggeringPrincipal, payload.uris, payload.hashes, payload.names, payload.icons, callback); } - - case MSG_PROMISE_REQUEST: { - let mm = aMessage.target.messageManager; - let resolve = (value) => { - mm.sendAsyncMessage(MSG_PROMISE_RESULT, { - callbackID: payload.callbackID, - resolve: value - }); - } - let reject = (value) => { - mm.sendAsyncMessage(MSG_PROMISE_RESULT, { - callbackID: payload.callbackID, - reject: value - }); - } - - let API = AddonManager.webAPI; - if (payload.type in API) { - API[payload.type](aMessage.target, ...payload.args).then(resolve, reject); - } - else { - reject("Unknown Add-on API request."); - } - break; - } - - case MSG_INSTALL_CLEANUP: { - AddonManager.webAPI.clearInstalls(payload.ids); - break; - } - - case MSG_ADDON_EVENT_REQ: { - let target = aMessage.target.messageManager; - if (payload.enabled) { - this._addAddonListener(target); - } else { - this._removeAddonListener(target); - } - } } - return undefined; - }, - - childClosed(target) { - AddonManager.webAPI.clearInstallsFrom(target); - this._removeAddonListener(target); - }, - - sendEvent(mm, data) { - mm.sendAsyncMessage(MSG_INSTALL_EVENT, data); }, classID: Components.ID("{4399533d-08d1-458c-a87a-235f74451cfa}"), _xpcom_factory: { - createInstance: function(aOuter, aIid) { + createInstance: function AMC_createInstance(aOuter, aIid) { if (aOuter != null) throw Components.Exception("Component does not support aggregation", Cr.NS_ERROR_NO_AGGREGATION); diff --git a/toolkit/mozapps/extensions/amContentHandler.js b/toolkit/mozapps/extensions/amContentHandler.js index 8dc4dfecd..708f670b1 100644 --- a/toolkit/mozapps/extensions/amContentHandler.js +++ b/toolkit/mozapps/extensions/amContentHandler.js @@ -28,7 +28,7 @@ amContentHandler.prototype = { * @param aRequest * The nsIRequest dealing with the content */ - handleContent: function(aMimetype, aContext, aRequest) { + handleContent: function XCH_handleContent(aMimetype, aContext, aRequest) { if (aMimetype != XPI_CONTENT_TYPE) throw Cr.NS_ERROR_WONT_HANDLE_CONTENT; @@ -89,7 +89,7 @@ amContentHandler.prototype = { classID: Components.ID("{7beb3ba8-6ec3-41b4-b67c-da89b8518922}"), QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentHandler]), - log : function(aMsg) { + log : function XCH_log(aMsg) { let msg = "amContentHandler.js: " + (aMsg.join ? aMsg.join("") : aMsg); Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService). logStringMessage(msg); diff --git a/toolkit/mozapps/extensions/amInstallTrigger.js b/toolkit/mozapps/extensions/amInstallTrigger.js index 382791d32..a18fe84c4 100644 --- a/toolkit/mozapps/extensions/amInstallTrigger.js +++ b/toolkit/mozapps/extensions/amInstallTrigger.js @@ -39,19 +39,13 @@ function CallbackObject(id, callback, urls, mediator) { }; } -function RemoteMediator(window) { - window.QueryInterface(Ci.nsIInterfaceRequestor); - let utils = window.getInterface(Ci.nsIDOMWindowUtils); - this._windowID = utils.currentInnerWindowID; - - this.mm = window - .getInterface(Ci.nsIDocShell) - .QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIContentFrameMessageManager); - this.mm.addWeakMessageListener(MSG_INSTALL_CALLBACK, this); - +function RemoteMediator(windowID) { + this._windowID = windowID; this._lastCallbackID = 0; this._callbacks = new Map(); + this.mm = Cc["@mozilla.org/childprocessmessagemanager;1"] + .getService(Ci.nsISyncMessageSender); + this.mm.addWeakMessageListener(MSG_INSTALL_CALLBACK, this); } RemoteMediator.prototype = { @@ -142,13 +136,9 @@ InstallTrigger.prototype = { this._principal = window.document.nodePrincipal; this._url = window.document.documentURIObject; - try { - this._mediator = new RemoteMediator(window); - } catch (ex) { - // If we can't set up IPC (e.g., because this is a top-level window - // or something), then don't expose InstallTrigger. - return null; - } + window.QueryInterface(Components.interfaces.nsIInterfaceRequestor); + let utils = window.getInterface(Components.interfaces.nsIDOMWindowUtils); + this._mediator = new RemoteMediator(utils.currentInnerWindowID); return window.InstallTriggerImpl._create(window, this); }, @@ -175,12 +165,12 @@ InstallTrigger.prototype = { item = { URL: item }; } if (!item.URL) { - throw new this._window.Error("Missing URL property for '" + name + "'"); + throw new this._window.DOMError("Error", "Missing URL property for '" + name + "'"); } let url = this._resolveURL(item.URL); if (!this._checkLoadURIFromScript(url)) { - throw new this._window.Error("Insufficient permissions to install: " + url.spec); + throw new this._window.DOMError("SecurityError", "Insufficient permissions to install: " + url.spec); } let iconUrl = null; @@ -213,7 +203,7 @@ InstallTrigger.prototype = { return this.startSoftwareUpdate(url); }, - _resolveURL: function(url) { + _resolveURL: function (url) { return Services.io.newURI(url, null, this._url); }, @@ -225,7 +215,7 @@ InstallTrigger.prototype = { secman.DISALLOW_INHERIT_PRINCIPAL); return true; } - catch (e) { + catch(e) { return false; } }, diff --git a/toolkit/mozapps/extensions/amWebAPI.js b/toolkit/mozapps/extensions/amWebAPI.js deleted file mode 100644 index 5ad0d23f1..000000000 --- a/toolkit/mozapps/extensions/amWebAPI.js +++ /dev/null @@ -1,269 +0,0 @@ -/* 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/. */ - -"use strict"; - -const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/Task.jsm"); - -const MSG_PROMISE_REQUEST = "WebAPIPromiseRequest"; -const MSG_PROMISE_RESULT = "WebAPIPromiseResult"; -const MSG_INSTALL_EVENT = "WebAPIInstallEvent"; -const MSG_INSTALL_CLEANUP = "WebAPICleanup"; -const MSG_ADDON_EVENT_REQ = "WebAPIAddonEventRequest"; -const MSG_ADDON_EVENT = "WebAPIAddonEvent"; - -class APIBroker { - constructor(mm) { - this.mm = mm; - - this._promises = new Map(); - - // _installMap maps integer ids to DOM AddonInstall instances - this._installMap = new Map(); - - this.mm.addMessageListener(MSG_PROMISE_RESULT, this); - this.mm.addMessageListener(MSG_INSTALL_EVENT, this); - - this._eventListener = null; - } - - receiveMessage(message) { - let payload = message.data; - - switch (message.name) { - case MSG_PROMISE_RESULT: { - if (!this._promises.has(payload.callbackID)) { - return; - } - - let resolve = this._promises.get(payload.callbackID); - this._promises.delete(payload.callbackID); - resolve(payload); - break; - } - - case MSG_INSTALL_EVENT: { - let install = this._installMap.get(payload.id); - if (!install) { - let err = new Error(`Got install event for unknown install ${payload.id}`); - Cu.reportError(err); - return; - } - install._dispatch(payload); - break; - } - - case MSG_ADDON_EVENT: { - if (this._eventListener) { - this._eventListener(payload); - } - } - } - } - - sendRequest(type, ...args) { - return new Promise(resolve => { - let callbackID = APIBroker._nextID++; - - this._promises.set(callbackID, resolve); - this.mm.sendAsyncMessage(MSG_PROMISE_REQUEST, { type, callbackID, args }); - }); - } - - setAddonListener(callback) { - this._eventListener = callback; - if (callback) { - this.mm.addMessageListener(MSG_ADDON_EVENT, this); - this.mm.sendAsyncMessage(MSG_ADDON_EVENT_REQ, {enabled: true}); - } else { - this.mm.removeMessageListener(MSG_ADDON_EVENT, this); - this.mm.sendAsyncMessage(MSG_ADDON_EVENT_REQ, {enabled: false}); - } - } - - sendCleanup(ids) { - this.setAddonListener(null); - this.mm.sendAsyncMessage(MSG_INSTALL_CLEANUP, { ids }); - } -} - -APIBroker._nextID = 0; - -// Base class for building classes to back content-exposed interfaces. -class APIObject { - init(window, broker, properties) { - this.window = window; - this.broker = broker; - - // Copy any provided properties onto this object, webidl bindings - // will only expose to content what should be exposed. - for (let key of Object.keys(properties)) { - this[key] = properties[key]; - } - } - - /** - * Helper to implement an asychronous method visible to content, where - * the method is implemented by sending a message to the parent process - * and then wrapping the returned object or error in an appropriate object. - * This helper method ensures that: - * - Returned Promise objects are from the content window - * - Rejected Promises have Error objects from the content window - * - Only non-internal errors are exposed to the caller - * - * @param {string} apiRequest The command to invoke in the parent process. - * @param {array<cloneable>} apiArgs The arguments to include with the - * request to the parent process. - * @param {function} resultConvert If provided, a function called with the - * result from the parent process as an - * argument. Used to convert the result - * into something appropriate for content. - * @returns {Promise<any>} A Promise suitable for passing directly to content. - */ - _apiTask(apiRequest, apiArgs, resultConverter) { - let win = this.window; - let broker = this.broker; - return new win.Promise((resolve, reject) => { - Task.spawn(function*() { - let result = yield broker.sendRequest(apiRequest, ...apiArgs); - if ("reject" in result) { - let err = new win.Error(result.reject.message); - // We don't currently put any other properties onto Errors - // generated by mozAddonManager. If/when we do, they will - // need to get copied here. - reject(err); - return; - } - - let obj = result.resolve; - if (resultConverter) { - obj = resultConverter(obj); - } - resolve(obj); - }).catch(err => { - Cu.reportError(err); - reject(new win.Error("Unexpected internal error")); - }); - }); - } -} - -class Addon extends APIObject { - constructor(...args) { - super(); - this.init(...args); - } - - uninstall() { - return this._apiTask("addonUninstall", [this.id]); - } - - setEnabled(value) { - return this._apiTask("addonSetEnabled", [this.id, value]); - } -} - -class AddonInstall extends APIObject { - constructor(window, broker, properties) { - super(); - this.init(window, broker, properties); - - broker._installMap.set(properties.id, this); - } - - _dispatch(data) { - // The message for the event includes updated copies of all install - // properties. Use the usual "let webidl filter visible properties" trick. - for (let key of Object.keys(data)) { - this[key] = data[key]; - } - - let event = new this.window.Event(data.event); - this.__DOM_IMPL__.dispatchEvent(event); - } - - install() { - return this._apiTask("addonInstallDoInstall", [this.id]); - } - - cancel() { - return this._apiTask("addonInstallCancel", [this.id]); - } -} - -class WebAPI extends APIObject { - constructor() { - super(); - this.allInstalls = []; - this.listenerCount = 0; - } - - init(window) { - let mm = window - .QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDocShell) - .QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIContentFrameMessageManager); - let broker = new APIBroker(mm); - - super.init(window, broker, {}); - - window.addEventListener("unload", event => { - this.broker.sendCleanup(this.allInstalls); - }); - } - - getAddonByID(id) { - return this._apiTask("getAddonByID", [id], addonInfo => { - if (!addonInfo) { - return null; - } - let addon = new Addon(this.window, this.broker, addonInfo); - return this.window.Addon._create(this.window, addon); - }); - } - - createInstall(options) { - return this._apiTask("createInstall", [options], installInfo => { - if (!installInfo) { - return null; - } - let install = new AddonInstall(this.window, this.broker, installInfo); - this.allInstalls.push(installInfo.id); - return this.window.AddonInstall._create(this.window, install); - }); - } - - eventListenerWasAdded(type) { - if (this.listenerCount == 0) { - this.broker.setAddonListener(data => { - let event = new this.window.AddonEvent(data.event, data); - this.__DOM_IMPL__.dispatchEvent(event); - }); - } - this.listenerCount++; - } - - eventListenerWasRemoved(type) { - this.listenerCount--; - if (this.listenerCount == 0) { - this.broker.setAddonListener(null); - } - } - - QueryInterface(iid) { - if (iid.equals(WebAPI.classID) || iid.equals(Ci.nsISupports) - || iid.equals(Ci.nsIDOMGlobalPropertyInitializer)) { - return this; - } - return Cr.NS_ERROR_NO_INTERFACE; - } -} - -WebAPI.prototype.classID = Components.ID("{8866d8e3-4ea5-48b7-a891-13ba0ac15235}"); -this.NSGetFactory = XPCOMUtils.generateNSGetFactory([WebAPI]); diff --git a/toolkit/mozapps/extensions/amWebInstallListener.js b/toolkit/mozapps/extensions/amWebInstallListener.js index 0bcc345e8..ac6e2495d 100644 --- a/toolkit/mozapps/extensions/amWebInstallListener.js +++ b/toolkit/mozapps/extensions/amWebInstallListener.js @@ -19,7 +19,6 @@ const Cu = Components.utils; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/AddonManager.jsm"); Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/Preferences.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "PromptUtils", "resource://gre/modules/SharedPromptUtils.jsm"); @@ -70,13 +69,13 @@ function Installer(aBrowser, aUrl, aInstalls) { notifyObservers("addon-install-started", aBrowser, aUrl, aInstalls); - for (let install of aInstalls) { - install.addListener(this); + aInstalls.forEach(function(aInstall) { + aInstall.addListener(this); // Start downloading if it hasn't already begun - if (READY_STATES.indexOf(install.state) != -1) - install.install(); - } + if (READY_STATES.indexOf(aInstall.state) != -1) + aInstall.install(); + }, this); this.checkAllDownloaded(); } @@ -90,7 +89,7 @@ Installer.prototype = { /** * Checks if all downloads are now complete and if so prompts to install. */ - checkAllDownloaded: function() { + checkAllDownloaded: function Installer_checkAllDownloaded() { // Prevent re-entrancy caused by the confirmation dialog cancelling unwanted // installs. if (!this.isDownloading) @@ -117,14 +116,14 @@ Installer.prototype = { installs.push(install); if (install.linkedInstalls) { - for (let linkedInstall of install.linkedInstalls) { - linkedInstall.addListener(this); - // Corrupt or incompatible items fail to install - if (linkedInstall.state == AddonManager.STATE_DOWNLOAD_FAILED || linkedInstall.addon.appDisabled) - failed.push(linkedInstall); + install.linkedInstalls.forEach(function(aInstall) { + aInstall.addListener(this); + // App disabled items are not compatible and so fail to install + if (aInstall.addon.appDisabled) + failed.push(aInstall); else - installs.push(linkedInstall); - } + installs.push(aInstall); + }, this); } break; case AddonManager.STATE_CANCELLED: @@ -132,7 +131,7 @@ Installer.prototype = { break; default: logger.warn("Download of " + install.sourceURI.spec + " in unexpected state " + - install.state); + install.state); } } @@ -142,12 +141,12 @@ Installer.prototype = { if (failed.length > 0) { // Stop listening and cancel any installs that are failed because of // compatibility reasons. - for (let install of failed) { - if (install.state == AddonManager.STATE_DOWNLOADED) { - install.removeListener(this); - install.cancel(); + failed.forEach(function(aInstall) { + if (aInstall.state == AddonManager.STATE_DOWNLOADED) { + aInstall.removeListener(this); + aInstall.cancel(); } - } + }, this); notifyObservers("addon-install-failed", this.browser, this.url, failed); } @@ -167,11 +166,6 @@ Installer.prototype = { catch (e) {} } - if (Preferences.get("xpinstall.customConfirmationUI", false)) { - notifyObservers("addon-install-confirmation", this.browser, this.url, this.downloads); - return; - } - let args = {}; args.url = this.url; args.installs = this.downloads; @@ -191,12 +185,12 @@ Installer.prototype = { null, "chrome,modal,centerscreen", args); } catch (e) { logger.warn("Exception showing install confirmation dialog", e); - for (let install of this.downloads) { - install.removeListener(this); + this.downloads.forEach(function(aInstall) { + aInstall.removeListener(this); // Cancel the installs, as currently there is no way to make them fail // from here. - install.cancel(); - } + aInstall.cancel(); + }, this); notifyObservers("addon-install-cancelled", this.browser, this.url, this.downloads); } @@ -205,11 +199,11 @@ Installer.prototype = { /** * Checks if all installs are now complete and if so notifies observers. */ - checkAllInstalled: function() { + checkAllInstalled: function Installer_checkAllInstalled() { var failed = []; for (let install of this.downloads) { - switch (install.state) { + switch(install.state) { case AddonManager.STATE_DOWNLOADED: case AddonManager.STATE_INSTALLING: // Exit early if any add-ons haven't started installing yet or are @@ -231,32 +225,32 @@ Installer.prototype = { this.installed = null; }, - onDownloadCancelled: function(aInstall) { + onDownloadCancelled: function Installer_onDownloadCancelled(aInstall) { aInstall.removeListener(this); this.checkAllDownloaded(); }, - onDownloadFailed: function(aInstall) { + onDownloadFailed: function Installer_onDownloadFailed(aInstall) { aInstall.removeListener(this); this.checkAllDownloaded(); }, - onDownloadEnded: function(aInstall) { + onDownloadEnded: function Installer_onDownloadEnded(aInstall) { this.checkAllDownloaded(); return false; }, - onInstallCancelled: function(aInstall) { + onInstallCancelled: function Installer_onInstallCancelled(aInstall) { aInstall.removeListener(this); this.checkAllInstalled(); }, - onInstallFailed: function(aInstall) { + onInstallFailed: function Installer_onInstallFailed(aInstall) { aInstall.removeListener(this); this.checkAllInstalled(); }, - onInstallEnded: function(aInstall) { + onInstallEnded: function Installer_onInstallEnded(aInstall) { aInstall.removeListener(this); this.installed.push(aInstall); @@ -278,7 +272,7 @@ extWebInstallListener.prototype = { /** * @see amIWebInstallListener.idl */ - onWebInstallDisabled: function(aBrowser, aUri, aInstalls) { + onWebInstallDisabled: function extWebInstallListener_onWebInstallDisabled(aBrowser, aUri, aInstalls) { let info = { browser: aBrowser, originatingURI: aUri, @@ -292,13 +286,13 @@ extWebInstallListener.prototype = { /** * @see amIWebInstallListener.idl */ - onWebInstallOriginBlocked: function(aBrowser, aUri, aInstalls) { + onWebInstallOriginBlocked: function extWebInstallListener_onWebInstallOriginBlocked(aBrowser, aUri, aInstalls) { let info = { browser: aBrowser, originatingURI: aUri, installs: aInstalls, - install: function() { + install: function onWebInstallBlocked_install() { }, QueryInterface: XPCOMUtils.generateQI([Ci.amIWebInstallInfo]) @@ -311,13 +305,13 @@ extWebInstallListener.prototype = { /** * @see amIWebInstallListener.idl */ - onWebInstallBlocked: function(aBrowser, aUri, aInstalls) { + onWebInstallBlocked: function extWebInstallListener_onWebInstallBlocked(aBrowser, aUri, aInstalls) { let info = { browser: aBrowser, originatingURI: aUri, installs: aInstalls, - install: function() { + install: function onWebInstallBlocked_install() { new Installer(this.browser, this.originatingURI, this.installs); }, @@ -331,7 +325,7 @@ extWebInstallListener.prototype = { /** * @see amIWebInstallListener.idl */ - onWebInstallRequested: function(aBrowser, aUri, aInstalls) { + onWebInstallRequested: function extWebInstallListener_onWebInstallRequested(aBrowser, aUri, aInstalls) { new Installer(aBrowser, aUri, aInstalls); // We start the installs ourself diff --git a/toolkit/mozapps/extensions/content/about.js b/toolkit/mozapps/extensions/content/about.js index 4f8fb353e..49ca4acc1 100644 --- a/toolkit/mozapps/extensions/content/about.js +++ b/toolkit/mozapps/extensions/content/about.js @@ -6,21 +6,15 @@ "use strict"; -/* import-globals-from ../../../content/contentAreaUtils.js */ - -var Cu = Components.utils; -Cu.import("resource://gre/modules/AddonManager.jsm"); - function init() { var addon = window.arguments[0]; var extensionsStrings = document.getElementById("extensionsStrings"); document.documentElement.setAttribute("addontype", addon.type); - var iconURL = AddonManager.getPreferredIconURL(addon, 48, window); - if (iconURL) { + if (addon.iconURL) { var extensionIcon = document.getElementById("extensionIcon"); - extensionIcon.src = iconURL; + extensionIcon.src = addon.iconURL; } document.title = extensionsStrings.getFormattedString("aboutWindowTitle", [addon.name]); @@ -74,7 +68,7 @@ function init() { var acceptButton = document.documentElement.getButton("accept"); acceptButton.label = extensionsStrings.getString("aboutWindowCloseButton"); - + setTimeout(sizeToContent, 0); } diff --git a/toolkit/mozapps/extensions/content/blocklist.js b/toolkit/mozapps/extensions/content/blocklist.js index 6d524e6ee..6b47fd652 100644 --- a/toolkit/mozapps/extensions/content/blocklist.js +++ b/toolkit/mozapps/extensions/content/blocklist.js @@ -26,7 +26,7 @@ function init() { var richlist = document.getElementById("addonList"); var list = gArgs.list; - list.sort(function(a, b) { return String.localeCompare(a.name, b.name); }); + list.sort(function listSort(a, b) { return String.localeCompare(a.name, b.name); }); for (let listItem of list) { let item = document.createElement("richlistitem"); item.setAttribute("name", listItem.name); diff --git a/toolkit/mozapps/extensions/content/eula.js b/toolkit/mozapps/extensions/content/eula.js index 537ee7284..a05f7fe1c 100644 --- a/toolkit/mozapps/extensions/content/eula.js +++ b/toolkit/mozapps/extensions/content/eula.js @@ -6,18 +6,14 @@ "use strict"; -var Cu = Components.utils; -Cu.import("resource://gre/modules/AddonManager.jsm"); - function Startup() { var bundle = document.getElementById("extensionsStrings"); var addon = window.arguments[0].addon; document.documentElement.setAttribute("addontype", addon.type); - var iconURL = AddonManager.getPreferredIconURL(addon, 48, window); - if (iconURL) - document.getElementById("icon").src = iconURL; + if (addon.iconURL) + document.getElementById("icon").src = addon.iconURL; var label = document.createTextNode(bundle.getFormattedString("eulaHeader", [addon.name])); document.getElementById("heading").appendChild(label); diff --git a/toolkit/mozapps/extensions/content/extensions.css b/toolkit/mozapps/extensions/content/extensions.css index cb5313365..41c140565 100644 --- a/toolkit/mozapps/extensions/content/extensions.css +++ b/toolkit/mozapps/extensions/content/extensions.css @@ -39,6 +39,10 @@ xhtml|link { -moz-binding: url("chrome://mozapps/content/extensions/extensions.xml#creator-link"); } +.translators { + -moz-binding: url("chrome://mozapps/content/extensions/extensions.xml#translators-list"); +} + .meta-rating { -moz-binding: url("chrome://mozapps/content/extensions/extensions.xml#rating"); } @@ -74,8 +78,7 @@ setting[type="bool"][localized="true"] { -moz-binding: url("chrome://mozapps/content/extensions/setting.xml#setting-localized-bool"); } -setting[type="bool"]:not([learnmore]) .preferences-learnmore, -setting[type="boolint"]:not([learnmore]) .preferences-learnmore { +setting[type="bool"]:not([learnmore]) .preferences-learnmore { visibility: collapse; } @@ -131,11 +134,6 @@ setting[type="menulist"] { display: none; } -#show-disabled-unsigned-extensions .button-text { - margin-inline-start: 3px !important; - margin-inline-end: 2px !important; -} - #header-searching:not([active]) { visibility: hidden; } @@ -154,6 +152,8 @@ setting[type="menulist"] { .addon:not([notification="info"]) .info, .addon:not([pending]) .pending, .addon:not([upgrade="true"]) .update-postfix, +.addon:not([native="true"]) .nativeAddon, +.addon:not([native="false"]) .compatAddon, .addon[active="true"] .disabled-postfix, .addon[pending="install"] .update-postfix, .addon[pending="install"] .disabled-postfix, @@ -198,7 +198,7 @@ setting[type="menulist"] { display: none; } -#addons-page .view-pane:not([type="plugin"]) #plugindeprecation-notice { +#addons-page .view-pane:not([type="plugin"]) .plugin-info-container { display: none; } @@ -249,13 +249,10 @@ richlistitem:not([selected]) * { .view-pane[type="experiment"] .addon:not([pending="uninstall"]) .pending, .view-pane[type="experiment"] .disabled-postfix, .view-pane[type="experiment"] .update-postfix, -.view-pane[type="experiment"] .addon-control.enable, -.view-pane[type="experiment"] .addon-control.disable, +.view-pane[type="experiment"] .version, #detail-view[type="experiment"] .alert-container, #detail-view[type="experiment"] #detail-version, -#detail-view[type="experiment"] #detail-creator, -#detail-view[type="experiment"] #detail-enable-btn, -#detail-view[type="experiment"] #detail-disable-btn { +#detail-view[type="experiment"] #detail-creator { display: none; } @@ -268,3 +265,24 @@ richlistitem:not([selected]) * { .addon[type="experiment"][status="installing"] .experiment-state { display: none; } + +/* Indicator style for extension target application */ +.addon[native] .nativeIndicator { + margin-left: 5pt; + padding-bottom: 1pt; +} +.addon[native][active="false"] .nativeIndicator { + opacity: 0.4; +} +.addon[native] .nativeAddon { + color: #3366FF; +} +.addon[native] .compatAddon { + color: #FF6600; +} + +/* Translators for Language Pack details */ +.translators > label { + -moz-margin-start: 0px; + -moz-margin-end: 0px; +} diff --git a/toolkit/mozapps/extensions/content/extensions.js b/toolkit/mozapps/extensions/content/extensions.js index 56158d9c6..8d9c132e6 100644 --- a/toolkit/mozapps/extensions/content/extensions.js +++ b/toolkit/mozapps/extensions/content/extensions.js @@ -4,13 +4,10 @@ "use strict"; -/* import-globals-from ../../../content/contentAreaUtils.js */ -/* globals XMLStylesheetProcessingInstruction*/ - -var Cc = Components.classes; -var Ci = Components.interfaces; -var Cu = Components.utils; -var Cr = Components.results; +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cu = Components.utils; +const Cr = Components.results; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Services.jsm"); @@ -18,19 +15,13 @@ Cu.import("resource://gre/modules/DownloadUtils.jsm"); Cu.import("resource://gre/modules/AddonManager.jsm"); Cu.import("resource://gre/modules/addons/AddonRepository.jsm"); -const CONSTANTS = {}; -Cu.import("resource://gre/modules/addons/AddonConstants.jsm", CONSTANTS); -const SIGNING_REQUIRED = CONSTANTS.REQUIRE_SIGNING ? - true : - Services.prefs.getBoolPref("xpinstall.signatures.required"); - XPCOMUtils.defineLazyModuleGetter(this, "PluralForm", "resource://gre/modules/PluralForm.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "Preferences", - "resource://gre/modules/Preferences.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "Experiments", - "resource:///modules/experiments/Experiments.jsm"); +XPCOMUtils.defineLazyGetter(this, "BrowserToolboxProcess", function () { + return Cu.import("resource://devtools/client/framework/ToolboxProcess.jsm", {}). + BrowserToolboxProcess; +}); const PREF_DISCOVERURL = "extensions.webservice.discoverURL"; const PREF_DISCOVER_ENABLED = "extensions.getAddons.showPane"; @@ -40,6 +31,8 @@ const PREF_GETADDONS_CACHE_ENABLED = "extensions.getAddons.cache.enabled"; const PREF_GETADDONS_CACHE_ID_ENABLED = "extensions.%ID%.getAddons.cache.enabled"; const PREF_UI_TYPE_HIDDEN = "extensions.ui.%TYPE%.hidden"; const PREF_UI_LASTCATEGORY = "extensions.ui.lastCategory"; +const PREF_ADDON_DEBUGGING_ENABLED = "devtools.chrome.enabled"; +const PREF_REMOTE_DEBUGGING_ENABLED = "devtools.debugger.remote-enabled"; const LOADING_MSG_DELAY = 100; @@ -63,103 +56,28 @@ XPCOMUtils.defineLazyServiceGetter(gStrings, "bundleSvc", "@mozilla.org/intl/stringbundle;1", "nsIStringBundleService"); -XPCOMUtils.defineLazyGetter(gStrings, "brand", function() { +XPCOMUtils.defineLazyGetter(gStrings, "brand", function brandLazyGetter() { return this.bundleSvc.createBundle("chrome://branding/locale/brand.properties"); }); -XPCOMUtils.defineLazyGetter(gStrings, "ext", function() { +XPCOMUtils.defineLazyGetter(gStrings, "ext", function extLazyGetter() { return this.bundleSvc.createBundle("chrome://mozapps/locale/extensions/extensions.properties"); }); -XPCOMUtils.defineLazyGetter(gStrings, "dl", function() { +XPCOMUtils.defineLazyGetter(gStrings, "dl", function dlLazyGetter() { return this.bundleSvc.createBundle("chrome://mozapps/locale/downloads/downloads.properties"); }); -XPCOMUtils.defineLazyGetter(gStrings, "brandShortName", function() { +XPCOMUtils.defineLazyGetter(gStrings, "brandShortName", function brandShortNameLazyGetter() { return this.brand.GetStringFromName("brandShortName"); }); -XPCOMUtils.defineLazyGetter(gStrings, "appVersion", function() { +XPCOMUtils.defineLazyGetter(gStrings, "appVersion", function appVersionLazyGetter() { return Services.appinfo.version; }); document.addEventListener("load", initialize, true); window.addEventListener("unload", shutdown, false); -class MessageDispatcher { - constructor(target) { - this.listeners = new Map(); - this.target = target; - } - - addMessageListener(name, handler) { - if (!this.listeners.has(name)) { - this.listeners.set(name, new Set()); - } - - this.listeners.get(name).add(handler); - } - - removeMessageListener(name, handler) { - if (this.listeners.has(name)) { - this.listeners.get(name).delete(handler); - } - } - - sendAsyncMessage(name, data) { - for (let handler of this.listeners.get(name) || new Set()) { - Promise.resolve().then(() => { - handler.receiveMessage({ - name, - data, - target: this.target, - }); - }); - } - } -} - -/** - * A mock FrameMessageManager global to allow frame scripts to run in - * non-top-level, non-remote <browser>s as if they were top-level or - * remote. - * - * @param {Element} browser - * A XUL <browser> element. - */ -class FakeFrameMessageManager { - constructor(browser) { - let dispatcher = new MessageDispatcher(browser); - let frameDispatcher = new MessageDispatcher(null); - - this.sendAsyncMessage = frameDispatcher.sendAsyncMessage.bind(frameDispatcher); - this.addMessageListener = dispatcher.addMessageListener.bind(dispatcher); - this.removeMessageListener = dispatcher.removeMessageListener.bind(dispatcher); - - this.frame = { - get content() { - return browser.contentWindow; - }, - - get docShell() { - return browser.docShell; - }, - - addEventListener: browser.addEventListener.bind(browser), - removeEventListener: browser.removeEventListener.bind(browser), - - sendAsyncMessage: dispatcher.sendAsyncMessage.bind(dispatcher), - addMessageListener: frameDispatcher.addMessageListener.bind(frameDispatcher), - removeMessageListener: frameDispatcher.removeMessageListener.bind(frameDispatcher), - } - } - - loadFrameScript(url) { - Services.scriptloader.loadSubScript(url, Object.create(this.frame)); - } -} - var gPendingInitializations = 1; -Object.defineProperty(this, "gIsInitializing", { - get: () => gPendingInitializations > 0 -}); +this.__defineGetter__("gIsInitializing", function gIsInitializingGetter() gPendingInitializations > 0); function initialize(event) { // XXXbz this listener gets _all_ load events for all nodes in the @@ -236,6 +154,9 @@ function initialize(event) { } gViewController.loadInitialView(view); + + Services.prefs.addObserver(PREF_ADDON_DEBUGGING_ENABLED, debuggingPrefChanged, false); + Services.prefs.addObserver(PREF_REMOTE_DEBUGGING_ENABLED, debuggingPrefChanged, false); } function notifyInitialized() { @@ -256,6 +177,8 @@ function shutdown() { gEventManager.shutdown(); gViewController.shutdown(); Services.obs.removeObserver(sendEMPong, "EM-ping"); + Services.prefs.removeObserver(PREF_ADDON_DEBUGGING_ENABLED, debuggingPrefChanged); + Services.prefs.removeObserver(PREF_REMOTE_DEBUGGING_ENABLED, debuggingPrefChanged); } function sendEMPong(aSubject, aTopic, aData) { @@ -274,12 +197,6 @@ function loadView(aViewId) { } } -function isCorrectlySigned(aAddon) { - // Add-ons without an "isCorrectlySigned" property are correctly signed as - // they aren't the correct type for signing. - return aAddon.isCorrectlySigned !== false; -} - function isDiscoverEnabled() { if (Services.prefs.getPrefType(PREF_DISCOVERURL) == Services.prefs.PREF_INVALID) return false; @@ -297,23 +214,6 @@ function isDiscoverEnabled() { return true; } -function getExperimentEndDate(aAddon) { - if (!("@mozilla.org/browser/experiments-service;1" in Cc)) { - return 0; - } - - if (!aAddon.isActive) { - return aAddon.endDate; - } - - let experiment = Experiments.instance().getActiveExperiment(); - if (!experiment) { - return 0; - } - - return experiment.endDate; -} - /** * Obtain the main DOMWindow for the current context. */ @@ -345,8 +245,9 @@ function getMainWindowWithPreferencesPane() { let mainWindow = getMainWindow(); if (mainWindow && "openAdvancedPreferences" in mainWindow) { return mainWindow; + } else { + return null; } - return null; } /** @@ -372,27 +273,27 @@ var HTML5History = { .canGoForward; }, - back: function() { + back: function HTML5History_back() { window.history.back(); gViewController.updateCommand("cmd_back"); gViewController.updateCommand("cmd_forward"); }, - forward: function() { + forward: function HTML5History_forward() { window.history.forward(); gViewController.updateCommand("cmd_back"); gViewController.updateCommand("cmd_forward"); }, - pushState: function(aState) { + pushState: function HTML5History_pushState(aState) { window.history.pushState(aState, document.title); }, - replaceState: function(aState) { + replaceState: function HTML5History_replaceState(aState) { window.history.replaceState(aState, document.title); }, - popState: function() { + popState: function HTML5History_popState() { function onStatePopped(aEvent) { window.removeEventListener("popstate", onStatePopped, true); // TODO To ensure we can't go forward again we put an additional entry @@ -426,7 +327,7 @@ var FakeHistory = { return (this.pos + 1) < this.states.length; }, - back: function() { + back: function FakeHistory_back() { if (this.pos == 0) throw Components.Exception("Cannot go back from this point"); @@ -436,7 +337,7 @@ var FakeHistory = { gViewController.updateCommand("cmd_forward"); }, - forward: function() { + forward: function FakeHistory_forward() { if ((this.pos + 1) >= this.states.length) throw Components.Exception("Cannot go forward from this point"); @@ -446,17 +347,17 @@ var FakeHistory = { gViewController.updateCommand("cmd_forward"); }, - pushState: function(aState) { + pushState: function FakeHistory_pushState(aState) { this.pos++; this.states.splice(this.pos, this.states.length); this.states.push(aState); }, - replaceState: function(aState) { + replaceState: function FakeHistory_replaceState(aState) { this.states[this.pos] = aState; }, - popState: function() { + popState: function FakeHistory_popState() { if (this.pos == 0) throw Components.Exception("Cannot popState from this view"); @@ -484,7 +385,8 @@ var gEventManager = { _listeners: {}, _installListeners: [], - initialize: function() { + initialize: function gEM_initialize() { + var self = this; const ADDON_EVENTS = ["onEnabling", "onEnabled", "onDisabling", "onDisabled", "onUninstalling", "onUninstalled", "onInstalled", "onOperationCancelled", @@ -493,7 +395,9 @@ var gEventManager = { "onPropertyChanged"]; for (let evt of ADDON_EVENTS) { let event = evt; - this[event] = (...aArgs) => this.delegateAddonEvent(event, aArgs); + self[event] = function initialize_delegateAddonEvent(...aArgs) { + self.delegateAddonEvent(event, aArgs); + }; } const INSTALL_EVENTS = ["onNewInstall", "onDownloadStarted", @@ -504,7 +408,9 @@ var gEventManager = { "onExternalInstall"]; for (let evt of INSTALL_EVENTS) { let event = evt; - this[event] = (...aArgs) => this.delegateInstallEvent(event, aArgs); + self[event] = function initialize_delegateInstallEvent(...aArgs) { + self.delegateInstallEvent(event, aArgs); + }; } AddonManager.addManagerListener(this); @@ -515,7 +421,7 @@ var gEventManager = { this.refreshAutoUpdateDefault(); var contextMenu = document.getElementById("addonitem-popup"); - contextMenu.addEventListener("popupshowing", function() { + contextMenu.addEventListener("popupshowing", function contextMenu_onPopupshowing() { var addon = gViewController.currentViewObj.getSelectedAddon(); contextMenu.setAttribute("addontype", addon.type); @@ -535,39 +441,15 @@ var gEventManager = { menuSep.hidden = (countMenuItemsBeforeSep == 0); }, false); - - let addonTooltip = document.getElementById("addonitem-tooltip"); - addonTooltip.addEventListener("popupshowing", function() { - let addonItem = addonTooltip.triggerNode; - // The way the test triggers the tooltip the richlistitem is the - // tooltipNode but in normal use it is the anonymous node. This allows - // any case - if (addonItem.localName != "richlistitem") - addonItem = document.getBindingParent(addonItem); - - let tiptext = addonItem.getAttribute("name"); - - if (addonItem.mAddon) { - if (shouldShowVersionNumber(addonItem.mAddon)) { - tiptext += " " + (addonItem.hasAttribute("upgrade") ? addonItem.mManualUpdate.version - : addonItem.mAddon.version); - } - } - else if (shouldShowVersionNumber(addonItem.mInstall)) { - tiptext += " " + addonItem.mInstall.version; - } - - addonTooltip.label = tiptext; - }, false); }, - shutdown: function() { + shutdown: function gEM_shutdown() { AddonManager.removeManagerListener(this); AddonManager.removeInstallListener(this); AddonManager.removeAddonListener(this); }, - registerAddonListener: function(aListener, aAddonId) { + registerAddonListener: function gEM_registerAddonListener(aListener, aAddonId) { if (!(aAddonId in this._listeners)) this._listeners[aAddonId] = []; else if (this._listeners[aAddonId].indexOf(aListener) != -1) @@ -575,7 +457,7 @@ var gEventManager = { this._listeners[aAddonId].push(aListener); }, - unregisterAddonListener: function(aListener, aAddonId) { + unregisterAddonListener: function gEM_unregisterAddonListener(aListener, aAddonId) { if (!(aAddonId in this._listeners)) return; var index = this._listeners[aAddonId].indexOf(aListener); @@ -584,20 +466,20 @@ var gEventManager = { this._listeners[aAddonId].splice(index, 1); }, - registerInstallListener: function(aListener) { + registerInstallListener: function gEM_registerInstallListener(aListener) { if (this._installListeners.indexOf(aListener) != -1) return; this._installListeners.push(aListener); }, - unregisterInstallListener: function(aListener) { + unregisterInstallListener: function gEM_unregisterInstallListener(aListener) { var i = this._installListeners.indexOf(aListener); if (i == -1) return; this._installListeners.splice(i, 1); }, - delegateAddonEvent: function(aEvent, aParams) { + delegateAddonEvent: function gEM_delegateAddonEvent(aEvent, aParams) { var addon = aParams.shift(); if (!(addon.id in this._listeners)) return; @@ -608,14 +490,14 @@ var gEventManager = { continue; try { listener[aEvent].apply(listener, aParams); - } catch (e) { + } catch(e) { // this shouldn't be fatal Cu.reportError(e); } } }, - delegateInstallEvent: function(aEvent, aParams) { + delegateInstallEvent: function gEM_delegateInstallEvent(aEvent, aParams) { var existingAddon = aEvent == "onExternalInstall" ? aParams[1] : aParams[0].existingAddon; // If the install is an update then send the event to all listeners // registered for the existing add-on @@ -627,14 +509,14 @@ var gEventManager = { continue; try { listener[aEvent].apply(listener, aParams); - } catch (e) { + } catch(e) { // this shouldn't be fatal Cu.reportError(e); } } }, - refreshGlobalWarning: function() { + refreshGlobalWarning: function gEM_refreshGlobalWarning() { var page = document.getElementById("addons-page"); if (Services.appinfo.inSafeMode) { @@ -656,7 +538,7 @@ var gEventManager = { page.removeAttribute("warning"); }, - refreshAutoUpdateDefault: function() { + refreshAutoUpdateDefault: function gEM_refreshAutoUpdateDefault() { var updateEnabled = AddonManager.updateEnabled; var autoUpdateDefault = AddonManager.autoUpdateDefault; @@ -669,15 +551,15 @@ var gEventManager = { document.getElementById("utils-resetAddonUpdatesToManual").hidden = autoUpdateDefault; }, - onCompatibilityModeChanged: function() { + onCompatibilityModeChanged: function gEM_onCompatibilityModeChanged() { this.refreshGlobalWarning(); }, - onCheckUpdateSecurityChanged: function() { + onCheckUpdateSecurityChanged: function gEM_onCheckUpdateSecurityChanged() { this.refreshGlobalWarning(); }, - onUpdateModeChanged: function() { + onUpdateModeChanged: function gEM_onUpdateModeChanged() { this.refreshAutoUpdateDefault(); } }; @@ -693,10 +575,8 @@ var gViewController = { initialViewSelected: false, lastHistoryIndex: -1, - initialize: function() { + initialize: function gVC_initialize() { this.viewPort = document.getElementById("view-port"); - this.headeredViews = document.getElementById("headered-views"); - this.headeredViewsDeck = document.getElementById("headered-views-content"); this.viewObjects["search"] = gSearchView; this.viewObjects["discover"] = gDiscoverView; @@ -704,30 +584,28 @@ var gViewController = { this.viewObjects["detail"] = gDetailView; this.viewObjects["updates"] = gUpdatesView; - for (let type in this.viewObjects) { - let view = this.viewObjects[type]; + for each (let view in this.viewObjects) view.initialize(); - } window.controllers.appendController(this); - window.addEventListener("popstate", function(e) { + window.addEventListener("popstate", + function window_onStatePopped(e) { gViewController.updateState(e.state); }, false); }, - shutdown: function() { + shutdown: function gVC_shutdown() { if (this.currentViewObj) this.currentViewObj.hide(); this.currentViewRequest = 0; - for (let type in this.viewObjects) { - let view = this.viewObjects[type]; + for each(let view in this.viewObjects) { if ("shutdown" in view) { try { view.shutdown(); - } catch (e) { + } catch(e) { // this shouldn't be fatal Cu.reportError(e); } @@ -737,7 +615,7 @@ var gViewController = { window.controllers.removeController(this); }, - updateState: function(state) { + updateState: function gVC_updateState(state) { try { this.loadViewInternal(state.view, state.previousView, state); this.lastHistoryIndex = gHistory.index; @@ -749,17 +627,18 @@ var gViewController = { gHistory.back(); else gViewController.replaceView(gViewDefault); - } else if (gHistory.canGoForward) { - gHistory.forward(); } else { - gViewController.replaceView(gViewDefault); + if (gHistory.canGoForward) + gHistory.forward(); + else + gViewController.replaceView(gViewDefault); } } }, - parseViewId: function(aViewId) { + parseViewId: function gVC_parseViewId(aViewId) { var matchRegex = /^addons:\/\/([^\/]+)\/(.*)$/; - var [, viewType, viewParam] = aViewId.match(matchRegex) || []; + var [,viewType, viewParam] = aViewId.match(matchRegex) || []; return {type: viewType, param: decodeURIComponent(viewParam)}; }, @@ -767,7 +646,7 @@ var gViewController = { return !this.currentViewObj || this.currentViewObj.node.hasAttribute("loading"); }, - loadView: function(aViewId) { + loadView: function gVC_loadView(aViewId) { var isRefresh = false; if (aViewId == this.currentViewId) { if (this.isLoading) @@ -792,7 +671,7 @@ var gViewController = { // Replaces the existing view with a new one, rewriting the current history // entry to match. - replaceView: function(aViewId) { + replaceView: function gVC_replaceView(aViewId) { if (aViewId == this.currentViewId) return; @@ -804,7 +683,7 @@ var gViewController = { this.loadViewInternal(aViewId, null, state); }, - loadInitialView: function(aViewId) { + loadInitialView: function gVC_loadInitialView(aViewId) { var state = { view: aViewId, previousView: null @@ -816,24 +695,7 @@ var gViewController = { notifyInitialized(); }, - get displayedView() { - if (this.viewPort.selectedPanel == this.headeredViews) { - return this.headeredViewsDeck.selectedPanel; - } - return this.viewPort.selectedPanel; - }, - - set displayedView(view) { - let node = view.node; - if (node.parentNode == this.headeredViewsDeck) { - this.headeredViewsDeck.selectedPanel = node; - this.viewPort.selectedPanel = this.headeredViews; - } else { - this.viewPort.selectedPanel = node; - } - }, - - loadViewInternal: function(aViewId, aPreviousView, aState) { + loadViewInternal: function gVC_loadViewInternal(aViewId, aPreviousView, aState) { var view = this.parseViewId(aViewId); if (!view.type || !(view.type in this.viewObjects)) @@ -848,7 +710,7 @@ var gViewController = { let canHide = this.currentViewObj.hide(); if (canHide === false) return; - this.displayedView.removeAttribute("loading"); + this.viewPort.selectedPanel.removeAttribute("loading"); } catch (e) { // this shouldn't be fatal Cu.reportError(e); @@ -860,8 +722,8 @@ var gViewController = { this.currentViewId = aViewId; this.currentViewObj = viewObj; - this.displayedView = this.currentViewObj; - this.currentViewObj.node.setAttribute("loading", "true"); + this.viewPort.selectedPanel = this.currentViewObj.node; + this.viewPort.selectedPanel.setAttribute("loading", "true"); this.currentViewObj.node.focus(); if (aViewId == aPreviousView) @@ -871,13 +733,13 @@ var gViewController = { }, // Moves back in the document history and removes the current history entry - popState: function(aCallback) { + popState: function gVC_popState(aCallback) { this.viewChangeCallback = aCallback; gHistory.popState(); }, - notifyViewChanged: function() { - this.displayedView.removeAttribute("loading"); + notifyViewChanged: function gVC_notifyViewChanged() { + this.viewPort.selectedPanel.removeAttribute("loading"); if (this.viewChangeCallback) { this.viewChangeCallback(); @@ -891,35 +753,33 @@ var gViewController = { commands: { cmd_back: { - isEnabled: function() { + isEnabled: function cmd_back_isEnabled() { return gHistory.canGoBack; }, - doCommand: function() { + doCommand: function cmd_back_doCommand() { gHistory.back(); } }, cmd_forward: { - isEnabled: function() { + isEnabled: function cmd_forward_isEnabled() { return gHistory.canGoForward; }, - doCommand: function() { + doCommand: function cmd_forward_doCommand() { gHistory.forward(); } }, cmd_focusSearch: { isEnabled: () => true, - doCommand: function() { + doCommand: function cmd_focusSearch_doCommand() { gHeader.focusSearchBox(); } }, cmd_restartApp: { - isEnabled: function() { - return true; - }, - doCommand: function() { + isEnabled: function cmd_restartApp_isEnabled() true, + doCommand: function cmd_restartApp_doCommand() { let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"]. createInstance(Ci.nsISupportsPRBool); Services.obs.notifyObservers(cancelQuit, "quit-application-requested", @@ -934,28 +794,31 @@ var gViewController = { }, cmd_enableCheckCompatibility: { - isEnabled: function() { - return true; - }, - doCommand: function() { + isEnabled: function cmd_enableCheckCompatibility_isEnabled() true, + doCommand: function cmd_enableCheckCompatibility_doCommand() { AddonManager.checkCompatibility = true; } }, cmd_enableUpdateSecurity: { - isEnabled: function() { - return true; - }, - doCommand: function() { + isEnabled: function cmd_enableUpdateSecurity_isEnabled() true, + doCommand: function cmd_enableUpdateSecurity_doCommand() { AddonManager.checkUpdateSecurity = true; } }, +/* Plugincheck service is currently N/A for Pale Moon + cmd_pluginCheck: { + isEnabled: function cmd_pluginCheck_isEnabled() true, + doCommand: function cmd_pluginCheck_doCommand() { + openURL(Services.urlFormatter.formatURLPref("plugins.update.url")); + } + }, +*/ + cmd_toggleAutoUpdateDefault: { - isEnabled: function() { - return true; - }, - doCommand: function() { + isEnabled: function cmd_toggleAutoUpdateDefault_isEnabled() true, + doCommand: function cmd_toggleAutoUpdateDefault_doCommand() { if (!AddonManager.updateEnabled || !AddonManager.autoUpdateDefault) { // One or both of the prefs is false, i.e. the checkbox is not checked. // Now toggle both to true. If the user wants us to auto-update @@ -971,11 +834,9 @@ var gViewController = { }, cmd_resetAddonAutoUpdate: { - isEnabled: function() { - return true; - }, - doCommand: function() { - AddonManager.getAllAddons(function(aAddonList) { + isEnabled: function cmd_resetAddonAutoUpdate_isEnabled() true, + doCommand: function cmd_resetAddonAutoUpdate_doCommand() { + AddonManager.getAllAddons(function cmd_resetAddonAutoUpdate_getAllAddons(aAddonList) { for (let addon of aAddonList) { if ("applyBackgroundUpdates" in addon) addon.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DEFAULT; @@ -985,37 +846,33 @@ var gViewController = { }, cmd_goToDiscoverPane: { - isEnabled: function() { + isEnabled: function cmd_goToDiscoverPane_isEnabled() { return gDiscoverView.enabled; }, - doCommand: function() { + doCommand: function cmd_goToDiscoverPane_doCommand() { gViewController.loadView("addons://discover/"); } }, cmd_goToRecentUpdates: { - isEnabled: function() { - return true; - }, - doCommand: function() { + isEnabled: function cmd_goToRecentUpdates_isEnabled() true, + doCommand: function cmd_goToRecentUpdates_doCommand() { gViewController.loadView("addons://updates/recent"); } }, cmd_goToAvailableUpdates: { - isEnabled: function() { - return true; - }, - doCommand: function() { + isEnabled: function cmd_goToAvailableUpdates_isEnabled() true, + doCommand: function cmd_goToAvailableUpdates_doCommand() { gViewController.loadView("addons://updates/available"); } }, cmd_showItemDetails: { - isEnabled: function(aAddon) { + isEnabled: function cmd_showItemDetails_isEnabled(aAddon) { return !!aAddon && (gViewController.currentViewObj != gDetailView); }, - doCommand: function(aAddon, aScrollToPreferences) { + doCommand: function cmd_showItemDetails_doCommand(aAddon, aScrollToPreferences) { gViewController.loadView("addons://detail/" + encodeURIComponent(aAddon.id) + (aScrollToPreferences ? "/preferences" : "")); @@ -1024,10 +881,8 @@ var gViewController = { cmd_findAllUpdates: { inProgress: false, - isEnabled: function() { - return !this.inProgress; - }, - doCommand: function() { + isEnabled: function cmd_findAllUpdates_isEnabled() !this.inProgress, + doCommand: function cmd_findAllUpdates_doCommand() { this.inProgress = true; gViewController.updateCommand("cmd_findAllUpdates"); document.getElementById("updates-noneFound").hidden = true; @@ -1038,12 +893,13 @@ var gViewController = { var numUpdated = 0; var numManualUpdates = 0; var restartNeeded = false; + var self = this; - let updateStatus = () => { + function updateStatus() { if (pendingChecks > 0) return; - this.inProgress = false; + self.inProgress = false; gViewController.updateCommand("cmd_findAllUpdates"); document.getElementById("updates-progress").hidden = true; gUpdatesView.maybeRefresh(); @@ -1067,15 +923,15 @@ var gViewController = { } var updateInstallListener = { - onDownloadFailed: function() { + onDownloadFailed: function cmd_findAllUpdates_downloadFailed() { pendingChecks--; updateStatus(); }, - onInstallFailed: function() { + onInstallFailed: function cmd_findAllUpdates_installFailed() { pendingChecks--; updateStatus(); }, - onInstallEnded: function(aInstall, aAddon) { + onInstallEnded: function cmd_findAllUpdates_installEnded(aInstall, aAddon) { pendingChecks--; numUpdated++; if (isPending(aInstall.existingAddon, "upgrade")) @@ -1085,7 +941,7 @@ var gViewController = { }; var updateCheckListener = { - onUpdateAvailable: function(aAddon, aInstall) { + onUpdateAvailable: function cmd_findAllUpdates_updateAvailable(aAddon, aInstall) { gEventManager.delegateAddonEvent("onUpdateAvailable", [aAddon, aInstall]); if (AddonManager.shouldAutoUpdate(aAddon)) { @@ -1097,17 +953,17 @@ var gViewController = { updateStatus(); } }, - onNoUpdateAvailable: function(aAddon) { + onNoUpdateAvailable: function cmd_findAllUpdates_noUpdateAvailable(aAddon) { pendingChecks--; updateStatus(); }, - onUpdateFinished: function(aAddon, aError) { + onUpdateFinished: function cmd_findAllUpdates_updateFinished(aAddon, aError) { gEventManager.delegateAddonEvent("onUpdateFinished", [aAddon, aError]); } }; - AddonManager.getAddonsByTypes(null, function(aAddonList) { + AddonManager.getAddonsByTypes(null, function cmd_findAllUpdates_getAddonsByTypes(aAddonList) { for (let addon of aAddonList) { if (addon.permissions & AddonManager.PERM_CAN_UPGRADE) { pendingChecks++; @@ -1123,20 +979,20 @@ var gViewController = { }, cmd_findItemUpdates: { - isEnabled: function(aAddon) { + isEnabled: function cmd_findItemUpdates_isEnabled(aAddon) { if (!aAddon) return false; return hasPermission(aAddon, "upgrade"); }, - doCommand: function(aAddon) { + doCommand: function cmd_findItemUpdates_doCommand(aAddon) { var listener = { - onUpdateAvailable: function(aAddon, aInstall) { + onUpdateAvailable: function cmd_findItemUpdates_updateAvailable(aAddon, aInstall) { gEventManager.delegateAddonEvent("onUpdateAvailable", [aAddon, aInstall]); if (AddonManager.shouldAutoUpdate(aAddon)) aInstall.install(); }, - onNoUpdateAvailable: function(aAddon) { + onNoUpdateAvailable: function cmd_findItemUpdates_noUpdateAvailable(aAddon) { gEventManager.delegateAddonEvent("onNoUpdateAvailable", [aAddon]); } @@ -1146,24 +1002,37 @@ var gViewController = { } }, + cmd_debugItem: { + doCommand: function cmd_debugItem_doCommand(aAddon) { + BrowserToolboxProcess.init({ addonID: aAddon.id }); + }, + + isEnabled: function cmd_debugItem_isEnabled(aAddon) { + let debuggerEnabled = Services.prefs. + getBoolPref(PREF_ADDON_DEBUGGING_ENABLED); + let remoteEnabled = Services.prefs. + getBoolPref(PREF_REMOTE_DEBUGGING_ENABLED); + return aAddon && aAddon.isDebuggable && debuggerEnabled && remoteEnabled; + } + }, + cmd_showItemPreferences: { - isEnabled: function(aAddon) { + isEnabled: function cmd_showItemPreferences_isEnabled(aAddon) { if (!aAddon || (!aAddon.isActive && !aAddon.isGMPlugin) || !aAddon.optionsURL) { return false; } if (gViewController.currentViewObj == gDetailView && - (aAddon.optionsType == AddonManager.OPTIONS_TYPE_INLINE || - aAddon.optionsType == AddonManager.OPTIONS_TYPE_INLINE_BROWSER)) { + aAddon.optionsType == AddonManager.OPTIONS_TYPE_INLINE) { return false; } if (aAddon.optionsType == AddonManager.OPTIONS_TYPE_INLINE_INFO) return false; return true; }, - doCommand: function(aAddon) { - if (hasInlineOptions(aAddon)) { + doCommand: function cmd_showItemPreferences_doCommand(aAddon) { + if (aAddon.optionsType == AddonManager.OPTIONS_TYPE_INLINE) { gViewController.commands.cmd_showItemDetails.doCommand(aAddon, true); return; } @@ -1195,11 +1064,11 @@ var gViewController = { }, cmd_showItemAbout: { - isEnabled: function(aAddon) { + isEnabled: function cmd_showItemAbout_isEnabled(aAddon) { // XXXunf This may be applicable to install items too. See bug 561260 return !!aAddon; }, - doCommand: function(aAddon) { + doCommand: function cmd_showItemAbout_doCommand(aAddon) { var aboutURL = aAddon.aboutURL; if (aboutURL) openDialog(aboutURL, "", "chrome,centerscreen,modal", aAddon); @@ -1210,17 +1079,17 @@ var gViewController = { }, cmd_enableItem: { - isEnabled: function(aAddon) { + isEnabled: function cmd_enableItem_isEnabled(aAddon) { if (!aAddon) return false; let addonType = AddonManager.addonTypes[aAddon.type]; return (!(addonType.flags & AddonManager.TYPE_SUPPORTS_ASK_TO_ACTIVATE) && hasPermission(aAddon, "enable")); }, - doCommand: function(aAddon) { + doCommand: function cmd_enableItem_doCommand(aAddon) { aAddon.userDisabled = false; }, - getTooltip: function(aAddon) { + getTooltip: function cmd_enableItem_getTooltip(aAddon) { if (!aAddon) return ""; if (aAddon.operationsRequiringRestart & AddonManager.OP_NEEDS_RESTART_ENABLE) @@ -1230,17 +1099,17 @@ var gViewController = { }, cmd_disableItem: { - isEnabled: function(aAddon) { + isEnabled: function cmd_disableItem_isEnabled(aAddon) { if (!aAddon) return false; let addonType = AddonManager.addonTypes[aAddon.type]; return (!(addonType.flags & AddonManager.TYPE_SUPPORTS_ASK_TO_ACTIVATE) && hasPermission(aAddon, "disable")); }, - doCommand: function(aAddon) { + doCommand: function cmd_disableItem_doCommand(aAddon) { aAddon.userDisabled = true; }, - getTooltip: function(aAddon) { + getTooltip: function cmd_disableItem_getTooltip(aAddon) { if (!aAddon) return ""; if (aAddon.operationsRequiringRestart & AddonManager.OP_NEEDS_RESTART_DISABLE) @@ -1250,12 +1119,12 @@ var gViewController = { }, cmd_installItem: { - isEnabled: function(aAddon) { + isEnabled: function cmd_installItem_isEnabled(aAddon) { if (!aAddon) return false; return aAddon.install && aAddon.install.state == AddonManager.STATE_AVAILABLE; }, - doCommand: function(aAddon) { + doCommand: function cmd_installItem_doCommand(aAddon) { function doInstall() { gViewController.currentViewObj.getListItemForID(aAddon.id)._installStatus.installRemote(); } @@ -1268,33 +1137,33 @@ var gViewController = { }, cmd_purchaseItem: { - isEnabled: function(aAddon) { + isEnabled: function cmd_purchaseItem_isEnabled(aAddon) { if (!aAddon) return false; return !!aAddon.purchaseURL; }, - doCommand: function(aAddon) { + doCommand: function cmd_purchaseItem_doCommand(aAddon) { openURL(aAddon.purchaseURL); } }, cmd_uninstallItem: { - isEnabled: function(aAddon) { + isEnabled: function cmd_uninstallItem_isEnabled(aAddon) { if (!aAddon) return false; return hasPermission(aAddon, "uninstall"); }, - doCommand: function(aAddon) { + doCommand: function cmd_uninstallItem_doCommand(aAddon) { if (gViewController.currentViewObj != gDetailView) { aAddon.uninstall(); return; } - gViewController.popState(function() { + gViewController.popState(function cmd_uninstallItem_popState() { gViewController.currentViewObj.getListItemForID(aAddon.id).uninstall(); }); }, - getTooltip: function(aAddon) { + getTooltip: function cmd_uninstallItem_getTooltip(aAddon) { if (!aAddon) return ""; if (aAddon.operationsRequiringRestart & AddonManager.OP_NEEDS_RESTART_UNINSTALL) @@ -1304,21 +1173,19 @@ var gViewController = { }, cmd_cancelUninstallItem: { - isEnabled: function(aAddon) { + isEnabled: function cmd_cancelUninstallItem_isEnabled(aAddon) { if (!aAddon) return false; return isPending(aAddon, "uninstall"); }, - doCommand: function(aAddon) { + doCommand: function cmd_cancelUninstallItem_doCommand(aAddon) { aAddon.cancelUninstall(); } }, cmd_installFromFile: { - isEnabled: function() { - return true; - }, - doCommand: function() { + isEnabled: function cmd_installFromFile_isEnabled() true, + doCommand: function cmd_installFromFile_doCommand() { const nsIFilePicker = Ci.nsIFilePicker; var fp = Cc["@mozilla.org/filepicker;1"] .createInstance(nsIFilePicker); @@ -1345,13 +1212,13 @@ var gViewController = { getService(Ci.amIWebInstallListener); webInstaller.onWebInstallRequested(getBrowserElement(), document.documentURIObject, - installs); + installs, installs.length); } return; } var file = files.getNext(); - AddonManager.getInstallForFile(file, function(aInstall) { + AddonManager.getInstallForFile(file, function cmd_installFromFile_getInstallForFile(aInstall) { installs.push(aInstall); buildNextInstall(); }); @@ -1361,25 +1228,13 @@ var gViewController = { } }, - cmd_debugAddons: { - isEnabled: function() { - return true; - }, - doCommand: function() { - let mainWindow = getMainWindow(); - if ("switchToTabHavingURI" in mainWindow) { - mainWindow.switchToTabHavingURI("about:debugging#addons", true); - } - }, - }, - cmd_cancelOperation: { - isEnabled: function(aAddon) { + isEnabled: function cmd_cancelOperation_isEnabled(aAddon) { if (!aAddon) return false; return aAddon.pendingOperations != AddonManager.PENDING_NONE; }, - doCommand: function(aAddon) { + doCommand: function cmd_cancelOperation_doCommand(aAddon) { if (isPending(aAddon, "install")) { aAddon.install.cancel(); } else if (isPending(aAddon, "upgrade")) { @@ -1395,107 +1250,68 @@ var gViewController = { }, cmd_contribute: { - isEnabled: function(aAddon) { + isEnabled: function cmd_contribute_isEnabled(aAddon) { if (!aAddon) return false; return ("contributionURL" in aAddon && aAddon.contributionURL); }, - doCommand: function(aAddon) { + doCommand: function cmd_contribute_doCommand(aAddon) { openURL(aAddon.contributionURL); } }, cmd_askToActivateItem: { - isEnabled: function(aAddon) { + isEnabled: function cmd_askToActivateItem_isEnabled(aAddon) { if (!aAddon) return false; let addonType = AddonManager.addonTypes[aAddon.type]; return ((addonType.flags & AddonManager.TYPE_SUPPORTS_ASK_TO_ACTIVATE) && hasPermission(aAddon, "ask_to_activate")); }, - doCommand: function(aAddon) { + doCommand: function cmd_askToActivateItem_doCommand(aAddon) { aAddon.userDisabled = AddonManager.STATE_ASK_TO_ACTIVATE; } }, cmd_alwaysActivateItem: { - isEnabled: function(aAddon) { + isEnabled: function cmd_alwaysActivateItem_isEnabled(aAddon) { if (!aAddon) return false; let addonType = AddonManager.addonTypes[aAddon.type]; return ((addonType.flags & AddonManager.TYPE_SUPPORTS_ASK_TO_ACTIVATE) && hasPermission(aAddon, "enable")); }, - doCommand: function(aAddon) { + doCommand: function cmd_alwaysActivateItem_doCommand(aAddon) { aAddon.userDisabled = false; } }, cmd_neverActivateItem: { - isEnabled: function(aAddon) { + isEnabled: function cmd_neverActivateItem_isEnabled(aAddon) { if (!aAddon) return false; let addonType = AddonManager.addonTypes[aAddon.type]; return ((addonType.flags & AddonManager.TYPE_SUPPORTS_ASK_TO_ACTIVATE) && hasPermission(aAddon, "disable")); }, - doCommand: function(aAddon) { + doCommand: function cmd_neverActivateItem_doCommand(aAddon) { aAddon.userDisabled = true; } - }, - - cmd_experimentsLearnMore: { - isEnabled: function() { - let mainWindow = getMainWindow(); - return mainWindow && "switchToTabHavingURI" in mainWindow; - }, - doCommand: function() { - let url = Services.prefs.getCharPref("toolkit.telemetry.infoURL"); - openOptionsInTab(url); - }, - }, - - cmd_experimentsOpenTelemetryPreferences: { - isEnabled: function() { - return !!getMainWindowWithPreferencesPane(); - }, - doCommand: function() { - let mainWindow = getMainWindowWithPreferencesPane(); - mainWindow.openAdvancedPreferences("dataChoicesTab"); - }, - }, - - cmd_showUnsignedExtensions: { - isEnabled: function() { - return true; - }, - doCommand: function() { - gViewController.loadView("addons://list/extension?unsigned=true"); - }, - }, - - cmd_showAllExtensions: { - isEnabled: function() { - return true; - }, - doCommand: function() { - gViewController.loadView("addons://list/extension"); - }, - }, + } }, - supportsCommand: function(aCommand) { + supportsCommand: function gVC_supportsCommand(aCommand) { return (aCommand in this.commands); }, - isCommandEnabled: function(aCommand) { + isCommandEnabled: function gVC_isCommandEnabled(aCommand) { if (!this.supportsCommand(aCommand)) return false; var addon = this.currentViewObj.getSelectedAddon(); return this.commands[aCommand].isEnabled(addon); }, - updateCommands: function() { + updateCommands: function gVC_updateCommands() { // wait until the view is initialized if (!this.currentViewObj) return; @@ -1504,7 +1320,7 @@ var gViewController = { this.updateCommand(commandId, addon); }, - updateCommand: function(aCommandId, aAddon) { + updateCommand: function gVC_updateCommand(aCommandId, aAddon) { if (typeof aAddon == "undefined") aAddon = this.currentViewObj.getSelectedAddon(); var cmd = this.commands[aCommandId]; @@ -1519,7 +1335,7 @@ var gViewController = { } }, - doCommand: function(aCommand, aAddon) { + doCommand: function gVC_doCommand(aCommand, aAddon) { if (!this.supportsCommand(aCommand)) return; var cmd = this.commands[aCommand]; @@ -1530,12 +1346,11 @@ var gViewController = { cmd.doCommand(aAddon); }, - onEvent: function() {} + onEvent: function gVC_onEvent() {} }; function hasInlineOptions(aAddon) { return (aAddon.optionsType == AddonManager.OPTIONS_TYPE_INLINE || - aAddon.optionsType == AddonManager.OPTIONS_TYPE_INLINE_BROWSER || aAddon.optionsType == AddonManager.OPTIONS_TYPE_INLINE_INFO); } @@ -1549,11 +1364,14 @@ function openOptionsInTab(optionsURL) { } function formatDate(aDate) { - const locale = Cc["@mozilla.org/chrome/chrome-registry;1"] - .getService(Ci.nsIXULChromeRegistry) - .getSelectedLocale("global", true); - const dtOptions = { year: 'numeric', month: 'long', day: 'numeric' }; - return aDate.toLocaleDateString(locale, dtOptions); + return Cc["@mozilla.org/intl/scriptabledateformat;1"] + .getService(Ci.nsIScriptableDateFormat) + .FormatDate("", + Ci.nsIScriptableDateFormat.dateFormatLong, + aDate.getFullYear(), + aDate.getMonth() + 1, + aDate.getDate() + ); } @@ -1577,10 +1395,6 @@ function shouldShowVersionNumber(aAddon) { if (!aAddon.version) return false; - // The version number is hidden for experiments. - if (aAddon.type == "experiment") - return false; - // The version number is hidden for lightweight themes. if (aAddon.type == "theme") return !/@personas\.mozilla\.org$/.test(aAddon.id); @@ -1614,10 +1428,6 @@ function createItem(aObj, aIsInstall, aIsRemote) { // the binding handles the rest item.setAttribute("value", aObj.id); - if (aObj.type == "experiment") { - item.endDate = getExperimentEndDate(aObj); - } - return item; } @@ -1702,7 +1512,8 @@ function sortElements(aElements, aSortBy, aAscending) { if (addonType && (addonType.flags & AddonManager.TYPE_SUPPORTS_ASK_TO_ACTIVATE) && addon.userDisabled == AddonManager.STATE_ASK_TO_ACTIVATE) return "askToActivate"; - return "enabled"; + else + return "enabled"; } return addon[aKey]; @@ -1726,7 +1537,7 @@ function sortElements(aElements, aSortBy, aAscending) { } - aElements.sort(function(a, b) { + aElements.sort(function elementsSort(a, b) { if (!aAscending) [a, b] = [b, a]; @@ -1771,15 +1582,15 @@ function getAddonsAndInstalls(aType, aCallback) { let addons = null, installs = null; let types = (aType != null) ? [aType] : null; - AddonManager.getAddonsByTypes(types, function(aAddonsList) { - addons = aAddonsList.filter(a => !a.hidden); + AddonManager.getAddonsByTypes(types, function getAddonsAndInstalls_getAddonsByTypes(aAddonsList) { + addons = aAddonsList; if (installs != null) aCallback(addons, installs); }); - AddonManager.getInstallsByTypes(types, function(aInstallsList) { + AddonManager.getInstallsByTypes(types, function getAddonsAndInstalls_getInstallsByTypes(aInstallsList) { // skip over upgrade installs and non-active installs - installs = aInstallsList.filter(function(aInstall) { + installs = aInstallsList.filter(function installsFilter(aInstall) { return !(aInstall.existingAddon || aInstall.state == AddonManager.STATE_AVAILABLE); }); @@ -1796,7 +1607,7 @@ function doPendingUninstalls(aListBox) { var listitem = aListBox.firstChild; while (listitem) { if (listitem.getAttribute("pending") == "uninstall" && - !(listitem.opRequiresRestart("UNINSTALL"))) + !(listitem.opRequiresRestart("uninstall"))) items.push(listitem.mAddon); listitem = listitem.nextSibling; } @@ -1809,7 +1620,7 @@ var gCategories = { node: null, _search: null, - initialize: function() { + initialize: function gCategories_initialize() { this.node = document.getElementById("categories"); this._search = this.get("addons://search/"); @@ -1829,13 +1640,14 @@ var gCategories = { if (!this.node.selectedItem || this.node.selectedItem == this._search) this.node.value = gViewDefault; - this.node.addEventListener("select", () => { - this.maybeHideSearch(); - gViewController.loadView(this.node.selectedItem.value); + var self = this; + this.node.addEventListener("select", function node_onSelected() { + self.maybeHideSearch(); + gViewController.loadView(self.node.selectedItem.value); }, false); - this.node.addEventListener("click", (aEvent) => { - var selectedItem = this.node.selectedItem; + this.node.addEventListener("click", function node_onClicked(aEvent) { + var selectedItem = self.node.selectedItem; if (aEvent.target.localName == "richlistitem" && aEvent.target == selectedItem) { var viewId = selectedItem.value; @@ -1849,11 +1661,11 @@ var gCategories = { }, false); }, - shutdown: function() { + shutdown: function gCategories_shutdown() { AddonManager.removeTypeListener(this); }, - _insertCategory: function(aId, aName, aView, aPriority, aStartHidden) { + _insertCategory: function gCategories_insertCategory(aId, aName, aView, aPriority, aStartHidden) { // If this category already exists then don't re-add it if (document.getElementById("category-" + aId)) return; @@ -1887,7 +1699,7 @@ var gCategories = { this.node.insertBefore(category, node); }, - _removeCategory: function(aId) { + _removeCategory: function gCategories_removeCategory(aId) { var category = document.getElementById("category-" + aId); if (!category) return; @@ -1899,7 +1711,7 @@ var gCategories = { this.node.removeChild(category); }, - onTypeAdded: function(aType) { + onTypeAdded: function gCategories_onTypeAdded(aType) { // Ignore types that we don't have a view object for if (!(aType.viewType in gViewController.viewObjects)) return; @@ -1917,10 +1729,11 @@ var gCategories = { startHidden = true; } + var self = this; gPendingInitializations++; - getAddonsAndInstalls(aType.id, (aAddonsList, aInstallsList) => { + getAddonsAndInstalls(aType.id, function onTypeAdded_getAddonsAndInstalls(aAddonsList, aInstallsList) { var hidden = (aAddonsList.length == 0 && aInstallsList.length == 0); - var item = this.get(aViewId); + var item = self.get(aViewId); // Don't load view that is becoming hidden if (hidden && aViewId == gViewController.currentViewId) @@ -1935,25 +1748,25 @@ var gCategories = { } gEventManager.registerInstallListener({ - onDownloadStarted: function(aInstall) { + onDownloadStarted: function gCategories_onDownloadStarted(aInstall) { this._maybeShowCategory(aInstall); }, - onInstallStarted: function(aInstall) { + onInstallStarted: function gCategories_onInstallStarted(aInstall) { this._maybeShowCategory(aInstall); }, - onInstallEnded: function(aInstall, aAddon) { + onInstallEnded: function gCategories_onInstallEnded(aInstall, aAddon) { this._maybeShowCategory(aAddon); }, - onExternalInstall: function(aAddon, aExistingAddon, aRequiresRestart) { + onExternalInstall: function gCategories_onExternalInstall(aAddon, aExistingAddon, aRequiresRestart) { this._maybeShowCategory(aAddon); }, - _maybeShowCategory: aAddon => { + _maybeShowCategory: function gCategories_maybeShowCategory(aAddon) { if (aType.id == aAddon.type) { - this.get(aViewId).hidden = false; + self.get(aViewId).hidden = false; Services.prefs.setBoolPref(prefName, false); gEventManager.unregisterInstallListener(this); } @@ -1968,7 +1781,7 @@ var gCategories = { startHidden); }, - onTypeRemoved: function(aType) { + onTypeRemoved: function gCategories_onTypeRemoved(aType) { this._removeCategory(aType.id); }, @@ -1976,13 +1789,12 @@ var gCategories = { return this.node.selectedItem ? this.node.selectedItem.value : null; }, - select: function(aId, aPreviousView) { + select: function gCategories_select(aId, aPreviousView) { var view = gViewController.parseViewId(aId); if (view.type == "detail" && aPreviousView) { aId = aPreviousView; view = gViewController.parseViewId(aPreviousView); } - aId = aId.replace(/\?.*/, ""); Services.prefs.setCharPref(PREF_UI_LASTCATEGORY, aId); @@ -1993,11 +1805,10 @@ var gCategories = { return; } - var item; if (view.type == "search") - item = this._search; + var item = this._search; else - item = this.get(aId); + var item = this.get(aId); if (item) { item.hidden = false; @@ -2011,20 +1822,20 @@ var gCategories = { } }, - get: function(aId) { + get: function gCategories_get(aId) { var items = document.getElementsByAttribute("value", aId); if (items.length) return items[0]; return null; }, - setBadge: function(aId, aCount) { + setBadge: function gCategories_setBadge(aId, aCount) { let item = this.get(aId); if (item) item.badgeCount = aCount; }, - maybeHideSearch: function() { + maybeHideSearch: function gCategories_maybeHideSearch() { var view = gViewController.parseViewId(this.node.selectedItem.value); this._search.disabled = view.type != "search"; } @@ -2035,10 +1846,10 @@ var gHeader = { _search: null, _dest: "", - initialize: function() { + initialize: function gHeader_initialize() { this._search = document.getElementById("header-search"); - this._search.addEventListener("command", function(aEvent) { + this._search.addEventListener("command", function search_onCommand(aEvent) { var query = aEvent.target.value; if (query.length == 0) return; @@ -2052,7 +1863,7 @@ var gHeader = { document.getElementById("forward-btn").hidden = !shouldShow; } - window.addEventListener("focus", function(aEvent) { + window.addEventListener("focus", function window_onFocus(aEvent) { if (aEvent.target == window) updateNavButtonVisibility(); }, false); @@ -2060,15 +1871,27 @@ var gHeader = { updateNavButtonVisibility(); }, - focusSearchBox: function() { + focusSearchBox: function gHeader_focusSearchBox() { this._search.focus(); }, - onKeyPress: function(aEvent) { + onKeyPress: function gHeader_onKeyPress(aEvent) { if (String.fromCharCode(aEvent.charCode) == "/") { this.focusSearchBox(); return; } + + // XXXunf Temporary until bug 371900 is fixed. + let key = document.getElementById("focusSearch").getAttribute("key"); +#ifdef XP_MACOSX + let keyModifier = aEvent.metaKey; +#else + let keyModifier = aEvent.ctrlKey; +#endif + if (String.fromCharCode(aEvent.charCode) == key && keyModifier) { + this.focusSearchBox(); + return; + } }, get shouldShowNavButtons() { @@ -2123,9 +1946,8 @@ var gDiscoverView = { _error: null, homepageURL: null, _loadListeners: [], - hideHeader: true, - initialize: function() { + initialize: function gDiscoverView_initialize() { this.enabled = isDiscoverEnabled(); if (!this.enabled) { gCategories.get("addons://discover/").hidden = true; @@ -2147,20 +1969,22 @@ var gDiscoverView = { url = url.replace("%COMPATIBILITY_MODE%", compatMode); url = Services.urlFormatter.formatURL(url); - let setURL = (aURL) => { + var self = this; + + function setURL(aURL) { try { - this.homepageURL = Services.io.newURI(aURL, null, null); + self.homepageURL = Services.io.newURI(aURL, null, null); } catch (e) { - this.showError(); + self.showError(); notifyInitialized(); return; } - this._browser.homePage = this.homepageURL.spec; - this._browser.addProgressListener(this); + self._browser.homePage = self.homepageURL.spec; + self._browser.addProgressListener(self); - if (this.loaded) - this._loadURL(this.homepageURL.spec, false, notifyInitialized); + if (self.loaded) + self._loadURL(self.homepageURL.spec, false, notifyInitialized); else notifyInitialized(); } @@ -2171,7 +1995,7 @@ var gDiscoverView = { } gPendingInitializations++; - AddonManager.getAllAddons(function(aAddons) { + AddonManager.getAllAddons(function initialize_getAllAddons(aAddons) { var list = {}; for (let addon of aAddons) { var prefName = PREF_GETADDONS_CACHE_ID_ENABLED.replace("%ID%", @@ -2194,7 +2018,7 @@ var gDiscoverView = { }); }, - destroy: function() { + destroy: function gDiscoverView_destroy() { try { this._browser.removeProgressListener(this); } @@ -2203,7 +2027,7 @@ var gDiscoverView = { } }, - show: function(aParam, aRequest, aState, aIsRefresh) { + show: function gDiscoverView_show(aParam, aRequest, aState, aIsRefresh) { gViewController.updateCommands(); // If we're being told to load a specific URL then just do that @@ -2234,24 +2058,24 @@ var gDiscoverView = { gViewController.notifyViewChanged.bind(gViewController)); }, - canRefresh: function() { + canRefresh: function gDiscoverView_canRefresh() { if (this._browser.currentURI && this._browser.currentURI.spec == this._browser.homePage) return false; return true; }, - refresh: function(aParam, aRequest, aState) { + refresh: function gDiscoverView_refresh(aParam, aRequest, aState) { this.show(aParam, aRequest, aState, true); }, - hide: function() { }, + hide: function gDiscoverView_hide() { }, - showError: function() { + showError: function gDiscoverView_showError() { this.node.selectedPanel = this._error; }, - _loadURL: function(aURL, aKeepHistory, aCallback) { + _loadURL: function gDiscoverView_loadURL(aURL, aKeepHistory, aCallback) { if (this._browser.currentURI.spec == aURL) { if (aCallback) aCallback(); @@ -2268,7 +2092,7 @@ var gDiscoverView = { this._browser.loadURIWithFlags(aURL, flags); }, - onLocationChange: function(aWebProgress, aRequest, aLocation, aFlags) { + onLocationChange: function gDiscoverView_onLocationChange(aWebProgress, aRequest, aLocation, aFlags) { // Ignore the about:blank load if (aLocation.spec == "about:blank") return; @@ -2306,7 +2130,7 @@ var gDiscoverView = { aRequest.cancel(Components.results.NS_BINDING_ABORTED); }, - onSecurityChange: function(aWebProgress, aRequest, aState) { + onSecurityChange: function gDiscoverView_onSecurityChange(aWebProgress, aRequest, aState) { // Don't care about security if the page is not https if (!this.homepageURL.schemeIs("https")) return; @@ -2320,12 +2144,12 @@ var gDiscoverView = { aRequest.cancel(Components.results.NS_BINDING_ABORTED); }, - onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus) { + onStateChange: function gDiscoverView_onStateChange(aWebProgress, aRequest, aStateFlags, aStatus) { let transferStart = Ci.nsIWebProgressListener.STATE_IS_DOCUMENT | Ci.nsIWebProgressListener.STATE_IS_REQUEST | Ci.nsIWebProgressListener.STATE_TRANSFERRING; // Once transferring begins show the content - if ((aStateFlags & transferStart) === transferStart) + if (aStateFlags & transferStart) this.node.selectedPanel = this._browser; // Only care about the network events @@ -2364,15 +2188,13 @@ var gDiscoverView = { listener(); }, - onProgressChange: function() { }, - onStatusChange: function() { }, + onProgressChange: function gDiscoverView_onProgressChange() { }, + onStatusChange: function gDiscoverView_onStatusChange() { }, QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener, Ci.nsISupportsWeakReference]), - getSelectedAddon: function() { - return null; - } + getSelectedAddon: function gDiscoverView_getSelectedAddon() null }; @@ -2390,7 +2212,7 @@ var gSearchView = { _lastRemoteTotal: 0, _pendingSearches: 0, - initialize: function() { + initialize: function gSearchView_initialize() { this.node = document.getElementById("search-view"); this._filter = document.getElementById("search-filter-radiogroup"); this._sorters = document.getElementById("search-sorters"); @@ -2403,18 +2225,19 @@ var gSearchView = { if (!AddonManager.isInstallEnabled("application/x-xpinstall")) this._filter.hidden = true; - this._listBox.addEventListener("keydown", aEvent => { + var self = this; + this._listBox.addEventListener("keydown", function listbox_onKeydown(aEvent) { if (aEvent.keyCode == aEvent.DOM_VK_RETURN) { - var item = this._listBox.selectedItem; + var item = self._listBox.selectedItem; if (item) item.showInDetailView(); } }, false); - this._filter.addEventListener("command", () => this.updateView(), false); + this._filter.addEventListener("command", function filter_onCommand() self.updateView(), false); }, - shutdown: function() { + shutdown: function gSearchView_shutdown() { if (AddonRepository.isSearching) AddonRepository.cancelSearch(); }, @@ -2423,7 +2246,7 @@ var gSearchView = { return this._pendingSearches > 0; }, - show: function(aQuery, aRequest) { + show: function gSearchView_show(aQuery, aRequest) { gEventManager.registerInstallListener(this); this.showEmptyNotice(false); @@ -2446,18 +2269,19 @@ var gSearchView = { while (this._listBox.firstChild.localName == "richlistitem") this._listBox.removeChild(this._listBox.firstChild); + var self = this; gCachedAddons = {}; this._pendingSearches = 2; this._sorters.setSort("relevancescore", false); var elements = []; - let createSearchResults = (aObjsList, aIsInstall, aIsRemote) => { + function createSearchResults(aObjsList, aIsInstall, aIsRemote) { for (let index in aObjsList) { let obj = aObjsList[index]; let score = aObjsList.length - index; if (!aIsRemote && aQuery.length > 0) { - score = this.getMatchScore(obj, aQuery); + score = self.getMatchScore(obj, aQuery); if (score == 0) continue; } @@ -2467,29 +2291,29 @@ var gSearchView = { if (aIsRemote) { gCachedAddons[obj.id] = obj; if (obj.purchaseURL) - this._sorters.showprice = true; + self._sorters.showprice = true; } elements.push(item); } } - let finishSearch = (createdCount) => { + function finishSearch(createdCount) { if (elements.length > 0) { - sortElements(elements, [this._sorters.sortBy], this._sorters.ascending); + sortElements(elements, [self._sorters.sortBy], self._sorters.ascending); for (let element of elements) - this._listBox.insertBefore(element, this._listBox.lastChild); - this.updateListAttributes(); + self._listBox.insertBefore(element, self._listBox.lastChild); + self.updateListAttributes(); } - this._pendingSearches--; - this.updateView(); + self._pendingSearches--; + self.updateView(); - if (!this.isSearching) + if (!self.isSearching) gViewController.notifyViewChanged(); } - getAddonsAndInstalls(null, function(aAddons, aInstalls) { + getAddonsAndInstalls(null, function show_getAddonsAndInstalls(aAddons, aInstalls) { if (gViewController && aRequest != gViewController.currentViewRequest) return; @@ -2501,7 +2325,7 @@ var gSearchView = { var maxRemoteResults = 0; try { maxRemoteResults = Services.prefs.getIntPref(PREF_MAXRESULTS); - } catch (e) {} + } catch(e) {} if (maxRemoteResults <= 0) { finishSearch(0); @@ -2509,24 +2333,24 @@ var gSearchView = { } AddonRepository.searchAddons(aQuery, maxRemoteResults, { - searchFailed: () => { + searchFailed: function show_SearchFailed() { if (gViewController && aRequest != gViewController.currentViewRequest) return; - this._lastRemoteTotal = 0; + self._lastRemoteTotal = 0; // XXXunf Better handling of AMO search failure. See bug 579502 finishSearch(0); // Silently fail }, - searchSucceeded: (aAddonsList, aAddonCount, aTotalResults) => { + searchSucceeded: function show_SearchSucceeded(aAddonsList, aAddonCount, aTotalResults) { if (gViewController && aRequest != gViewController.currentViewRequest) return; if (aTotalResults > maxRemoteResults) - this._lastRemoteTotal = aTotalResults; + self._lastRemoteTotal = aTotalResults; else - this._lastRemoteTotal = 0; + self._lastRemoteTotal = 0; var createdCount = createSearchResults(aAddonsList, false, true); finishSearch(createdCount); @@ -2534,12 +2358,12 @@ var gSearchView = { }); }, - showLoading: function(aLoading) { + showLoading: function gSearchView_showLoading(aLoading) { this._loading.hidden = !aLoading; this._listBox.hidden = aLoading; }, - updateView: function() { + updateView: function gSearchView_updateView() { var showLocal = this._filter.value == "local"; if (!showLocal && !AddonManager.isInstallEnabled("application/x-xpinstall")) @@ -2567,12 +2391,12 @@ var gSearchView = { gViewController.updateCommands(); }, - hide: function() { + hide: function gSearchView_hide() { gEventManager.unregisterInstallListener(this); doPendingUninstalls(this._listBox); }, - getMatchScore: function(aObj, aQuery) { + getMatchScore: function gSearchView_getMatchScore(aObj, aQuery) { var score = 0; score += this.calculateMatchScore(aObj.name, aQuery, SEARCH_SCORE_MULTIPLIER_NAME); @@ -2581,7 +2405,7 @@ var gSearchView = { return score; }, - calculateMatchScore: function(aStr, aQuery, aMultiplier) { + calculateMatchScore: function gSearchView_calculateMatchScore(aStr, aQuery, aMultiplier) { var score = 0; if (!aStr || aQuery.length == 0) return score; @@ -2613,12 +2437,12 @@ var gSearchView = { return score * aMultiplier; }, - showEmptyNotice: function(aShow) { + showEmptyNotice: function gSearchView_showEmptyNotice(aShow) { this._emptyNotice.hidden = !aShow; this._listBox.hidden = aShow; }, - showAllResultsLink: function(aTotalResults) { + showAllResultsLink: function gSearchView_showAllResultsLink(aTotalResults) { if (aTotalResults == 0) { this._allResultsLink.hidden = true; return; @@ -2632,9 +2456,9 @@ var gSearchView = { this._allResultsLink.setAttribute("href", AddonRepository.getSearchURL(this._lastQuery)); this._allResultsLink.hidden = false; - }, + }, - updateListAttributes: function() { + updateListAttributes: function gSearchView_updateListAttributes() { var item = this._listBox.querySelector("richlistitem[remote='true'][first]"); if (item) item.removeAttribute("first"); @@ -2661,7 +2485,7 @@ var gSearchView = { }, - onSortChanged: function(aSortBy, aAscending) { + onSortChanged: function gSearchView_onSortChanged(aSortBy, aAscending) { var footer = this._listBox.lastChild; this._listBox.removeChild(footer); @@ -2671,15 +2495,15 @@ var gSearchView = { this._listBox.appendChild(footer); }, - onDownloadCancelled: function(aInstall) { + onDownloadCancelled: function gSearchView_onDownloadCancelled(aInstall) { this.removeInstall(aInstall); }, - onInstallCancelled: function(aInstall) { + onInstallCancelled: function gSearchView_onInstallCancelled(aInstall) { this.removeInstall(aInstall); }, - removeInstall: function(aInstall) { + removeInstall: function gSearchView_removeInstall(aInstall) { for (let item of this._listBox.childNodes) { if (item.mInstall == aInstall) { this._listBox.removeChild(item); @@ -2688,14 +2512,14 @@ var gSearchView = { } }, - getSelectedAddon: function() { + getSelectedAddon: function gSearchView_getSelectedAddon() { var item = this._listBox.selectedItem; if (item) return item.mAddon; return null; }, - getListItemForID: function(aId) { + getListItemForID: function gSearchView_getListItemForID(aId) { var listitem = this._listBox.firstChild; while (listitem) { if (listitem.getAttribute("status") == "installed" && listitem.mAddon.id == aId) @@ -2713,52 +2537,22 @@ var gListView = { _emptyNotice: null, _type: null, - initialize: function() { + initialize: function gListView_initialize() { this.node = document.getElementById("list-view"); this._listBox = document.getElementById("addon-list"); this._emptyNotice = document.getElementById("addon-list-empty"); - this._listBox.addEventListener("keydown", (aEvent) => { + var self = this; + this._listBox.addEventListener("keydown", function listbox_onKeydown(aEvent) { if (aEvent.keyCode == aEvent.DOM_VK_RETURN) { - var item = this._listBox.selectedItem; + var item = self._listBox.selectedItem; if (item) item.showInDetailView(); } }, false); - - document.getElementById("signing-learn-more").setAttribute("href", - Services.urlFormatter.formatURLPref("app.support.baseURL") + "unsigned-addons"); - - let findSignedAddonsLink = document.getElementById("find-alternative-addons"); - try { - findSignedAddonsLink.setAttribute("href", - Services.urlFormatter.formatURLPref("extensions.getAddons.link.url")); - } catch (e) { - findSignedAddonsLink.classList.remove("text-link"); - } - - try { - document.getElementById("signing-dev-manual-link").setAttribute("href", - Services.prefs.getCharPref("xpinstall.signatures.devInfoURL")); - } catch (e) { - document.getElementById("signing-dev-info").hidden = true; - } - - if (Preferences.get("plugin.load_flash_only", true)) { - document.getElementById("plugindeprecation-learnmore-link") - .setAttribute("href", Services.urlFormatter.formatURLPref("app.support.baseURL") + "npapi"); - } else { - document.getElementById("plugindeprecation-notice").hidden = true; - } }, - show: function(aType, aRequest) { - let showOnlyDisabledUnsigned = false; - if (aType.endsWith("?unsigned=true")) { - aType = aType.replace(/\?.*/, ""); - showOnlyDisabledUnsigned = true; - } - + show: function gListView_show(aType, aRequest) { if (!(aType in AddonManager.addonTypes)) throw Components.Exception("Attempting to show unknown type " + aType, Cr.NS_ERROR_INVALID_ARG); @@ -2773,7 +2567,8 @@ var gListView = { navigator.plugins.refresh(false); } - getAddonsAndInstalls(aType, (aAddonsList, aInstallsList) => { + var self = this; + getAddonsAndInstalls(aType, function show_getAddonsAndInstalls(aAddonsList, aInstallsList) { if (gViewController && aRequest != gViewController.currentViewRequest) return; @@ -2785,96 +2580,64 @@ var gListView = { for (let installItem of aInstallsList) elements.push(createItem(installItem, true)); - this.showEmptyNotice(elements.length == 0); + self.showEmptyNotice(elements.length == 0); if (elements.length > 0) { sortElements(elements, ["uiState", "name"], true); for (let element of elements) - this._listBox.appendChild(element); + self._listBox.appendChild(element); } - this.filterDisabledUnsigned(showOnlyDisabledUnsigned); - - gEventManager.registerInstallListener(this); + gEventManager.registerInstallListener(self); gViewController.updateCommands(); gViewController.notifyViewChanged(); }); }, - hide: function() { + hide: function gListView_hide() { gEventManager.unregisterInstallListener(this); doPendingUninstalls(this._listBox); }, - filterDisabledUnsigned: function(aFilter = true) { - let foundDisabledUnsigned = false; - - if (SIGNING_REQUIRED) { - for (let item of this._listBox.childNodes) { - if (!isCorrectlySigned(item.mAddon)) - foundDisabledUnsigned = true; - else - item.hidden = aFilter; - } - } - - document.getElementById("show-disabled-unsigned-extensions").hidden = - aFilter || !foundDisabledUnsigned; - - document.getElementById("show-all-extensions").hidden = !aFilter; - document.getElementById("disabled-unsigned-addons-info").hidden = !aFilter; - }, - - showEmptyNotice: function(aShow) { + showEmptyNotice: function gListView_showEmptyNotice(aShow) { this._emptyNotice.hidden = !aShow; - this._listBox.hidden = aShow; }, - onSortChanged: function(aSortBy, aAscending) { + onSortChanged: function gListView_onSortChanged(aSortBy, aAscending) { sortList(this._listBox, aSortBy, aAscending); }, - onExternalInstall: function(aAddon, aExistingAddon, aRequiresRestart) { + onExternalInstall: function gListView_onExternalInstall(aAddon, aExistingAddon, aRequiresRestart) { // The existing list item will take care of upgrade installs if (aExistingAddon) return; - if (aAddon.hidden) - return; - this.addItem(aAddon); }, - onDownloadStarted: function(aInstall) { + onDownloadStarted: function gListView_onDownloadStarted(aInstall) { this.addItem(aInstall, true); }, - onInstallStarted: function(aInstall) { + onInstallStarted: function gListView_onInstallStarted(aInstall) { this.addItem(aInstall, true); }, - onDownloadCancelled: function(aInstall) { + onDownloadCancelled: function gListView_onDownloadCancelled(aInstall) { this.removeItem(aInstall, true); }, - onInstallCancelled: function(aInstall) { + onInstallCancelled: function gListView_onInstallCancelled(aInstall) { this.removeItem(aInstall, true); }, - onInstallEnded: function(aInstall) { + onInstallEnded: function gListView_onInstallEnded(aInstall) { // Remove any install entries for upgrades, their status will appear against // the existing item if (aInstall.existingAddon) this.removeItem(aInstall, true); - - if (aInstall.addon.type == "experiment") { - let item = this.getListItemForID(aInstall.addon.id); - if (item) { - item.endDate = getExperimentEndDate(aInstall.addon); - } - } }, - addItem: function(aObj, aIsInstall) { + addItem: function gListView_addItem(aObj, aIsInstall) { if (aObj.type != this._type) return; @@ -2892,7 +2655,7 @@ var gListView = { this.showEmptyNotice(false); }, - removeItem: function(aObj, aIsInstall) { + removeItem: function gListView_removeItem(aObj, aIsInstall) { let prop = aIsInstall ? "mInstall" : "mAddon"; for (let item of this._listBox.childNodes) { @@ -2904,14 +2667,14 @@ var gListView = { } }, - getSelectedAddon: function() { + getSelectedAddon: function gListView_getSelectedAddon() { var item = this._listBox.selectedItem; if (item) return item.mAddon; return null; }, - getListItemForID: function(aId) { + getListItemForID: function gListView_getListItemForID(aId) { var listitem = this._listBox.firstChild; while (listitem) { if (listitem.getAttribute("status") == "installed" && listitem.mAddon.id == aId) @@ -2929,25 +2692,26 @@ var gDetailView = { _loadingTimer: null, _autoUpdate: null, - initialize: function() { + initialize: function gDetailView_initialize() { this.node = document.getElementById("detail-view"); this._autoUpdate = document.getElementById("detail-autoUpdate"); - this._autoUpdate.addEventListener("command", () => { - this._addon.applyBackgroundUpdates = this._autoUpdate.value; + var self = this; + this._autoUpdate.addEventListener("command", function autoUpdate_onCommand() { + self._addon.applyBackgroundUpdates = self._autoUpdate.value; }, true); }, - shutdown: function() { + shutdown: function gDetailView_shutdown() { AddonManager.removeManagerListener(this); }, - onUpdateModeChanged: function() { + onUpdateModeChanged: function gDetailView_onUpdateModeChanged() { this.onPropertyChanged(["applyBackgroundUpdates"]); }, - _updateView: function(aAddon, aIsRemote, aScrollToPreferences) { + _updateView: function gDetailView_updateView(aAddon, aIsRemote, aScrollToPreferences) { AddonManager.addManagerListener(this); this.clearLoading(); @@ -2963,9 +2727,10 @@ var gDetailView = { gCategories.select("addons://list/" + aAddon.type); document.getElementById("detail-name").textContent = aAddon.name; - var icon = AddonManager.getPreferredIconURL(aAddon, 64, window); + var icon = aAddon.icon64URL ? aAddon.icon64URL : aAddon.iconURL; document.getElementById("detail-icon").src = icon ? icon : ""; document.getElementById("detail-creator").setCreator(aAddon.creator, aAddon.homepageURL); + document.getElementById("detail-translators").setTranslators(aAddon.translators, aAddon.type); var version = document.getElementById("detail-version"); if (shouldShowVersionNumber(aAddon)) { @@ -2975,7 +2740,6 @@ var gDetailView = { version.hidden = true; } - var screenshotbox = document.getElementById("detail-screenshot-box"); var screenshot = document.getElementById("detail-screenshot"); if (aAddon.screenshots && aAddon.screenshots.length > 0) { if (aAddon.screenshots[0].thumbnailURL) { @@ -2988,9 +2752,9 @@ var gDetailView = { screenshot.height = aAddon.screenshots[0].height; } screenshot.setAttribute("loading", "true"); - screenshotbox.hidden = false; + screenshot.hidden = false; } else { - screenshotbox.hidden = true; + screenshot.hidden = true; } var desc = document.getElementById("detail-desc"); @@ -3103,7 +2867,7 @@ var gDetailView = { downloadsRow.value = null; } - var canUpdate = !aIsRemote && hasPermission(aAddon, "upgrade") && aAddon.id != AddonManager.hotfixID; + var canUpdate = !aIsRemote && hasPermission(aAddon, "upgrade"); document.getElementById("detail-updates-row").hidden = !canUpdate; if ("applyBackgroundUpdates" in aAddon) { @@ -3130,41 +2894,13 @@ var gDetailView = { } } - if (this._addon.type == "experiment") { - let prefix = "details.experiment."; - let active = this._addon.isActive; - - let stateKey = prefix + "state." + (active ? "active" : "complete"); - let node = document.getElementById("detail-experiment-state"); - node.value = gStrings.ext.GetStringFromName(stateKey); - - let now = Date.now(); - let end = getExperimentEndDate(this._addon); - let days = Math.abs(end - now) / (24 * 60 * 60 * 1000); - - let timeKey = prefix + "time."; - let timeMessage; - if (days < 1) { - timeKey += (active ? "endsToday" : "endedToday"); - timeMessage = gStrings.ext.GetStringFromName(timeKey); - } else { - timeKey += (active ? "daysRemaining" : "daysPassed"); - days = Math.round(days); - let timeString = gStrings.ext.GetStringFromName(timeKey); - timeMessage = PluralForm.get(days, timeString) - .replace("#1", days); - } - - document.getElementById("detail-experiment-time").value = timeMessage; - } - - this.fillSettingsRows(aScrollToPreferences, (function() { + this.fillSettingsRows(aScrollToPreferences, (function updateView_fillSettingsRows() { this.updateState(); gViewController.notifyViewChanged(); }).bind(this)); }, - show: function(aAddonId, aRequest) { + show: function gDetailView_show(aAddonId, aRequest) { let index = aAddonId.indexOf("/preferences"); let scrollToPreferences = false; if (index >= 0) { @@ -3172,33 +2908,34 @@ var gDetailView = { scrollToPreferences = true; } - this._loadingTimer = setTimeout(() => { - this.node.setAttribute("loading-extended", true); + var self = this; + this._loadingTimer = setTimeout(function loadTimeOutTimer() { + self.node.setAttribute("loading-extended", true); }, LOADING_MSG_DELAY); var view = gViewController.currentViewId; - AddonManager.getAddonByID(aAddonId, (aAddon) => { + AddonManager.getAddonByID(aAddonId, function show_getAddonByID(aAddon) { if (gViewController && aRequest != gViewController.currentViewRequest) return; if (aAddon) { - this._updateView(aAddon, false, scrollToPreferences); + self._updateView(aAddon, false, scrollToPreferences); return; } // Look for an add-on pending install - AddonManager.getAllInstalls(aInstalls => { + AddonManager.getAllInstalls(function show_getAllInstalls(aInstalls) { for (let install of aInstalls) { if (install.state == AddonManager.STATE_INSTALLED && install.addon.id == aAddonId) { - this._updateView(install.addon, false); + self._updateView(install.addon, false); return; } } if (aAddonId in gCachedAddons) { - this._updateView(gCachedAddons[aAddonId], true); + self._updateView(gCachedAddons[aAddonId], true); return; } @@ -3210,7 +2947,7 @@ var gDetailView = { }); }, - hide: function() { + hide: function gDetailView_hide() { AddonManager.removeManagerListener(this); this.clearLoading(); if (this._addon) { @@ -3230,14 +2967,14 @@ var gDetailView = { } }, - updateState: function() { + updateState: function gDetailView_updateState() { gViewController.updateCommands(); var pending = this._addon.pendingOperations; if (pending != AddonManager.PENDING_NONE) { this.node.removeAttribute("notification"); - pending = null; + var pending = null; const PENDING_OPERATIONS = ["enable", "disable", "install", "uninstall", "upgrade"]; for (let op of PENDING_OPERATIONS) { @@ -3263,15 +3000,6 @@ var gDetailView = { errorLink.value = gStrings.ext.GetStringFromName("details.notification.blocked.link"); errorLink.href = this._addon.blocklistURL; errorLink.hidden = false; - } else if (!isCorrectlySigned(this._addon) && SIGNING_REQUIRED) { - this.node.setAttribute("notification", "error"); - document.getElementById("detail-error").textContent = gStrings.ext.formatStringFromName( - "details.notification.unsignedAndDisabled", [this._addon.name, gStrings.brandShortName], 2 - ); - let errorLink = document.getElementById("detail-error-link"); - errorLink.value = gStrings.ext.GetStringFromName("details.notification.unsigned.link"); - errorLink.href = Services.urlFormatter.formatURLPref("app.support.baseURL") + "unsigned-addons"; - errorLink.hidden = false; } else if (!this._addon.isCompatible && (AddonManager.checkCompatibility || (this._addon.blocklistState != Ci.nsIBlocklistService.STATE_SOFTBLOCKED))) { this.node.setAttribute("notification", "warning"); @@ -3280,22 +3008,13 @@ var gDetailView = { [this._addon.name, gStrings.brandShortName, gStrings.appVersion], 3 ); document.getElementById("detail-warning-link").hidden = true; - } else if (!isCorrectlySigned(this._addon)) { - this.node.setAttribute("notification", "warning"); - document.getElementById("detail-warning").textContent = gStrings.ext.formatStringFromName( - "details.notification.unsigned", [this._addon.name, gStrings.brandShortName], 2 - ); - var warningLink = document.getElementById("detail-warning-link"); - warningLink.value = gStrings.ext.GetStringFromName("details.notification.unsigned.link"); - warningLink.href = Services.urlFormatter.formatURLPref("app.support.baseURL") + "unsigned-addons"; - warningLink.hidden = false; } else if (this._addon.blocklistState == Ci.nsIBlocklistService.STATE_SOFTBLOCKED) { this.node.setAttribute("notification", "warning"); document.getElementById("detail-warning").textContent = gStrings.ext.formatStringFromName( "details.notification.softblocked", [this._addon.name], 1 ); - let warningLink = document.getElementById("detail-warning-link"); + var warningLink = document.getElementById("detail-warning-link"); warningLink.value = gStrings.ext.GetStringFromName("details.notification.softblocked.link"); warningLink.href = this._addon.blocklistURL; warningLink.hidden = false; @@ -3305,9 +3024,9 @@ var gDetailView = { "details.notification.outdated", [this._addon.name], 1 ); - let warningLink = document.getElementById("detail-warning-link"); + var warningLink = document.getElementById("detail-warning-link"); warningLink.value = gStrings.ext.GetStringFromName("details.notification.outdated.link"); - warningLink.href = this._addon.blocklistURL; + warningLink.href = Services.urlFormatter.formatURLPref("plugins.update.url"); warningLink.hidden = false; } else if (this._addon.blocklistState == Ci.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE) { this.node.setAttribute("notification", "error"); @@ -3315,7 +3034,7 @@ var gDetailView = { "details.notification.vulnerableUpdatable", [this._addon.name], 1 ); - let errorLink = document.getElementById("detail-error-link"); + var errorLink = document.getElementById("detail-error-link"); errorLink.value = gStrings.ext.GetStringFromName("details.notification.vulnerableUpdatable.link"); errorLink.href = this._addon.blocklistURL; errorLink.hidden = false; @@ -3325,7 +3044,7 @@ var gDetailView = { "details.notification.vulnerableNoUpdate", [this._addon.name], 1 ); - let errorLink = document.getElementById("detail-error-link"); + var errorLink = document.getElementById("detail-error-link"); errorLink.value = gStrings.ext.GetStringFromName("details.notification.vulnerableNoUpdate.link"); errorLink.href = this._addon.blocklistURL; errorLink.hidden = false; @@ -3368,7 +3087,7 @@ var gDetailView = { this.node.setAttribute("active", this._addon.isActive); }, - clearLoading: function() { + clearLoading: function gDetailView_clearLoading() { if (this._loadingTimer) { clearTimeout(this._loadingTimer); this._loadingTimer = null; @@ -3377,14 +3096,14 @@ var gDetailView = { this.node.removeAttribute("loading-extended"); }, - emptySettingsRows: function() { + emptySettingsRows: function gDetailView_emptySettingsRows() { var lastRow = document.getElementById("detail-downloads"); var rows = lastRow.parentNode; while (lastRow.nextSibling) rows.removeChild(rows.lastChild); }, - fillSettingsRows: function(aScrollToPreferences, aCallback) { + fillSettingsRows: function gDetailView_fillSettingsRows(aScrollToPreferences, aCallback) { this.emptySettingsRows(); if (!hasInlineOptions(this._addon)) { if (aCallback) @@ -3392,34 +3111,6 @@ var gDetailView = { return; } - // We can't use a promise for this, since some code (especially in tests) - // relies on us finishing before the ViewChanged event bubbles up to its - // listeners, and promises resolve asynchronously. - let whenViewLoaded = callback => { - if (gViewController.displayedView.hasAttribute("loading")) { - gDetailView.node.addEventListener("ViewChanged", function viewChangedEventListener() { - gDetailView.node.removeEventListener("ViewChanged", viewChangedEventListener); - callback(); - }); - } else { - callback(); - } - }; - - let finish = (firstSetting) => { - // Ensure the page has loaded and force the XBL bindings to be synchronously applied, - // then notify observers. - whenViewLoaded(() => { - if (firstSetting) - firstSetting.clientTop; - Services.obs.notifyObservers(document, - AddonManager.OPTIONS_NOTIFICATION_DISPLAYED, - this._addon.id); - if (aScrollToPreferences) - gDetailView.scrollToPreferencesRows(); - }); - } - // This function removes and returns the text content of aNode without // removing any child elements. Removing the text nodes ensures any XBL // bindings apply properly. @@ -3439,77 +3130,79 @@ var gDetailView = { var rows = document.getElementById("detail-downloads").parentNode; try { - if (this._addon.optionsType == AddonManager.OPTIONS_TYPE_INLINE_BROWSER) { - whenViewLoaded(() => { - this.createOptionsBrowser(rows).then(browser => { - // Make sure the browser is unloaded as soon as we change views, - // rather than waiting for the next detail view to load. - document.addEventListener("ViewChanged", function viewChangedEventListener() { - document.removeEventListener("ViewChanged", viewChangedEventListener); - browser.remove(); - }); - - finish(browser); - }); - }); - - if (aCallback) - aCallback(); - } else { - var xhr = new XMLHttpRequest(); - xhr.open("GET", this._addon.optionsURL, true); - xhr.responseType = "xml"; - xhr.onload = (function() { - var xml = xhr.responseXML; - var settings = xml.querySelectorAll(":root > setting"); - - var firstSetting = null; - for (var setting of settings) { - - var desc = stripTextNodes(setting).trim(); - if (!setting.hasAttribute("desc")) - setting.setAttribute("desc", desc); - - var type = setting.getAttribute("type"); - if (type == "file" || type == "directory") - setting.setAttribute("fullpath", "true"); - - setting = document.importNode(setting, true); - var style = setting.getAttribute("style"); - if (style) { - setting.removeAttribute("style"); - setting.setAttribute("style", style); - } - - rows.appendChild(setting); - var visible = window.getComputedStyle(setting, null).getPropertyValue("display") != "none"; - if (!firstSetting && visible) { - setting.setAttribute("first-row", true); - firstSetting = setting; - } + var xhr = new XMLHttpRequest(); + xhr.open("GET", this._addon.optionsURL, true); + xhr.responseType = "xml"; + xhr.onload = (function fillSettingsRows_onload() { + var xml = xhr.responseXML; + var settings = xml.querySelectorAll(":root > setting"); + + var firstSetting = null; + for (var setting of settings) { + + var desc = stripTextNodes(setting).trim(); + if (!setting.hasAttribute("desc")) + setting.setAttribute("desc", desc); + + var type = setting.getAttribute("type"); + if (type == "file" || type == "directory") + setting.setAttribute("fullpath", "true"); + + setting = document.importNode(setting, true); + var style = setting.getAttribute("style"); + if (style) { + setting.removeAttribute("style"); + setting.setAttribute("style", style); } - finish(firstSetting); + rows.appendChild(setting); + var visible = window.getComputedStyle(setting, null).getPropertyValue("display") != "none"; + if (!firstSetting && visible) { + setting.setAttribute("first-row", true); + firstSetting = setting; + } + } - if (aCallback) - aCallback(); - }).bind(this); - xhr.onerror = function(aEvent) { - Cu.reportError("Error " + aEvent.target.status + - " occurred while receiving " + this._addon.optionsURL); - if (aCallback) - aCallback(); - }; - xhr.send(); - } - } catch (e) { + // Ensure the page has loaded and force the XBL bindings to be synchronously applied, + // then notify observers. + if (gViewController.viewPort.selectedPanel.hasAttribute("loading")) { + gDetailView.node.addEventListener("ViewChanged", function viewChangedEventListener() { + gDetailView.node.removeEventListener("ViewChanged", viewChangedEventListener, false); + if (firstSetting) + firstSetting.clientTop; + Services.obs.notifyObservers(document, + AddonManager.OPTIONS_NOTIFICATION_DISPLAYED, + gDetailView._addon.id); + if (aScrollToPreferences) + gDetailView.scrollToPreferencesRows(); + }, false); + } else { + if (firstSetting) + firstSetting.clientTop; + Services.obs.notifyObservers(document, + AddonManager.OPTIONS_NOTIFICATION_DISPLAYED, + this._addon.id); + if (aScrollToPreferences) + gDetailView.scrollToPreferencesRows(); + } + if (aCallback) + aCallback(); + }).bind(this); + xhr.onerror = function fillSettingsRows_onerror(aEvent) { + Cu.reportError("Error " + aEvent.target.status + + " occurred while receiving " + this._addon.optionsURL); + if (aCallback) + aCallback(); + }; + xhr.send(); + } catch(e) { Cu.reportError(e); if (aCallback) aCallback(); } }, - scrollToPreferencesRows: function() { + scrollToPreferencesRows: function gDetailView_scrollToPreferencesRows() { // We find this row, rather than remembering it from above, // in case it has been changed by the observers. let firstRow = gDetailView.node.querySelector('setting[first-row="true"]'); @@ -3524,55 +3217,20 @@ var gDetailView = { } }, - createOptionsBrowser: function(parentNode) { - let browser = document.createElement("browser"); - browser.setAttribute("type", "content"); - browser.setAttribute("disableglobalhistory", "true"); - browser.setAttribute("class", "inline-options-browser"); - - return new Promise((resolve, reject) => { - let messageListener = { - receiveMessage({name, data}) { - if (name === "Extension:BrowserResized") - browser.style.height = `${data.height}px`; - else if (name === "Extension:BrowserContentLoaded") - resolve(browser); - }, - }; - - let onload = () => { - browser.removeEventListener("load", onload, true); - - let mm = new FakeFrameMessageManager(browser); - mm.loadFrameScript("chrome://extensions/content/ext-browser-content.js", - false); - mm.addMessageListener("Extension:BrowserContentLoaded", messageListener); - mm.addMessageListener("Extension:BrowserResized", messageListener); - mm.sendAsyncMessage("Extension:InitBrowser", {fixedWidth: true}); - - browser.setAttribute("src", this._addon.optionsURL); - }; - browser.addEventListener("load", onload, true); - browser.addEventListener("error", reject); - - parentNode.appendChild(browser); - }); - }, - - getSelectedAddon: function() { + getSelectedAddon: function gDetailView_getSelectedAddon() { return this._addon; }, - onEnabling: function() { + onEnabling: function gDetailView_onEnabling() { this.updateState(); }, - onEnabled: function() { + onEnabled: function gDetailView_onEnabled() { this.updateState(); this.fillSettingsRows(); }, - onDisabling: function(aNeedsRestart) { + onDisabling: function gDetailView_onDisabling(aNeedsRestart) { this.updateState(); if (!aNeedsRestart && hasInlineOptions(this._addon)) { Services.obs.notifyObservers(document, @@ -3581,24 +3239,24 @@ var gDetailView = { } }, - onDisabled: function() { + onDisabled: function gDetailView_onDisabled() { this.updateState(); this.emptySettingsRows(); }, - onUninstalling: function() { + onUninstalling: function gDetailView_onUninstalling() { this.updateState(); }, - onUninstalled: function() { + onUninstalled: function gDetailView_onUninstalled() { gViewController.popState(); }, - onOperationCancelled: function() { + onOperationCancelled: function gDetailView_onOperationCancelled() { this.updateState(); }, - onPropertyChanged: function(aProperties) { + onPropertyChanged: function gDetailView_onPropertyChanged(aProperties) { if (aProperties.indexOf("applyBackgroundUpdates") != -1) { this._autoUpdate.value = this._addon.applyBackgroundUpdates; let hideFindUpdates = AddonManager.shouldAutoUpdate(this._addon); @@ -3606,12 +3264,11 @@ var gDetailView = { } if (aProperties.indexOf("appDisabled") != -1 || - aProperties.indexOf("signedState") != -1 || aProperties.indexOf("userDisabled") != -1) this.updateState(); }, - onExternalInstall: function(aAddon, aExistingAddon, aNeedsRestart) { + onExternalInstall: function gDetailView_onExternalInstall(aAddon, aExistingAddon, aNeedsRestart) { // Only care about upgrades for the currently displayed add-on if (!aExistingAddon || aExistingAddon.id != this._addon.id) return; @@ -3622,7 +3279,7 @@ var gDetailView = { this.updateState(); }, - onInstallCancelled: function(aInstall) { + onInstallCancelled: function gDetailView_onInstallCancelled(aInstall) { if (aInstall.addon.id == this._addon.id) gViewController.popState(); } @@ -3637,7 +3294,7 @@ var gUpdatesView = { _updateSelected: null, _categoryItem: null, - initialize: function() { + initialize: function gUpdatesView_initialize() { this.node = document.getElementById("updates-view"); this._listBox = document.getElementById("updates-list"); this._emptyNotice = document.getElementById("updates-list-empty"); @@ -3647,7 +3304,7 @@ var gUpdatesView = { this._categoryItem = gCategories.get("addons://updates/available"); this._updateSelected = document.getElementById("update-selected-btn"); - this._updateSelected.addEventListener("command", function() { + this._updateSelected.addEventListener("command", function updateSelected_onCommand() { gUpdatesView.installSelected(); }, false); @@ -3657,12 +3314,12 @@ var gUpdatesView = { AddonManager.addInstallListener(this); }, - shutdown: function() { + shutdown: function gUpdatesView_shutdown() { AddonManager.removeAddonListener(this); AddonManager.removeInstallListener(this); }, - show: function(aType, aRequest) { + show: function gUpdatesView_show(aType, aRequest) { document.getElementById("empty-availableUpdates-msg").hidden = aType != "available"; document.getElementById("empty-recentUpdates-msg").hidden = aType != "recent"; this.showEmptyNotice(false); @@ -3677,91 +3334,92 @@ var gUpdatesView = { this._showAvailableUpdates(false, aRequest); }, - hide: function() { + hide: function gUpdatesView_hide() { this._updateSelected.hidden = true; this._categoryItem.disabled = this._categoryItem.badgeCount == 0; doPendingUninstalls(this._listBox); }, - _showRecentUpdates: function(aRequest) { - AddonManager.getAllAddons((aAddonsList) => { + _showRecentUpdates: function gUpdatesView_showRecentUpdates(aRequest) { + var self = this; + AddonManager.getAllAddons(function showRecentUpdates_getAllAddons(aAddonsList) { if (gViewController && aRequest != gViewController.currentViewRequest) return; var elements = []; let threshold = Date.now() - UPDATES_RECENT_TIMESPAN; for (let addon of aAddonsList) { - if (addon.hidden || !addon.updateDate || addon.updateDate.getTime() < threshold) + if (!addon.updateDate || addon.updateDate.getTime() < threshold) continue; elements.push(createItem(addon)); } - this.showEmptyNotice(elements.length == 0); + self.showEmptyNotice(elements.length == 0); if (elements.length > 0) { - sortElements(elements, [this._sorters.sortBy], this._sorters.ascending); + sortElements(elements, [self._sorters.sortBy], self._sorters.ascending); for (let element of elements) - this._listBox.appendChild(element); + self._listBox.appendChild(element); } gViewController.notifyViewChanged(); }); }, - _showAvailableUpdates: function(aIsRefresh, aRequest) { + _showAvailableUpdates: function gUpdatesView_showAvailableUpdates(aIsRefresh, aRequest) { /* Disable the Update Selected button so it can't get clicked before everything is initialized asynchronously. It will get re-enabled by maybeDisableUpdateSelected(). */ this._updateSelected.disabled = true; - AddonManager.getAllInstalls((aInstallsList) => { + var self = this; + AddonManager.getAllInstalls(function showAvailableUpdates_getAllInstalls(aInstallsList) { if (!aIsRefresh && gViewController && aRequest && aRequest != gViewController.currentViewRequest) return; if (aIsRefresh) { - this.showEmptyNotice(false); - this._updateSelected.hidden = true; + self.showEmptyNotice(false); + self._updateSelected.hidden = true; - while (this._listBox.childNodes.length > 0) - this._listBox.removeChild(this._listBox.firstChild); + while (self._listBox.itemCount > 0) + self._listBox.removeItemAt(0); } var elements = []; for (let install of aInstallsList) { - if (!this.isManualUpdate(install)) + if (!self.isManualUpdate(install)) continue; let item = createItem(install.existingAddon); item.setAttribute("upgrade", true); - item.addEventListener("IncludeUpdateChanged", () => { - this.maybeDisableUpdateSelected(); + item.addEventListener("IncludeUpdateChanged", function item_onIncludeUpdateChanged() { + self.maybeDisableUpdateSelected(); }, false); elements.push(item); } - this.showEmptyNotice(elements.length == 0); + self.showEmptyNotice(elements.length == 0); if (elements.length > 0) { - this._updateSelected.hidden = false; - sortElements(elements, [this._sorters.sortBy], this._sorters.ascending); + self._updateSelected.hidden = false; + sortElements(elements, [self._sorters.sortBy], self._sorters.ascending); for (let element of elements) - this._listBox.appendChild(element); + self._listBox.appendChild(element); } // ensure badge count is in sync - this._categoryItem.badgeCount = this._listBox.itemCount; + self._categoryItem.badgeCount = self._listBox.itemCount; gViewController.notifyViewChanged(); }); }, - showEmptyNotice: function(aShow) { + showEmptyNotice: function gUpdatesView_showEmptyNotice(aShow) { this._emptyNotice.hidden = !aShow; - this._listBox.hidden = aShow; }, - isManualUpdate: function(aInstall, aOnlyAvailable) { + isManualUpdate: function gUpdatesView_isManualUpdate(aInstall, aOnlyAvailable) { var isManual = aInstall.existingAddon && !AddonManager.shouldAutoUpdate(aInstall.existingAddon); if (isManual && aOnlyAvailable) @@ -3769,28 +3427,29 @@ var gUpdatesView = { return isManual; }, - maybeRefresh: function() { + maybeRefresh: function gUpdatesView_maybeRefresh() { if (gViewController.currentViewId == "addons://updates/available") this._showAvailableUpdates(true); this.updateAvailableCount(); }, - updateAvailableCount: function(aInitializing) { + updateAvailableCount: function gUpdatesView_updateAvailableCount(aInitializing) { if (aInitializing) gPendingInitializations++; - AddonManager.getAllInstalls((aInstallsList) => { - var count = aInstallsList.filter(aInstall => { - return this.isManualUpdate(aInstall, true); + var self = this; + AddonManager.getAllInstalls(function updateAvailableCount_getAllInstalls(aInstallsList) { + var count = aInstallsList.filter(function installListFilter(aInstall) { + return self.isManualUpdate(aInstall, true); }).length; - this._categoryItem.disabled = gViewController.currentViewId != "addons://updates/available" && + self._categoryItem.disabled = gViewController.currentViewId != "addons://updates/available" && count == 0; - this._categoryItem.badgeCount = count; + self._categoryItem.badgeCount = count; if (aInitializing) notifyInitialized(); }); }, - maybeDisableUpdateSelected: function() { + maybeDisableUpdateSelected: function gUpdatesView_maybeDisableUpdateSelected() { for (let item of this._listBox.childNodes) { if (item.includeUpdate) { this._updateSelected.disabled = false; @@ -3800,7 +3459,7 @@ var gUpdatesView = { this._updateSelected.disabled = true; }, - installSelected: function() { + installSelected: function gUpdatesView_installSelected() { for (let item of this._listBox.childNodes) { if (item.includeUpdate) item.upgrade(); @@ -3809,14 +3468,14 @@ var gUpdatesView = { this._updateSelected.disabled = true; }, - getSelectedAddon: function() { + getSelectedAddon: function gUpdatesView_getSelectedAddon() { var item = this._listBox.selectedItem; if (item) return item.mAddon; return null; }, - getListItemForID: function(aId) { + getListItemForID: function gUpdatesView_getListItemForID(aId) { var listitem = this._listBox.firstChild; while (listitem) { if (listitem.mAddon.id == aId) @@ -3826,42 +3485,48 @@ var gUpdatesView = { return null; }, - onSortChanged: function(aSortBy, aAscending) { + onSortChanged: function gUpdatesView_onSortChanged(aSortBy, aAscending) { sortList(this._listBox, aSortBy, aAscending); }, - onNewInstall: function(aInstall) { + onNewInstall: function gUpdatesView_onNewInstall(aInstall) { if (!this.isManualUpdate(aInstall)) return; this.maybeRefresh(); }, - onInstallStarted: function(aInstall) { + onInstallStarted: function gUpdatesView_onInstallStarted(aInstall) { this.updateAvailableCount(); }, - onInstallCancelled: function(aInstall) { + onInstallCancelled: function gUpdatesView_onInstallCancelled(aInstall) { if (!this.isManualUpdate(aInstall)) return; this.maybeRefresh(); }, - onPropertyChanged: function(aAddon, aProperties) { + onPropertyChanged: function gUpdatesView_onPropertyChanged(aAddon, aProperties) { if (aProperties.indexOf("applyBackgroundUpdates") != -1) this.updateAvailableCount(); } }; +function debuggingPrefChanged() { + gViewController.updateState(); + gViewController.updateCommands(); + gViewController.notifyViewChanged(); +} + var gDragDrop = { - onDragOver: function(aEvent) { + onDragOver: function gDragDrop_onDragOver(aEvent) { var types = aEvent.dataTransfer.types; - if (types.includes("text/uri-list") || - types.includes("text/x-moz-url") || - types.includes("application/x-moz-file")) + if (types.contains("text/uri-list") || + types.contains("text/x-moz-url") || + types.contains("application/x-moz-file")) aEvent.preventDefault(); }, - onDrop: function(aEvent) { + onDrop: function gDragDrop_onDrop(aEvent) { var dataTransfer = aEvent.dataTransfer; var urls = []; @@ -3897,12 +3562,12 @@ var gDragDrop = { getService(Ci.amIWebInstallListener); webInstaller.onWebInstallRequested(getBrowserElement(), document.documentURIObject, - installs); + installs, installs.length); } return; } - AddonManager.getInstallForURL(urls[pos++], function(aInstall) { + AddonManager.getInstallForURL(urls[pos++], function onDrop_getInstallForURL(aInstall) { installs.push(aInstall); buildNextInstall(); }, "application/x-xpinstall"); diff --git a/toolkit/mozapps/extensions/content/extensions.xml b/toolkit/mozapps/extensions/content/extensions.xml index b49645cf0..fab340540 100644 --- a/toolkit/mozapps/extensions/content/extensions.xml +++ b/toolkit/mozapps/extensions/content/extensions.xml @@ -7,10 +7,10 @@ <!DOCTYPE page [ <!ENTITY % extensionsDTD SYSTEM "chrome://mozapps/locale/extensions/extensions.dtd"> %extensionsDTD; +<!ENTITY % aboutDTD SYSTEM "chrome://mozapps/locale/extensions/about.dtd"> +%aboutDTD; ]> -<!-- import-globals-from extensions.js --> - <bindings id="addonBindings" xmlns="http://www.mozilla.org/xbl" xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" @@ -489,6 +489,52 @@ </binding> + <!-- Translators list - Names of a translators of Language Pack. --> + <binding id="translators-list"> + <content> + <xul:label anonid="label" value="&translators.label;" class="sectionTitle"/> + <xul:vbox flex="1" anonid="translatorsBox" class="boxIndent"/> + </content> + + <implementation> + <constructor><![CDATA[ + if (this.hasAttribute("nameonly") && + this.getAttribute("nameonly") == "true") { + this._label.hidden = true; + } + ]]></constructor> + + <field name="_label"> + document.getAnonymousElementByAttribute(this, "anonid", "label"); + </field> + <field name="_translatorsBox"> + document.getAnonymousElementByAttribute(this, "anonid", "translatorsBox"); + </field> + + <method name="setTranslators"> + <parameter name="aTranslators"/> + <parameter name="aType"/> + <body><![CDATA[ + if (aType != "locale" || !aTranslators || aTranslators.length == 0) { + this.collapsed = true; + return; + } + this.collapsed = false; + while (this._translatorsBox.firstChild) { + this._translatorsBox.removeChild(this._translatorsBox.firstChild); + } + for (let currentItem of aTranslators) { + var label = document.createElement("label"); + label.textContent = currentItem; + label.setAttribute("class", "contributor"); + this._translatorsBox.appendChild(label); + } + ]]></body> + </method> + </implementation> + </binding> + + <!-- Install status - Displays the status of an install/upgrade. --> <binding id="install-status"> <content> @@ -739,14 +785,6 @@ ]]></body> </method> - <method name="isPending"> - <parameter name="aAction"/> - <body><![CDATA[ - var action = AddonManager["PENDING_" + aAction.toUpperCase()]; - return !!(this.mAddon.pendingOperations & action); - ]]></body> - </method> - <method name="typeHasFlag"> <parameter name="aFlag"/> <body><![CDATA[ @@ -757,6 +795,14 @@ ]]></body> </method> + <method name="isPending"> + <parameter name="aAction"/> + <body><![CDATA[ + var action = AddonManager["PENDING_" + aAction.toUpperCase()]; + return !!(this.mAddon.pendingOperations & action); + ]]></body> + </method> + <method name="onUninstalled"> <body><![CDATA[ this.parentNode.removeChild(this); @@ -775,14 +821,14 @@ <xul:image class="warning-icon"/> <xul:label anonid="warning" flex="1"/> <xul:label anonid="warning-link" class="text-link"/> - <xul:button anonid="warning-btn" class="button-link" hidden="true"/> + <xul:button anonid="warning-btn" class="button-link"/> <xul:spacer flex="5000"/> <!-- Necessary to allow the message to wrap --> </xul:hbox> <xul:hbox anonid="error-container" class="error"> <xul:image class="error-icon"/> <xul:label anonid="error" flex="1"/> - <xul:label anonid="error-link" class="text-link" hidden="true"/> + <xul:label anonid="error-link" class="text-link"/> <xul:spacer flex="5000"/> <!-- Necessary to allow the message to wrap --> </xul:hbox> <xul:hbox anonid="pending-container" @@ -799,7 +845,7 @@ <xul:spacer flex="5000"/> <!-- Necessary to allow the message to wrap --> </xul:hbox> - <xul:hbox class="content-container" align="center"> + <xul:hbox class="content-container"> <xul:vbox class="icon-container"> <xul:image anonid="icon" class="icon"/> </xul:vbox> @@ -807,7 +853,10 @@ <xul:hbox class="basicinfo-container"> <xul:hbox class="name-container"> <xul:label anonid="name" class="name" crop="end" flex="1" - tooltip="addonitem-tooltip" xbl:inherits="value=name"/> + xbl:inherits="value=name,tooltiptext=name"/> + <xul:label anonid="version" class="version"/> + <xul:label class="nativeIndicator nativeAddon" value="●" tooltiptext="&addon.nativeAddon;"/> + <xul:label class="nativeIndicator compatAddon" value="●" tooltiptext="&addon.compatAddon;"/> <xul:label class="disabled-postfix" value="&addon.disabled.postfix;"/> <xul:label class="update-postfix" value="&addon.update.postfix;"/> <xul:spacer flex="5000"/> <!-- Necessary to make the name crop --> @@ -853,72 +902,77 @@ oncommand="document.getBindingParent(this).toggleReleaseNotes();"/> </xul:hbox> </xul:vbox> - </xul:hbox> - </xul:vbox> - <xul:vbox class="status-control-wrapper"> - <xul:hbox class="status-container"> - <xul:hbox anonid="checking-update" hidden="true"> - <xul:image class="spinner"/> - <xul:label value="&addon.checkingForUpdates.label;"/> - </xul:hbox> - <xul:vbox anonid="update-available" class="update-available" - hidden="true"> - <xul:checkbox anonid="include-update" class="include-update" - label="&addon.includeUpdate.label;" checked="true" - oncommand="document.getBindingParent(this).onIncludeUpdateChanged();"/> - <xul:hbox class="update-info-container"> - <xul:label class="update-available-notice" - value="&addon.updateAvailable.label;"/> - <xul:button anonid="update-btn" class="addon-control update" - label="&addon.updateNow.label;" - tooltiptext="&addon.updateNow.tooltip;" - oncommand="document.getBindingParent(this).upgrade();"/> + <xul:vbox class="status-control-wrapper"> + <xul:hbox class="status-container"> + <xul:hbox anonid="checking-update" hidden="true"> + <xul:image class="spinner"/> + <xul:label value="&addon.checkingForUpdates.label;"/> + </xul:hbox> + <xul:vbox anonid="update-available" class="update-available" + hidden="true"> + <xul:checkbox anonid="include-update" class="include-update" + label="&addon.includeUpdate.label;" checked="true" + oncommand="document.getBindingParent(this).onIncludeUpdateChanged();"/> + <xul:hbox class="update-info-container"> + <xul:label class="update-available-notice" + value="&addon.updateAvailable.label;"/> + <xul:button anonid="update-btn" class="addon-control update" + label="&addon.updateNow.label;" + tooltiptext="&addon.updateNow.tooltip;" + oncommand="document.getBindingParent(this).upgrade();"/> + </xul:hbox> + </xul:vbox> + <xul:hbox anonid="install-status" class="install-status" + hidden="true"/> </xul:hbox> - </xul:vbox> - <xul:hbox anonid="install-status" class="install-status" - hidden="true"/> - </xul:hbox> - <xul:hbox anonid="control-container" class="control-container"> - <xul:button anonid="preferences-btn" - class="addon-control preferences" + <xul:hbox anonid="control-container" class="control-container"> + <xul:button anonid="preferences-btn" + class="addon-control preferences" #ifdef XP_WIN - label="&cmd.showPreferencesWin.label;" - tooltiptext="&cmd.showPreferencesWin.tooltip;" + label="&cmd.showPreferencesWin.label;" + tooltiptext="&cmd.showPreferencesWin.tooltip;" #else - label="&cmd.showPreferencesUnix.label;" - tooltiptext="&cmd.showPreferencesUnix.tooltip;" + label="&cmd.showPreferencesUnix.label;" + tooltiptext="&cmd.showPreferencesUnix.tooltip;" #endif - oncommand="document.getBindingParent(this).showPreferences();"/> - <xul:button anonid="enable-btn" class="addon-control enable" - label="&cmd.enableAddon.label;" - oncommand="document.getBindingParent(this).userDisabled = false;"/> - <xul:button anonid="disable-btn" class="addon-control disable" - label="&cmd.disableAddon.label;" - oncommand="document.getBindingParent(this).userDisabled = true;"/> - <xul:button anonid="remove-btn" class="addon-control remove" - label="&cmd.uninstallAddon.label;" - oncommand="document.getBindingParent(this).uninstall();"/> - <xul:menulist anonid="state-menulist" - class="addon-control state" - tooltiptext="&cmd.stateMenu.tooltip;"> - <xul:menupopup> - <xul:menuitem anonid="ask-to-activate-menuitem" - class="addon-control" - label="&cmd.askToActivate.label;" - tooltiptext="&cmd.askToActivate.tooltip;" - oncommand="document.getBindingParent(this).userDisabled = AddonManager.STATE_ASK_TO_ACTIVATE;"/> - <xul:menuitem anonid="always-activate-menuitem" - class="addon-control" - label="&cmd.alwaysActivate.label;" - tooltiptext="&cmd.alwaysActivate.tooltip;" - oncommand="document.getBindingParent(this).userDisabled = false;"/> - <xul:menuitem anonid="never-activate-menuitem" - class="addon-control" - label="&cmd.neverActivate.label;" - tooltiptext="&cmd.neverActivate.tooltip;" - oncommand="document.getBindingParent(this).userDisabled = true;"/> - </xul:menupopup> - </xul:menulist> + oncommand="document.getBindingParent(this).showPreferences();"/> + <!-- label="&cmd.debugAddon.label;" --> + <xul:button anonid="debug-btn" class="addon-control debug" + label="&cmd.debugAddon.label;" + oncommand="document.getBindingParent(this).debug();"/> + + <xul:button anonid="enable-btn" class="addon-control enable" + label="&cmd.enableAddon.label;" + oncommand="document.getBindingParent(this).userDisabled = false;"/> + <xul:button anonid="disable-btn" class="addon-control disable" + label="&cmd.disableAddon.label;" + oncommand="document.getBindingParent(this).userDisabled = true;"/> + <xul:button anonid="remove-btn" class="addon-control remove" + label="&cmd.uninstallAddon.label;" + oncommand="document.getBindingParent(this).uninstall();"/> + <xul:menulist anonid="state-menulist" + class="addon-control state" + tooltiptext="&cmd.stateMenu.tooltip;"> + <xul:menupopup> + <xul:menuitem anonid="ask-to-activate-menuitem" + class="addon-control" + label="&cmd.askToActivate.label;" + tooltiptext="&cmd.askToActivate.tooltip;" + oncommand="document.getBindingParent(this).userDisabled = AddonManager.STATE_ASK_TO_ACTIVATE;"/> + <xul:menuitem anonid="always-activate-menuitem" + class="addon-control" + label="&cmd.alwaysActivate.label;" + tooltiptext="&cmd.alwaysActivate.tooltip;" + oncommand="document.getBindingParent(this).userDisabled = false;"/> + <xul:menuitem anonid="never-activate-menuitem" + class="addon-control" + label="&cmd.neverActivate.label;" + tooltiptext="&cmd.neverActivate.tooltip;" + oncommand="document.getBindingParent(this).userDisabled = true;"/> + </xul:menupopup> + </xul:menulist> + </xul:hbox> + </xul:vbox> </xul:hbox> </xul:vbox> </xul:hbox> @@ -926,7 +980,6 @@ <implementation> <constructor><![CDATA[ - this._installStatus = document.getAnonymousElementByAttribute(this, "anonid", "install-status"); this._installStatus.mControl = this; this.setAttribute("contextmenu", "addonitem-popup"); @@ -986,6 +1039,9 @@ document.getAnonymousElementByAttribute(this, "anonid", "info"); </field> + <field name="_version"> + document.getAnonymousElementByAttribute(this, "anonid", "version"); + </field> <field name="_experimentState"> document.getAnonymousElementByAttribute(this, "anonid", "experiment-state"); </field> @@ -1027,6 +1083,10 @@ document.getAnonymousElementByAttribute(this, "anonid", "enable-btn"); </field> + <field name="_debugBtn"> + document.getAnonymousElementByAttribute(this, "anonid", + "debug-btn"); + </field> <field name="_disableBtn"> document.getAnonymousElementByAttribute(this, "anonid", "disable-btn"); @@ -1095,8 +1155,8 @@ return this._includeUpdate.checked && !!this.mManualUpdate; ]]></getter> <setter><![CDATA[ - // XXXunf Eventually, we'll want to persist this for individual - // updates - see bug 594619. + //XXXunf Eventually, we'll want to persist this for individual + // updates - see bug 594619. this._includeUpdate.checked = !!val; ]]></setter> </property> @@ -1112,12 +1172,17 @@ this.setAttribute("name", aAddon.name); - var iconURL = AddonManager.getPreferredIconURL(aAddon, 48, window); + var iconURL = this.mAddon.iconURL; if (iconURL) this._icon.src = iconURL; else this._icon.src = ""; + if (shouldShowVersionNumber(this.mAddon)) + this._version.value = this.mAddon.version; + else + this._version.hidden = true; + if (this.mAddon.description) this._description.value = this.mAddon.description; else @@ -1127,17 +1192,18 @@ (this.mAddon.applyBackgroundUpdates == AddonManager.AUTOUPDATE_DISABLE || (this.mAddon.applyBackgroundUpdates == AddonManager.AUTOUPDATE_DEFAULT && !AddonManager.autoUpdateDefault))) { - AddonManager.getAllInstalls(aInstallsList => { + var self = this; + AddonManager.getAllInstalls(function(aInstallsList) { // This can return after the binding has been destroyed, // so try to detect that and return early - if (!("onNewInstall" in this)) + if (!("onNewInstall" in self)) return; for (let install of aInstallsList) { if (install.existingAddon && - install.existingAddon.id == this.mAddon.id && + install.existingAddon.id == self.mAddon.id && install.state == AddonManager.STATE_AVAILABLE) { - this.onNewInstall(install); - this.onIncludeUpdateChanged(); + self.onNewInstall(install); + self.onIncludeUpdateChanged(); } } }); @@ -1165,11 +1231,14 @@ <method name="_updateDates"> <body><![CDATA[ function formatDate(aDate) { - const locale = Components.classes["@mozilla.org/chrome/chrome-registry;1"] - .getService(Components.interfaces.nsIXULChromeRegistry) - .getSelectedLocale("global", true); - const dtOptions = { year: 'numeric', month: 'long', day: 'numeric' }; - return aDate.toLocaleDateString(locale, dtOptions); + return Cc["@mozilla.org/intl/scriptabledateformat;1"] + .getService(Ci.nsIScriptableDateFormat) + .FormatDate("", + Ci.nsIScriptableDateFormat.dateFormatLong, + aDate.getFullYear(), + aDate.getMonth() + 1, + aDate.getDate() + ); } if (this.mAddon.updateDate) @@ -1188,7 +1257,7 @@ if (pending != AddonManager.PENDING_NONE) { this.removeAttribute("notification"); - pending = null; + var pending = null; const PENDING_OPERATIONS = ["enable", "disable", "install", "uninstall", "upgrade"]; for (let op of PENDING_OPERATIONS) { @@ -1238,14 +1307,6 @@ this._errorLink.value = gStrings.ext.GetStringFromName("notification.blocked.link"); this._errorLink.href = this.mAddon.blocklistURL; this._errorLink.hidden = false; - } else if (!isUpgrade && !isCorrectlySigned(this.mAddon) && SIGNING_REQUIRED) { - this.setAttribute("notification", "error"); - this._error.textContent = gStrings.ext.formatStringFromName( - "notification.unsignedAndDisabled", [this.mAddon.name, gStrings.brandShortName], 2 - ); - this._errorLink.value = gStrings.ext.GetStringFromName("notification.unsigned.link"); - this._errorLink.href = Services.urlFormatter.formatURLPref("app.support.baseURL") + "unsigned-addons"; - this._errorLink.hidden = false; } else if ((!isUpgrade && !this.mAddon.isCompatible) && (AddonManager.checkCompatibility || (this.mAddon.blocklistState != Ci.nsIBlocklistService.STATE_SOFTBLOCKED))) { this.setAttribute("notification", "warning"); @@ -1255,14 +1316,6 @@ ); this._warningLink.hidden = true; this._warningBtn.hidden = true; - } else if (!isUpgrade && !isCorrectlySigned(this.mAddon)) { - this.setAttribute("notification", "warning"); - this._warning.textContent = gStrings.ext.formatStringFromName( - "notification.unsigned", [this.mAddon.name, gStrings.brandShortName], 2 - ); - this._warningLink.value = gStrings.ext.GetStringFromName("notification.unsigned.link"); - this._warningLink.href = Services.urlFormatter.formatURLPref("app.support.baseURL") + "unsigned-addons"; - this._warningLink.hidden = false; } else if (!isUpgrade && this.mAddon.blocklistState == Ci.nsIBlocklistService.STATE_SOFTBLOCKED) { this.setAttribute("notification", "warning"); this._warning.textContent = gStrings.ext.formatStringFromName( @@ -1280,7 +1333,7 @@ [this.mAddon.name], 1 ); this._warningLink.value = gStrings.ext.GetStringFromName("notification.outdated.link"); - this._warningLink.href = this.mAddon.blocklistURL; + this._warningLink.href = Services.urlFormatter.formatURLPref("plugins.update.url"); this._warningLink.hidden = false; this._warningBtn.hidden = true; } else if (!isUpgrade && this.mAddon.blocklistState == Ci.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE) { @@ -1309,6 +1362,8 @@ [this.mAddon.name], 1); } else { this.removeAttribute("notification"); + if (this.mAddon.type == "extension") + this.setAttribute("native", this.mAddon.native); } } @@ -1335,31 +1390,30 @@ this._stateMenulist.classList.add('no-auto-hide'); } else { this._stateMenulist.hidden = true; - - let enableTooltip = gViewController.commands["cmd_enableItem"] - .getTooltip(this.mAddon); - this._enableBtn.setAttribute("tooltiptext", enableTooltip); if (this.hasPermission("enable")) { this._enableBtn.hidden = false; + let tooltip = gViewController.commands["cmd_enableItem"] + .getTooltip(this.mAddon); + this._enableBtn.setAttribute("tooltiptext", tooltip); } else { this._enableBtn.hidden = true; } - let disableTooltip = gViewController.commands["cmd_disableItem"] - .getTooltip(this.mAddon); - this._disableBtn.setAttribute("tooltiptext", disableTooltip); if (this.hasPermission("disable")) { this._disableBtn.hidden = false; + let tooltip = gViewController.commands["cmd_disableItem"] + .getTooltip(this.mAddon); + this._disableBtn.setAttribute("tooltiptext", tooltip); } else { this._disableBtn.hidden = true; } } - let uninstallTooltip = gViewController.commands["cmd_uninstallItem"] - .getTooltip(this.mAddon); - this._removeBtn.setAttribute("tooltiptext", uninstallTooltip); if (this.hasPermission("uninstall")) { this._removeBtn.hidden = false; + let tooltip = gViewController.commands["cmd_uninstallItem"] + .getTooltip(this.mAddon); + this._removeBtn.setAttribute("tooltiptext", tooltip); } else { this._removeBtn.hidden = true; } @@ -1370,6 +1424,12 @@ this.mAddon.install.state != AddonManager.STATE_INSTALLED); this._showStatus(showProgress ? "progress" : "none"); + let debuggable = this.mAddon.isDebuggable && + Services.prefs.getBoolPref('devtools.chrome.enabled') && + Services.prefs.getBoolPref('devtools.debugger.remote-enabled'); + + this._debugBtn.disabled = this._debugBtn.hidden = !debuggable + if (this.mAddon.type == "experiment") { this.removeAttribute("notification"); let prefix = "experiment."; @@ -1403,9 +1463,18 @@ ]]></body> </method> + <method name="_updateUpgradeInfo"> + <body><![CDATA[ + // Only update the version string if we're displaying the upgrade info + if (this.hasAttribute("upgrade") && shouldShowVersionNumber(this.mAddon)) + this._version.value = this.mManualUpdate.version; + ]]></body> + </method> + <method name="_fetchReleaseNotes"> <parameter name="aURI"/> <body><![CDATA[ + var self = this; if (!aURI || this._relNotesLoaded) { sendToggleEvent(); return; @@ -1417,17 +1486,17 @@ this._relNotesLoading.hidden = false; this._relNotesError.hidden = true; - let sendToggleEvent = () => { + function sendToggleEvent() { var event = document.createEvent("Events"); event.initEvent("RelNotesToggle", true, true); - this.dispatchEvent(event); + self.dispatchEvent(event); } - let showRelNotes = () => { + function showRelNotes() { if (!relNotesData || !transformData) return; - this._relNotesLoading.hidden = true; + self._relNotesLoading.hidden = true; var processor = Components.classes["@mozilla.org/document-transformer;1?type=xslt"] .createInstance(Components.interfaces.nsIXSLTProcessor); @@ -1435,20 +1504,20 @@ processor.importStylesheet(transformData); var fragment = processor.transformToFragment(relNotesData, document); - this._relNotes.appendChild(fragment); - if (this.hasAttribute("show-relnotes")) { - var container = this._relNotesContainer; + self._relNotes.appendChild(fragment); + if (self.hasAttribute("show-relnotes")) { + var container = self._relNotesContainer; container.style.height = container.scrollHeight + "px"; } sendToggleEvent(); } - let handleError = () => { + function handleError() { dataReq.abort(); styleReq.abort(); - this._relNotesLoading.hidden = true; - this._relNotesError.hidden = false; - this._relNotesLoaded = false; // allow loading to be re-tried + self._relNotesLoading.hidden = true; + self._relNotesError.hidden = false; + self._relNotesLoaded = false; // allow loading to be re-tried sendToggleEvent(); } @@ -1471,7 +1540,6 @@ var dataReq = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"] .createInstance(Components.interfaces.nsIXMLHttpRequest); dataReq.open("GET", aURI.spec, true); - dataReq.responseType = "document"; dataReq.addEventListener("load", handleResponse, false); dataReq.addEventListener("error", handleError, false); dataReq.send(null); @@ -1479,7 +1547,6 @@ var styleReq = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"] .createInstance(Components.interfaces.nsIXMLHttpRequest); styleReq.open("GET", UPDATES_RELEASENOTES_TRANSFORMFILE, true); - styleReq.responseType = "document"; styleReq.addEventListener("load", handleResponse, false); styleReq.addEventListener("error", handleError, false); styleReq.send(null); @@ -1555,6 +1622,12 @@ ]]></body> </method> + <method name="debug"> + <body><![CDATA[ + gViewController.doCommand("cmd_debugItem", this.mAddon); + ]]></body> + </method> + <method name="showPreferences"> <body><![CDATA[ gViewController.doCommand("cmd_showItemPreferences", this.mAddon); @@ -1637,7 +1710,6 @@ <parameter name="aProperties"/> <body><![CDATA[ if (aProperties.indexOf("appDisabled") != -1 || - aProperties.indexOf("signedState") != -1 || aProperties.indexOf("userDisabled") != -1) this._updateState(); ]]></body> @@ -1689,6 +1761,7 @@ this.mManualUpdate = aInstall; this._showStatus("update-available"); + this._updateUpgradeInfo(); ]]></body> </method> @@ -1890,7 +1963,8 @@ </xul:vbox> <xul:vbox class="fade name-outer-container" flex="1"> <xul:hbox class="name-container"> - <xul:label anonid="name" class="name" crop="end" tooltip="addonitem-tooltip"/> + <xul:label anonid="name" class="name" crop="end"/> + <xul:label anonid="version" class="version" hidden="true"/> </xul:hbox> </xul:vbox> <xul:vbox class="install-status-container"> @@ -1912,6 +1986,9 @@ <field name="_name"> document.getAnonymousElementByAttribute(this, "anonid", "name"); </field> + <field name="_version"> + document.getAnonymousElementByAttribute(this, "anonid", "version"); + </field> <field name="_warning"> document.getAnonymousElementByAttribute(this, "anonid", "warning"); </field> @@ -1939,6 +2016,14 @@ this._icon.src = this.mAddon.iconURL || (this.mInstall ? this.mInstall.iconURL : ""); this._name.value = this.mAddon.name; + + if (this.mAddon.version) { + this._version.value = this.mAddon.version; + this._version.hidden = false; + } else { + this._version.hidden = true; + } + } else { this._icon.src = this.mInstall.iconURL; // AddonInstall.name isn't always available - fallback to filename @@ -1952,6 +2037,13 @@ url.QueryInterface(Components.interfaces.nsIURL); this._name.value = url.fileName; } + + if (this.mInstall.version) { + this._version.value = this.mInstall.version; + this._version.hidden = false; + } else { + this._version.hidden = true; + } } if (this.mInstall.state == AddonManager.STATE_DOWNLOAD_FAILED) { diff --git a/toolkit/mozapps/extensions/content/extensions.xul b/toolkit/mozapps/extensions/content/extensions.xul index 70939d024..c1a8edc86 100644 --- a/toolkit/mozapps/extensions/content/extensions.xul +++ b/toolkit/mozapps/extensions/content/extensions.xul @@ -6,6 +6,7 @@ <?xml-stylesheet href="chrome://global/skin/" type="text/css"?> <?xml-stylesheet href="chrome://mozapps/content/extensions/extensions.css"?> <?xml-stylesheet href="chrome://mozapps/skin/extensions/extensions.css"?> +<?xml-stylesheet href="chrome://mozapps/skin/extensions/about.css"?> <!DOCTYPE page [ <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd" > @@ -52,6 +53,8 @@ <menuitem id="menuitem_uninstallItem" command="cmd_uninstallItem" label="&cmd.uninstallAddon.label;" accesskey="&cmd.uninstallAddon.accesskey;"/> + <menuitem id="menuitem_debugItem" command="cmd_debugItem" + label="&cmd.debugAddon.label;"/> <menuseparator id="addonitem-menuseparator" /> <menuitem id="menuitem_preferences" command="cmd_showItemPreferences" #ifdef XP_WIN @@ -68,32 +71,27 @@ label="&cmd.about.label;" accesskey="&cmd.about.accesskey;"/> </menupopup> - - <tooltip id="addonitem-tooltip"/> </popupset> <!-- global commands - these act on all addons, or affect the addons manager in some other way --> <commandset id="globalCommandSet"> - <!-- XXXsw remove useless oncommand attribute once bug 371900 is fixed --> - <command id="cmd_focusSearch" oncommand=";"/> + <command id="cmd_focusSearch"/> <command id="cmd_findAllUpdates"/> <command id="cmd_restartApp"/> <command id="cmd_goToDiscoverPane"/> <command id="cmd_goToRecentUpdates"/> <command id="cmd_goToAvailableUpdates"/> <command id="cmd_installFromFile"/> - <command id="cmd_debugAddons"/> <command id="cmd_back"/> <command id="cmd_forward"/> <command id="cmd_enableCheckCompatibility"/> +<!-- <command id="cmd_pluginCheck"/> --> <command id="cmd_enableUpdateSecurity"/> <command id="cmd_toggleAutoUpdateDefault"/> <command id="cmd_resetAddonAutoUpdate"/> <command id="cmd_experimentsLearnMore"/> <command id="cmd_experimentsOpenTelemetryPreferences"/> - <command id="cmd_showUnsignedExtensions"/> - <command id="cmd_showAllExtensions"/> </commandset> <!-- view commands - these act on the selected addon --> @@ -103,6 +101,7 @@ <command id="cmd_findItemUpdates"/> <command id="cmd_showItemPreferences"/> <command id="cmd_showItemAbout"/> + <command id="cmd_debugItem"/> <command id="cmd_enableItem"/> <command id="cmd_disableItem"/> <command id="cmd_installItem"/> @@ -117,51 +116,100 @@ </commandset> <keyset> + <!-- XXXunf Disabled until bug 371900 is fixed. --> <key id="focusSearch" key="&search.commandkey;" modifiers="accel" - command="cmd_focusSearch"/> + disabled="true"/> </keyset> + + <!-- main header --> + <hbox id="header" align="center"> + <toolbarbutton id="back-btn" class="nav-button header-button" command="cmd_back" + tooltiptext="&cmd.back.tooltip;" hidden="true" disabled="true"/> + <toolbarbutton id="forward-btn" class="nav-button header-button" command="cmd_forward" + tooltiptext="&cmd.forward.tooltip;" hidden="true" disabled="true"/> + <spacer flex="1"/> + <hbox id="updates-container" align="center"> + <image class="spinner"/> + <label id="updates-noneFound" hidden="true" + value="&updates.noneFound.label;"/> + <button id="updates-manualUpdatesFound-btn" class="button-link" + hidden="true" label="&updates.manualUpdatesFound.label;" + command="cmd_goToAvailableUpdates"/> + <label id="updates-progress" hidden="true" + value="&updates.updating.label;"/> + <label id="updates-installed" hidden="true" + value="&updates.installed.label;"/> + <label id="updates-downloaded" hidden="true" + value="&updates.downloaded.label;"/> + <button id="updates-restart-btn" class="button-link" hidden="true" + label="&updates.restart.label;" + command="cmd_restartApp"/> + </hbox> + <toolbarbutton id="header-utils-btn" class="header-button" type="menu" + tooltiptext="&toolsMenu.tooltip;"> + <menupopup id="utils-menu"> + <menuitem id="utils-updateNow" + label="&updates.checkForUpdates.label;" + accesskey="&updates.checkForUpdates.accesskey;" + command="cmd_findAllUpdates"/> + <menuitem id="utils-viewUpdates" + label="&updates.viewUpdates.label;" + accesskey="&updates.viewUpdates.accesskey;" + command="cmd_goToRecentUpdates"/> + <menuseparator id="utils-installFromFile-separator"/> + <menuitem id="utils-installFromFile" + label="&installAddonFromFile.label;" + accesskey="&installAddonFromFile.accesskey;" + command="cmd_installFromFile"/> + <menuseparator/> + <menuitem id="utils-autoUpdateDefault" + label="&updates.updateAddonsAutomatically.label;" + accesskey="&updates.updateAddonsAutomatically.accesskey;" + type="checkbox" autocheck="false" + command="cmd_toggleAutoUpdateDefault"/> + <menuitem id="utils-resetAddonUpdatesToAutomatic" + label="&updates.resetUpdatesToAutomatic.label;" + accesskey="&updates.resetUpdatesToAutomatic.accesskey;" + command="cmd_resetAddonAutoUpdate"/> + <menuitem id="utils-resetAddonUpdatesToManual" + label="&updates.resetUpdatesToManual.label;" + accesskey="&updates.resetUpdatesToManual.accesskey;" + command="cmd_resetAddonAutoUpdate"/> + </menupopup> + </toolbarbutton> + <textbox id="header-search" type="search" searchbutton="true" + searchbuttonlabel="&search.buttonlabel;" + placeholder="&search.placeholder;"/> + </hbox> + <hbox flex="1"> - <vbox> - <hbox id="nav-header" - align="center" - pack="center"> - <toolbarbutton id="back-btn" - class="nav-button header-button" - command="cmd_back" - tooltiptext="&cmd.back.tooltip;" - hidden="true" - disabled="true"/> - <toolbarbutton id="forward-btn" - class="nav-button header-button" - command="cmd_forward" - tooltiptext="&cmd.forward.tooltip;" - hidden="true" - disabled="true"/> - </hbox> - <!-- category list --> - <richlistbox id="categories" flex="1"> - <richlistitem id="category-search" value="addons://search/" - class="category" - name="&view.search.label;" priority="0" - tooltiptext="&view.search.label;" disabled="true"/> - <richlistitem id="category-discover" value="addons://discover/" - class="category" - name="&view.discover.label;" priority="1000" - tooltiptext="&view.discover.label;"/> - <richlistitem id="category-availableUpdates" value="addons://updates/available" - class="category" - name="&view.availableUpdates.label;" priority="100000" - tooltiptext="&view.availableUpdates.label;" - disabled="true"/> - <richlistitem id="category-recentUpdates" value="addons://updates/recent" - class="category" - name="&view.recentUpdates.label;" priority="101000" - tooltiptext="&view.recentUpdates.label;" disabled="true"/> - </richlistbox> - </vbox> - <vbox class="main-content" flex="1"> + + <!-- category list --> + <richlistbox id="categories"> + <richlistitem id="category-search" value="addons://search/" + class="category" + name="&view.search.label;" priority="0" + tooltiptext="&view.search.label;" disabled="true"/> + <richlistitem id="category-discover" value="addons://discover/" + class="category" + name="&view.discover.label;" priority="1000" + tooltiptext="&view.discover.label;"/> + <richlistitem id="category-availableUpdates" value="addons://updates/available" + class="category" + name="&view.availableUpdates.label;" priority="100000" + tooltiptext="&view.availableUpdates.label;" + disabled="true"/> + <richlistitem id="category-recentUpdates" value="addons://updates/recent" + class="category" + name="&view.recentUpdates.label;" priority="101000" + tooltiptext="&view.recentUpdates.label;" disabled="true"/> + </richlistbox> + + <box id="view-port-container" class="main-content" flex="1"> + <!-- view port --> <deck id="view-port" flex="1" selectedIndex="0"> + <!-- discover view --> <deck id="discover-view" flex="1" class="view-pane" selectedIndex="0" tabindex="0"> <vbox id="discover-loading" align="center" pack="stretch" flex="1" class="alert-container"> @@ -189,527 +237,453 @@ <spacer class="alert-spacer-after"/> </vbox> <browser id="discover-browser" type="content" flex="1" - disablehistory="true" homepage="about:blank"/> + disablehistory="true" homepage="about:blank"/> </deck> - <!-- container for views with the search/tools header --> - <vbox id="headered-views" flex="1"> - <!-- main header --> - <hbox id="header" align="center"> - <button id="show-all-extensions" hidden="true" - label="&showAllExtensions.button.label;" - command="cmd_showAllExtensions"/> - <spacer flex="1"/> - <hbox id="updates-container" align="center"> - <image class="spinner"/> - <label id="updates-noneFound" hidden="true" - value="&updates.noneFound.label;"/> - <button id="updates-manualUpdatesFound-btn" class="button-link" - hidden="true" label="&updates.manualUpdatesFound.label;" - command="cmd_goToAvailableUpdates"/> - <label id="updates-progress" hidden="true" - value="&updates.updating.label;"/> - <label id="updates-installed" hidden="true" - value="&updates.installed.label;"/> - <label id="updates-downloaded" hidden="true" - value="&updates.downloaded.label;"/> - <button id="updates-restart-btn" class="button-link" hidden="true" - label="&updates.restart.label;" - command="cmd_restartApp"/> + <!-- search view --> + <vbox id="search-view" flex="1" class="view-pane" tabindex="0"> + <hbox class="view-header global-warning-container" align="center"> + <!-- global warnings --> + <hbox class="global-warning" flex="1"> + <hbox class="global-warning-safemode" flex="1" align="center" + tooltiptext="&warning.safemode.label;"> + <image class="warning-icon"/> + <label class="global-warning-text" flex="1" crop="end" + value="&warning.safemode.label;"/> + </hbox> + <hbox class="global-warning-checkcompatibility" flex="1" align="center" + tooltiptext="&warning.checkcompatibility.label;"> + <image class="warning-icon"/> + <label class="global-warning-text" flex="1" crop="end" + value="&warning.checkcompatibility.label;"/> + </hbox> + <button class="button-link global-warning-checkcompatibility" + label="&warning.checkcompatibility.enable.label;" + tooltiptext="&warning.checkcompatibility.enable.tooltip;" + command="cmd_enableCheckCompatibility"/> + <hbox class="global-warning-updatesecurity" flex="1" align="center" + tooltiptext="&warning.updatesecurity.label;"> + <image class="warning-icon"/> + <label class="global-warning-text" flex="1" crop="end" + value="&warning.updatesecurity.label;"/> + </hbox> + <button class="button-link global-warning-updatesecurity" + label="&warning.updatesecurity.enable.label;" + tooltiptext="&warning.updatesecurity.enable.tooltip;" + command="cmd_enableUpdateSecurity"/> + <spacer flex="5000"/> <!-- Necessary to allow the message to wrap --> </hbox> - <button id="show-disabled-unsigned-extensions" hidden="true" - class="warning" - label="&showUnsignedExtensions.button.label;" - command="cmd_showUnsignedExtensions"/> - <toolbarbutton id="header-utils-btn" class="header-button" type="menu" - tooltiptext="&toolsMenu.tooltip;"> - <menupopup id="utils-menu"> - <menuitem id="utils-updateNow" - label="&updates.checkForUpdates.label;" - accesskey="&updates.checkForUpdates.accesskey;" - command="cmd_findAllUpdates"/> - <menuitem id="utils-viewUpdates" - label="&updates.viewUpdates.label;" - accesskey="&updates.viewUpdates.accesskey;" - command="cmd_goToRecentUpdates"/> - <menuseparator id="utils-installFromFile-separator"/> - <menuitem id="utils-installFromFile" - label="&installAddonFromFile.label;" - accesskey="&installAddonFromFile.accesskey;" - command="cmd_installFromFile"/> - <menuitem id="utils-debugAddons" - label="&debugAddons.label;" - accesskey="&debugAddons.accesskey;" - command="cmd_debugAddons"/> - <menuseparator/> - <menuitem id="utils-autoUpdateDefault" - label="&updates.updateAddonsAutomatically.label;" - accesskey="&updates.updateAddonsAutomatically.accesskey;" - type="checkbox" autocheck="false" - command="cmd_toggleAutoUpdateDefault"/> - <menuitem id="utils-resetAddonUpdatesToAutomatic" - label="&updates.resetUpdatesToAutomatic.label;" - accesskey="&updates.resetUpdatesToAutomatic.accesskey;" - command="cmd_resetAddonAutoUpdate"/> - <menuitem id="utils-resetAddonUpdatesToManual" - label="&updates.resetUpdatesToManual.label;" - accesskey="&updates.resetUpdatesToManual.accesskey;" - command="cmd_resetAddonAutoUpdate"/> - </menupopup> - </toolbarbutton> - <textbox id="header-search" type="search" searchbutton="true" - searchbuttonlabel="&search.buttonlabel;" - placeholder="&search.placeholder;"/> + <spacer flex="1"/> + <hbox id="search-sorters" class="sort-controls" + showrelevance="true" sortby="relevancescore" ascending="false"/> + </hbox> + <hbox id="search-filter" align="center"> + <label id="search-filter-label" value="&search.filter2.label;"/> + <radiogroup id="search-filter-radiogroup" orient="horizontal" + align="center" persist="value" value="remote"> + <radio id="search-filter-local" class="search-filter-radio" + label="&search.filter2.installed.label;" value="local" + tooltiptext="&search.filter2.installed.tooltip;"/> + <radio id="search-filter-remote" class="search-filter-radio" + label="&search.filter2.available.label;" value="remote" + tooltiptext="&search.filter2.available.tooltip;"/> + </radiogroup> </hbox> + <vbox id="search-loading" class="alert-container" + flex="1" hidden="true"> + <spacer class="alert-spacer-before"/> + <hbox class="alert loading" align="center"> + <image/> + <label value="&loading.label;"/> + </hbox> + <spacer class="alert-spacer-after"/> + </vbox> + <vbox id="search-list-empty" class="alert-container" + flex="1" hidden="true"> + <spacer class="alert-spacer-before"/> + <vbox class="alert"> + <label value="&listEmpty.search.label;"/> + <button class="discover-button" + id="discover-button-search" + label="&listEmpty.button.label;" + command="cmd_goToDiscoverPane"/> + </vbox> + <spacer class="alert-spacer-after"/> + </vbox> + <richlistbox id="search-list" class="list" flex="1"> + <hbox pack="center"> + <label id="search-allresults-link" class="text-link"/> + </hbox> + </richlistbox> + </vbox> - <deck id="headered-views-content" flex="1" selectedIndex="0"> - <!-- search view --> - <vbox id="search-view" flex="1" class="view-pane" tabindex="0"> - <hbox class="view-header global-warning-container" align="center"> - <!-- global warnings --> - <hbox class="global-warning" flex="1"> - <hbox class="global-warning-safemode" flex="1" align="center" - tooltiptext="&warning.safemode.label;"> - <image class="warning-icon"/> - <label class="global-warning-text" flex="1" crop="end" - value="&warning.safemode.label;"/> - </hbox> - <hbox class="global-warning-checkcompatibility" flex="1" align="center" - tooltiptext="&warning.checkcompatibility.label;"> - <image class="warning-icon"/> - <label class="global-warning-text" flex="1" crop="end" - value="&warning.checkcompatibility.label;"/> - </hbox> - <button class="button-link global-warning-checkcompatibility" - label="&warning.checkcompatibility.enable.label;" - tooltiptext="&warning.checkcompatibility.enable.tooltip;" - command="cmd_enableCheckCompatibility"/> - <hbox class="global-warning-updatesecurity" flex="1" align="center" - tooltiptext="&warning.updatesecurity.label;"> - <image class="warning-icon"/> - <label class="global-warning-text" flex="1" crop="end" - value="&warning.updatesecurity.label;"/> - </hbox> - <button class="button-link global-warning-updatesecurity" - label="&warning.updatesecurity.enable.label;" - tooltiptext="&warning.updatesecurity.enable.tooltip;" - command="cmd_enableUpdateSecurity"/> - <spacer flex="5000"/> <!-- Necessary to allow the message to wrap --> - </hbox> - <spacer flex="1"/> - <hbox id="search-sorters" class="sort-controls" - showrelevance="true" sortby="relevancescore" ascending="false"/> + <!-- list view --> + <vbox id="list-view" flex="1" class="view-pane" align="stretch" tabindex="0"> + <hbox class="view-header global-warning-container"> + <!-- global warnings --> + <hbox class="global-warning" flex="1"> + <hbox class="global-warning-safemode" flex="1" align="center" + tooltiptext="&warning.safemode.label;"> + <image class="warning-icon"/> + <label class="global-warning-text" flex="1" crop="end" + value="&warning.safemode.label;"/> </hbox> - <hbox id="search-filter" align="center"> - <label id="search-filter-label" value="&search.filter2.label;"/> - <radiogroup id="search-filter-radiogroup" orient="horizontal" - align="center" persist="value" value="remote"> - <radio id="search-filter-local" class="search-filter-radio" - label="&search.filter2.installed.label;" value="local" - tooltiptext="&search.filter2.installed.tooltip;"/> - <radio id="search-filter-remote" class="search-filter-radio" - label="&search.filter2.available.label;" value="remote" - tooltiptext="&search.filter2.available.tooltip;"/> - </radiogroup> + <hbox class="global-warning-checkcompatibility" flex="1" align="center" + tooltiptext="&warning.checkcompatibility.label;"> + <image class="warning-icon"/> + <label class="global-warning-text" flex="1" crop="end" + value="&warning.checkcompatibility.label;"/> </hbox> - <vbox id="search-loading" class="alert-container" - flex="1" hidden="true"> - <spacer class="alert-spacer-before"/> - <hbox class="alert loading" align="center"> - <image/> - <label value="&loading.label;"/> - </hbox> - <spacer class="alert-spacer-after"/> - </vbox> - <vbox id="search-list-empty" class="alert-container" - flex="1" hidden="true"> - <spacer class="alert-spacer-before"/> - <vbox class="alert"> - <label value="&listEmpty.search.label;"/> - <button class="discover-button" - id="discover-button-search" - label="&listEmpty.button.label;" - command="cmd_goToDiscoverPane"/> - </vbox> - <spacer class="alert-spacer-after"/> - </vbox> - <richlistbox id="search-list" class="list" flex="1"> - <hbox pack="center"> - <label id="search-allresults-link" class="text-link"/> - </hbox> - </richlistbox> + <button class="button-link global-warning-checkcompatibility" + label="&warning.checkcompatibility.enable.label;" + tooltiptext="&warning.checkcompatibility.enable.tooltip;" + command="cmd_enableCheckCompatibility"/> + <hbox class="global-warning-updatesecurity" flex="1" align="center" + tooltiptext="&warning.updatesecurity.label;"> + <image class="warning-icon"/> + <label class="global-warning-text" flex="1" crop="end" + value="&warning.updatesecurity.label;"/> + </hbox> + <button class="button-link global-warning-updatesecurity" + label="&warning.updatesecurity.enable.label;" + tooltiptext="&warning.updatesecurity.enable.tooltip;" + command="cmd_enableUpdateSecurity"/> + <spacer flex="5000"/> <!-- Necessary to allow the message to wrap --> + </hbox> + </hbox> +<!-- <hbox class="view-header global-info-container plugin-info-container"> + <hbox class="global-info" flex="1" align="center"> + <button class="button-link global-info-plugincheck" + label="&info.plugincheck.label;" + tooltiptext="&info.plugincheck.tooltip;" + command="cmd_pluginCheck"/> + <spacer flex="5000"/> + </hbox> + </hbox> --> + <hbox class="view-header global-info-container experiment-info-container"> + <hbox class="global-info" flex="1" align="center"> + <label value="&experiment.info.label;"/> + <button id="experiments-learn-more" + label="&experiment.info.learnmore;" + tooltiptext="&experiment.info.learnmore;" + accesskey="&experiment.info.learnmore.accesskey;" + command="cmd_experimentsLearnMore"/> + <button id="experiments-change-telemetry" + label="&experiment.info.changetelemetry;" + tooltiptext="&experiment.info.changetelemetry;" + accesskey="&experiment.info.changetelemetry.accesskey;" + command="cmd_experimentsOpenTelemetryPreferences"/> + <spacer flex="5000"/> <!-- Necessary to allow the message to wrap. --> + </hbox> + </hbox> + <vbox id="addon-list-empty" class="alert-container" + flex="1" hidden="true"> + <spacer class="alert-spacer-before"/> + <vbox class="alert"> + <label value="&listEmpty.installed.label;"/> + <button class="discover-button" + id="discover-button-install" + label="&listEmpty.button.label;" + command="cmd_goToDiscoverPane"/> </vbox> + <spacer class="alert-spacer-after"/> + </vbox> + <richlistbox id="addon-list" class="list" flex="1"/> + </vbox> - <!-- list view --> - <vbox id="list-view" flex="1" class="view-pane" align="stretch" tabindex="0"> - <!-- info UI for add-ons that have been disabled for being unsigned --> - <vbox id="disabled-unsigned-addons-info" hidden="true"> - <label id="disabled-unsigned-addons-heading" value="&disabledUnsigned.heading;"/> - <description> - &disabledUnsigned.description.start;<label class="text-link plain" id="find-alternative-addons">&disabledUnsigned.description.findAddonsLink;</label>&disabledUnsigned.description.end; - </description> - <hbox pack="start"><label class="text-link" id="signing-learn-more">&disabledUnsigned.learnMore;</label></hbox> - <description id="signing-dev-info"> - &disabledUnsigned.devInfo.start;<label class="text-link plain" id="signing-dev-manual-link">&disabledUnsigned.devInfo.linkToManual;</label>&disabledUnsigned.devInfo.end; - </description> - </vbox> - <vbox id="plugindeprecation-notice" class="alert-container"> - <hbox class="alert"> - <description>&pluginDeprecation.description;   - <label class="text-link plain" id="plugindeprecation-learnmore-link">&pluginDeprecation.learnMore;</label> - </description> - </hbox> - </vbox> - <hbox class="view-header global-warning-container"> - <!-- global warnings --> - <hbox class="global-warning" flex="1"> - <hbox class="global-warning-safemode" flex="1" align="center" - tooltiptext="&warning.safemode.label;"> - <image class="warning-icon"/> - <label class="global-warning-text" flex="1" crop="end" - value="&warning.safemode.label;"/> - </hbox> - <hbox class="global-warning-checkcompatibility" flex="1" align="center" - tooltiptext="&warning.checkcompatibility.label;"> - <image class="warning-icon"/> - <label class="global-warning-text" flex="1" crop="end" - value="&warning.checkcompatibility.label;"/> - </hbox> - <button class="button-link global-warning-checkcompatibility" - label="&warning.checkcompatibility.enable.label;" - tooltiptext="&warning.checkcompatibility.enable.tooltip;" - command="cmd_enableCheckCompatibility"/> - <hbox class="global-warning-updatesecurity" flex="1" align="center" - tooltiptext="&warning.updatesecurity.label;"> - <image class="warning-icon"/> - <label class="global-warning-text" flex="1" crop="end" - value="&warning.updatesecurity.label;"/> - </hbox> - <button class="button-link global-warning-updatesecurity" - label="&warning.updatesecurity.enable.label;" - tooltiptext="&warning.updatesecurity.enable.tooltip;" - command="cmd_enableUpdateSecurity"/> - <spacer flex="5000"/> <!-- Necessary to allow the message to wrap --> - </hbox> - </hbox> - <hbox class="view-header global-info-container experiment-info-container"> - <hbox class="global-info" flex="1" align="center"> - <label value="&experiment.info.label;"/> - <button id="experiments-learn-more" - label="&experiment.info.learnmore;" - tooltiptext="&experiment.info.learnmore;" - accesskey="&experiment.info.learnmore.accesskey;" - command="cmd_experimentsLearnMore"/> - <button id="experiments-change-telemetry" - label="&experiment.info.changetelemetry;" - tooltiptext="&experiment.info.changetelemetry;" - accesskey="&experiment.info.changetelemetry.accesskey;" - command="cmd_experimentsOpenTelemetryPreferences"/> - <spacer flex="5000"/> <!-- Necessary to allow the message to wrap. --> - </hbox> + <!-- updates view --> + <vbox id="updates-view" flex="1" class="view-pane" tabindex="0"> + <hbox class="view-header global-warning-container" align="center"> + <!-- global warnings --> + <hbox class="global-warning" flex="1"> + <hbox class="global-warning-safemode" flex="1" align="center" + tooltiptext="&warning.safemode.label;"> + <image class="warning-icon"/> + <label class="global-warning-text" flex="1" crop="end" + value="&warning.safemode.label;"/> </hbox> - <vbox id="addon-list-empty" class="alert-container" - flex="1" hidden="true"> - <spacer class="alert-spacer-before"/> - <vbox class="alert"> - <label value="&listEmpty.installed.label;"/> - <button class="discover-button" - id="discover-button-install" - label="&listEmpty.button.label;" - command="cmd_goToDiscoverPane"/> - </vbox> - <spacer class="alert-spacer-after"/> - </vbox> - <richlistbox id="addon-list" class="list" flex="1"/> - </vbox> - <!-- updates view --> - <vbox id="updates-view" flex="1" class="view-pane" tabindex="0"> - <hbox class="view-header global-warning-container" align="center"> - <!-- global warnings --> - <hbox class="global-warning" flex="1"> - <hbox class="global-warning-safemode" flex="1" align="center" - tooltiptext="&warning.safemode.label;"> - <image class="warning-icon"/> - <label class="global-warning-text" flex="1" crop="end" - value="&warning.safemode.label;"/> - </hbox> - <hbox class="global-warning-checkcompatibility" flex="1" align="center" - tooltiptext="&warning.checkcompatibility.label;"> - <image class="warning-icon"/> - <label class="global-warning-text" flex="1" crop="end" - value="&warning.checkcompatibility.label;"/> - </hbox> - <button class="button-link global-warning-checkcompatibility" - label="&warning.checkcompatibility.enable.label;" - tooltiptext="&warning.checkcompatibility.enable.tooltip;" - command="cmd_enableCheckCompatibility"/> - <hbox class="global-warning-updatesecurity" flex="1" align="center" - tooltiptext="&warning.updatesecurity.label;"> - <image class="warning-icon"/> - <label class="global-warning-text" flex="1" crop="end" - value="&warning.updatesecurity.label;"/> - </hbox> - <button class="button-link global-warning-updatesecurity" - label="&warning.updatesecurity.enable.label;" - tooltiptext="&warning.updatesecurity.enable.tooltip;" - command="cmd_enableUpdateSecurity"/> - <spacer flex="5000"/> <!-- Necessary to allow the message to wrap --> - </hbox> - <spacer flex="1"/> - <hbox id="updates-sorters" class="sort-controls" sortby="updateDate" - ascending="false"/> + <hbox class="global-warning-checkcompatibility" flex="1" align="center" + tooltiptext="&warning.checkcompatibility.label;"> + <image class="warning-icon"/> + <label class="global-warning-text" flex="1" crop="end" + value="&warning.checkcompatibility.label;"/> </hbox> - <vbox id="updates-list-empty" class="alert-container" - flex="1" hidden="true"> - <spacer class="alert-spacer-before"/> - <vbox class="alert"> - <label id="empty-availableUpdates-msg" value="&listEmpty.availableUpdates.label;"/> - <label id="empty-recentUpdates-msg" value="&listEmpty.recentUpdates.label;"/> - <button label="&listEmpty.findUpdates.label;" - command="cmd_findAllUpdates"/> - </vbox> - <spacer class="alert-spacer-after"/> - </vbox> - <hbox id="update-actions" pack="center"> - <button id="update-selected-btn" hidden="true" - label="&updates.updateSelected.label;" - tooltiptext="&updates.updateSelected.tooltip;"/> + <button class="button-link global-warning-checkcompatibility" + label="&warning.checkcompatibility.enable.label;" + tooltiptext="&warning.checkcompatibility.enable.tooltip;" + command="cmd_enableCheckCompatibility"/> + <hbox class="global-warning-updatesecurity" flex="1" align="center" + tooltiptext="&warning.updatesecurity.label;"> + <image class="warning-icon"/> + <label class="global-warning-text" flex="1" crop="end" + value="&warning.updatesecurity.label;"/> </hbox> - <richlistbox id="updates-list" class="list" flex="1"/> + <button class="button-link global-warning-updatesecurity" + label="&warning.updatesecurity.enable.label;" + tooltiptext="&warning.updatesecurity.enable.tooltip;" + command="cmd_enableUpdateSecurity"/> + <spacer flex="5000"/> <!-- Necessary to allow the message to wrap --> + </hbox> + <spacer flex="1"/> + <hbox id="updates-sorters" class="sort-controls" sortby="updateDate" + ascending="false"/> + </hbox> + <vbox id="updates-list-empty" class="alert-container" + flex="1" hidden="true"> + <spacer class="alert-spacer-before"/> + <vbox class="alert"> + <label id="empty-availableUpdates-msg" value="&listEmpty.availableUpdates.label;"/> + <label id="empty-recentUpdates-msg" value="&listEmpty.recentUpdates.label;"/> + <button label="&listEmpty.findUpdates.label;" + command="cmd_findAllUpdates"/> </vbox> + <spacer class="alert-spacer-after"/> + </vbox> + <hbox id="update-actions" pack="center"> + <button id="update-selected-btn" hidden="true" + label="&updates.updateSelected.label;" + tooltiptext="&updates.updateSelected.tooltip;"/> + </hbox> + <richlistbox id="updates-list" class="list" flex="1"/> + </vbox> - <!-- detail view --> - <scrollbox id="detail-view" flex="1" class="view-pane addon-view" orient="vertical" tabindex="0" - role="document"> - <!-- global warnings --> - <hbox class="global-warning-container global-warning"> - <hbox class="global-warning-safemode" flex="1" align="center" - tooltiptext="&warning.safemode.label;"> + <!-- detail view --> + <scrollbox id="detail-view" flex="1" class="view-pane addon-view" orient="vertical" tabindex="0" + role="document"> + <!-- global warnings --> + <hbox class="global-warning-container global-warning"> + <hbox class="global-warning-safemode" flex="1" align="center" + tooltiptext="&warning.safemode.label;"> + <image class="warning-icon"/> + <label class="global-warning-text" flex="1" crop="end" + value="&warning.safemode.label;"/> + </hbox> + <hbox class="global-warning-checkcompatibility" flex="1" align="center" + tooltiptext="&warning.checkcompatibility.label;"> + <image class="warning-icon"/> + <label class="global-warning-text" flex="1" crop="end" + value="&warning.checkcompatibility.label;"/> + </hbox> + <button class="button-link global-warning-checkcompatibility" + label="&warning.checkcompatibility.enable.label;" + tooltiptext="&warning.checkcompatibility.enable.tooltip;" + command="cmd_enableCheckCompatibility"/> + <hbox class="global-warning-updatesecurity" flex="1" align="center" + tooltiptext="&warning.updatesecurity.label;"> + <image class="warning-icon"/> + <label class="global-warning-text" flex="1" crop="end" + value="&warning.updatesecurity.label;"/> + </hbox> + <button class="button-link global-warning-updatesecurity" + label="&warning.updatesecurity.enable.label;" + tooltiptext="&warning.updatesecurity.enable.tooltip;" + command="cmd_enableUpdateSecurity"/> + <spacer flex="5000"/> <!-- Necessary to allow the message to wrap --> + </hbox> + <hbox flex="1"> + <spacer flex="1"/> + <!-- "loading" splash screen --> + <vbox class="alert-container"> + <spacer class="alert-spacer-before"/> + <hbox class="alert loading"> + <image/> + <label value="&loading.label;"/> + </hbox> + <spacer class="alert-spacer-after"/> + </vbox> + <!-- actual detail view --> + <vbox class="detail-view-container" flex="3" contextmenu="addonitem-popup"> + <vbox id="detail-notifications"> + <hbox id="warning-container" align="center" class="warning"> <image class="warning-icon"/> - <label class="global-warning-text" flex="1" crop="end" - value="&warning.safemode.label;"/> + <label id="detail-warning" flex="1"/> + <label id="detail-warning-link" class="text-link"/> + <spacer flex="5000"/> <!-- Necessary to allow the message to wrap --> </hbox> - <hbox class="global-warning-checkcompatibility" flex="1" align="center" - tooltiptext="&warning.checkcompatibility.label;"> - <image class="warning-icon"/> - <label class="global-warning-text" flex="1" crop="end" - value="&warning.checkcompatibility.label;"/> + <hbox id="error-container" align="center" class="error"> + <image class="error-icon"/> + <label id="detail-error" flex="1"/> + <label id="detail-error-link" class="text-link"/> + <spacer flex="5000"/> <!-- Necessary to allow the message to wrap --> </hbox> - <button class="button-link global-warning-checkcompatibility" - label="&warning.checkcompatibility.enable.label;" - tooltiptext="&warning.checkcompatibility.enable.tooltip;" - command="cmd_enableCheckCompatibility"/> - <hbox class="global-warning-updatesecurity" flex="1" align="center" - tooltiptext="&warning.updatesecurity.label;"> - <image class="warning-icon"/> - <label class="global-warning-text" flex="1" crop="end" - value="&warning.updatesecurity.label;"/> + <hbox id="pending-container" align="center" class="pending"> + <image class="pending-icon"/> + <label id="detail-pending" flex="1"/> + <button id="detail-restart-btn" class="button-link" + label="&addon.restartNow.label;" + command="cmd_restartApp"/> + <button id="detail-undo-btn" class="button-link" + label="&addon.undoAction.label;" + tooltipText="&addon.undoAction.tooltip;" + command="cmd_cancelOperation"/> + <spacer flex="5000"/> <!-- Necessary to allow the message to wrap --> </hbox> - <button class="button-link global-warning-updatesecurity" - label="&warning.updatesecurity.enable.label;" - tooltiptext="&warning.updatesecurity.enable.tooltip;" - command="cmd_enableUpdateSecurity"/> - <spacer flex="5000"/> <!-- Necessary to allow the message to wrap --> - </hbox> - <hbox flex="1"> - <spacer flex="1"/> - <!-- "loading" splash screen --> - <vbox class="alert-container"> - <spacer class="alert-spacer-before"/> - <hbox class="alert loading"> - <image/> - <label value="&loading.label;"/> - </hbox> - <spacer class="alert-spacer-after"/> + </vbox> + <hbox align="start"> + <vbox id="detail-icon-container" align="end"> + <image id="detail-icon" class="icon"/> </vbox> - <!-- actual detail view --> - <vbox class="detail-view-container" flex="3" contextmenu="addonitem-popup"> - <vbox id="detail-notifications"> - <hbox id="warning-container" align="center" class="warning"> - <image class="warning-icon"/> - <label id="detail-warning" flex="1"/> - <label id="detail-warning-link" class="text-link"/> - <spacer flex="5000"/> <!-- Necessary to allow the message to wrap --> - </hbox> - <hbox id="error-container" align="center" class="error"> - <image class="error-icon"/> - <label id="detail-error" flex="1"/> - <label id="detail-error-link" class="text-link"/> - <spacer flex="5000"/> <!-- Necessary to allow the message to wrap --> - </hbox> - <hbox id="pending-container" align="center" class="pending"> - <image class="pending-icon"/> - <label id="detail-pending" flex="1"/> - <button id="detail-restart-btn" class="button-link" - label="&addon.restartNow.label;" - command="cmd_restartApp"/> - <button id="detail-undo-btn" class="button-link" - label="&addon.undoAction.label;" - tooltipText="&addon.undoAction.tooltip;" - command="cmd_cancelOperation"/> - <spacer flex="5000"/> <!-- Necessary to allow the message to wrap --> + <vbox flex="1"> + <vbox id="detail-summary"> + <hbox id="detail-name-container" class="name-container" + align="start"> + <label id="detail-name" flex="1"/> + <label id="detail-version"/> + <label class="disabled-postfix" value="&addon.disabled.postfix;"/> + <label class="update-postfix" value="&addon.update.postfix;"/> + <spacer flex="5000"/> <!-- Necessary to allow the name to wrap --> </hbox> + <label id="detail-creator" class="creator"/> + <label id="detail-translators" class="translators"/> </vbox> - <hbox align="start"> - <vbox id="detail-icon-container" align="end"> - <image id="detail-icon" class="icon"/> + <hbox id="detail-experiment-container"> + <svg width="8" height="8" viewBox="0 0 8 8" version="1.1" + xmlns="http://www.w3.org/2000/svg" + id="detail-experiment-bullet-container"> + <circle cx="4" cy="4" r="4" id="detail-experiment-bullet"/> + </svg> + <label id="detail-experiment-state"/> + <label id="detail-experiment-time"/> + </hbox> + <hbox id="detail-desc-container" align="start"> + <vbox pack="center"> <!-- Necessary to work around bug 394738 --> + <image id="detail-screenshot" hidden="true"/> </vbox> <vbox flex="1"> - <vbox id="detail-summary"> - <hbox id="detail-name-container" class="name-container" - align="start"> - <label id="detail-name" flex="1"/> - <label id="detail-version"/> - <label class="disabled-postfix" value="&addon.disabled.postfix;"/> - <label class="update-postfix" value="&addon.update.postfix;"/> - <spacer flex="5000"/> <!-- Necessary to allow the name to wrap --> - </hbox> - <label id="detail-creator" class="creator"/> - </vbox> - <hbox id="detail-experiment-container"> - <svg width="8" height="8" viewBox="0 0 8 8" version="1.1" - xmlns="http://www.w3.org/2000/svg" - id="detail-experiment-bullet-container"> - <circle cx="4" cy="4" r="4" id="detail-experiment-bullet"/> - </svg> - <label id="detail-experiment-state"/> - <label id="detail-experiment-time"/> - </hbox> - <hbox id="detail-desc-container" align="start"> - <vbox id="detail-screenshot-box" pack="center" hidden="true"> <!-- Necessary to work around bug 394738 --> - <image id="detail-screenshot"/> - </vbox> - <vbox flex="1"> - <description id="detail-desc"/> - <description id="detail-fulldesc"/> - </vbox> - </hbox> - <vbox id="detail-contributions"> - <description id="detail-contrib-description"> - &detail.contributions.description; - </description> + <description id="detail-desc"/> + <description id="detail-fulldesc"/> + </vbox> + </hbox> + <vbox id="detail-contributions"> + <description id="detail-contrib-description"> + &detail.contributions.description; + </description> + <hbox align="center"> + <label id="detail-contrib-suggested"/> + <spacer flex="1"/> + <button id="detail-contrib-btn" + label="&cmd.contribute.label;" + accesskey="&cmd.contribute.accesskey;" + tooltiptext="&cmd.contribute.tooltip;" + command="cmd_contribute"/> + </hbox> + </vbox> + <grid id="detail-grid"> + <columns> + <column flex="1"/> + <column flex="2"/> + </columns> + <rows id="detail-rows"> + <row class="detail-row-complex" id="detail-updates-row"> + <label class="detail-row-label" value="&detail.updateType;"/> <hbox align="center"> - <label id="detail-contrib-suggested"/> - <spacer flex="1"/> - <button id="detail-contrib-btn" - label="&cmd.contribute.label;" - accesskey="&cmd.contribute.accesskey;" - tooltiptext="&cmd.contribute.tooltip;" - command="cmd_contribute"/> + <radiogroup id="detail-autoUpdate" orient="horizontal"> + <!-- The values here need to match the values of + AddonManager.AUTOUPDATE_* --> + <radio label="&detail.updateDefault.label;" + tooltiptext="&detail.updateDefault.tooltip;" + value="1"/> + <radio label="&detail.updateAutomatic.label;" + tooltiptext="&detail.updateAutomatic.tooltip;" + value="2"/> + <radio label="&detail.updateManual.label;" + tooltiptext="&detail.updateManual.tooltip;" + value="0"/> + </radiogroup> + <button id="detail-findUpdates-btn" class="button-link" + label="&detail.checkForUpdates.label;" + accesskey="&detail.checkForUpdates.accesskey;" + tooltiptext="&detail.checkForUpdates.tooltip;" + command="cmd_findItemUpdates"/> </hbox> - </vbox> - <grid id="detail-grid"> - <columns> - <column flex="1"/> - <column flex="2"/> - </columns> - <rows id="detail-rows"> - <row class="detail-row-complex" id="detail-updates-row"> - <label class="detail-row-label" value="&detail.updateType;"/> - <hbox align="center"> - <radiogroup id="detail-autoUpdate" orient="horizontal"> - <!-- The values here need to match the values of - AddonManager.AUTOUPDATE_* --> - <radio label="&detail.updateDefault.label;" - tooltiptext="&detail.updateDefault.tooltip;" - value="1"/> - <radio label="&detail.updateAutomatic.label;" - tooltiptext="&detail.updateAutomatic.tooltip;" - value="2"/> - <radio label="&detail.updateManual.label;" - tooltiptext="&detail.updateManual.tooltip;" - value="0"/> - </radiogroup> - <button id="detail-findUpdates-btn" class="button-link" - label="&detail.checkForUpdates.label;" - accesskey="&detail.checkForUpdates.accesskey;" - tooltiptext="&detail.checkForUpdates.tooltip;" - command="cmd_findItemUpdates"/> - </hbox> - </row> - <row class="detail-row" id="detail-dateUpdated" label="&detail.lastupdated.label;"/> - <row class="detail-row-complex" id="detail-homepage-row" label="&detail.home;"> - <label class="detail-row-label" value="&detail.home;"/> - <label id="detail-homepage" class="detail-row-value text-link" crop="end"/> - </row> - <row class="detail-row-complex" id="detail-repository-row" label="&detail.repository;"> - <label class="detail-row-label" value="&detail.repository;"/> - <label id="detail-repository" class="detail-row-value text-link"/> - </row> - <row class="detail-row" id="detail-size" label="&detail.size;"/> - <row class="detail-row-complex" id="detail-rating-row"> - <label class="detail-row-label" value="&rating2.label;"/> - <hbox> - <label id="detail-rating" class="meta-value meta-rating" - showrating="average"/> - <label id="detail-reviews" class="text-link"/> - </hbox> - </row> - <row class="detail-row" id="detail-downloads" label="&detail.numberOfDownloads.label;"/> - </rows> - </grid> - <hbox id="detail-controls"> - <button id="detail-prefs-btn" class="addon-control preferences" + </row> + <row class="detail-row" id="detail-dateUpdated" label="&detail.lastupdated.label;"/> + <row class="detail-row-complex" id="detail-homepage-row" label="&detail.home;"> + <label class="detail-row-label" value="&detail.home;"/> + <label id="detail-homepage" class="detail-row-value text-link" crop="end"/> + </row> + <row class="detail-row-complex" id="detail-repository-row" label="&detail.repository;"> + <label class="detail-row-label" value="&detail.repository;"/> + <label id="detail-repository" class="detail-row-value text-link"/> + </row> + <row class="detail-row" id="detail-size" label="&detail.size;"/> + <row class="detail-row-complex" id="detail-rating-row"> + <label class="detail-row-label" value="&rating2.label;"/> + <hbox> + <label id="detail-rating" class="meta-value meta-rating" + showrating="average"/> + <label id="detail-reviews" class="text-link"/> + </hbox> + </row> + <row class="detail-row" id="detail-downloads" label="&detail.numberOfDownloads.label;"/> + </rows> + </grid> + <hbox id="detail-controls"> + <button id="detail-prefs-btn" class="addon-control preferences" #ifdef XP_WIN - label="&detail.showPreferencesWin.label;" - accesskey="&detail.showPreferencesWin.accesskey;" - tooltiptext="&detail.showPreferencesWin.tooltip;" + label="&detail.showPreferencesWin.label;" + accesskey="&detail.showPreferencesWin.accesskey;" + tooltiptext="&detail.showPreferencesWin.tooltip;" #else - label="&detail.showPreferencesUnix.label;" - accesskey="&detail.showPreferencesUnix.accesskey;" - tooltiptext="&detail.showPreferencesUnix.tooltip;" + label="&detail.showPreferencesUnix.label;" + accesskey="&detail.showPreferencesUnix.accesskey;" + tooltiptext="&detail.showPreferencesUnix.tooltip;" #endif - command="cmd_showItemPreferences"/> - <spacer flex="1"/> - <button id="detail-enable-btn" class="addon-control enable" - label="&cmd.enableAddon.label;" - accesskey="&cmd.enableAddon.accesskey;" - command="cmd_enableItem"/> - <button id="detail-disable-btn" class="addon-control disable" - label="&cmd.disableAddon.label;" - accesskey="&cmd.disableAddon.accesskey;" - command="cmd_disableItem"/> - <button id="detail-uninstall-btn" class="addon-control remove" - label="&cmd.uninstallAddon.label;" - accesskey="&cmd.uninstallAddon.accesskey;" - command="cmd_uninstallItem"/> - <button id="detail-purchase-btn" class="addon-control purchase" - command="cmd_purchaseItem"/> - <button id="detail-install-btn" class="addon-control install" - label="&cmd.installAddon.label;" - accesskey="&cmd.installAddon.accesskey;" - command="cmd_installItem"/> - <menulist id="detail-state-menulist" - crop="none" sizetopopup="always" - tooltiptext="&cmd.stateMenu.tooltip;"> - <menupopup> - <menuitem id="detail-ask-to-activate-menuitem" - class="addon-control" - label="&cmd.askToActivate.label;" - tooltiptext="&cmd.askToActivate.tooltip;" - command="cmd_askToActivateItem"/> - <menuitem id="detail-always-activate-menuitem" - class="addon-control" - label="&cmd.alwaysActivate.label;" - tooltiptext="&cmd.alwaysActivate.tooltip;" - command="cmd_alwaysActivateItem"/> - <menuitem id="detail-never-activate-menuitem" - class="addon-control" - label="&cmd.neverActivate.label;" - tooltiptext="&cmd.neverActivate.tooltip;" - command="cmd_neverActivateItem"/> - </menupopup> - </menulist> - </hbox> - </vbox> + command="cmd_showItemPreferences"/> + <spacer flex="1"/> + <button id="detail-debug-btn" class="addon-control debug" + label="Debug" + command="cmd_debugItem" /> + <button id="detail-enable-btn" class="addon-control enable" + label="&cmd.enableAddon.label;" + accesskey="&cmd.enableAddon.accesskey;" + command="cmd_enableItem"/> + <button id="detail-disable-btn" class="addon-control disable" + label="&cmd.disableAddon.label;" + accesskey="&cmd.disableAddon.accesskey;" + command="cmd_disableItem"/> + <button id="detail-uninstall-btn" class="addon-control remove" + label="&cmd.uninstallAddon.label;" + accesskey="&cmd.uninstallAddon.accesskey;" + command="cmd_uninstallItem"/> + <button id="detail-purchase-btn" class="addon-control purchase" + command="cmd_purchaseItem"/> + <button id="detail-install-btn" class="addon-control install" + label="&cmd.installAddon.label;" + accesskey="&cmd.installAddon.accesskey;" + command="cmd_installItem"/> + <menulist id="detail-state-menulist" + crop="none" sizetopopup="always" + tooltiptext="&cmd.stateMenu.tooltip;"> + <menupopup> + <menuitem id="detail-ask-to-activate-menuitem" + class="addon-control" + label="&cmd.askToActivate.label;" + tooltiptext="&cmd.askToActivate.tooltip;" + command="cmd_askToActivateItem"/> + <menuitem id="detail-always-activate-menuitem" + class="addon-control" + label="&cmd.alwaysActivate.label;" + tooltiptext="&cmd.alwaysActivate.tooltip;" + command="cmd_alwaysActivateItem"/> + <menuitem id="detail-never-activate-menuitem" + class="addon-control" + label="&cmd.neverActivate.label;" + tooltiptext="&cmd.neverActivate.tooltip;" + command="cmd_neverActivateItem"/> + </menupopup> + </menulist> </hbox> </vbox> - <spacer flex="1"/> </hbox> - </scrollbox> - </deck> - </vbox> + </vbox> + <spacer flex="1"/> + </hbox> + </scrollbox> + </deck> - </vbox> + + </box> </hbox> + </page> diff --git a/toolkit/mozapps/extensions/content/list.js b/toolkit/mozapps/extensions/content/list.js index a31922703..aac87911e 100644 --- a/toolkit/mozapps/extensions/content/list.js +++ b/toolkit/mozapps/extensions/content/list.js @@ -16,11 +16,11 @@ const kDialog = "dialog"; * caller can inspect the user action after the dialog closes by inspecting the * value of the |result| parameter on this object which is set to the dlgtype * of the button used to close the dialog. - * + * * window.arguments[0] is an array of strings to display in the tree. If the * array is empty the tree will not be displayed. * window.arguments[1] a JS Object with the following properties: - * + * * title: A title string, to be displayed in the title bar of the dialog. * message1: A message string, displayed above the addon list * message2: A message string, displayed below the addon list @@ -39,7 +39,7 @@ const kDialog = "dialog"; * ... * }, * - * result: The dlgtype of button that was used to dismiss the dialog. + * result: The dlgtype of button that was used to dismiss the dialog. */ "use strict"; @@ -113,7 +113,7 @@ function init() { message.appendChild(document.createTextNode(params[messageEntry])); } } - + document.getElementById("infoIcon").className = params["iconClass"] ? "spaced " + params["iconClass"] : "spaced alert-icon"; diff --git a/toolkit/mozapps/extensions/content/newaddon.js b/toolkit/mozapps/extensions/content/newaddon.js index b1ad5631b..2b2a54af5 100644 --- a/toolkit/mozapps/extensions/content/newaddon.js +++ b/toolkit/mozapps/extensions/content/newaddon.js @@ -2,9 +2,9 @@ * 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/. */ -var Cc = Components.classes; -var Ci = Components.interfaces; -var Cu = Components.utils; +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cu = Components.utils; Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/AddonManager.jsm"); @@ -13,7 +13,7 @@ var gAddon = null; // If the user enables the add-on through some other UI close this window var EnableListener = { - onEnabling: function(aAddon) { + onEnabling: function EnableListener_onEnabling(aAddon) { if (aAddon.id == gAddon.id) window.close(); } @@ -38,11 +38,11 @@ function initialize() { let bundle = Services.strings.createBundle("chrome://mozapps/locale/extensions/newaddon.properties"); - AddonManager.getAddonByID(id, function(aAddon) { - // If the add-on doesn't exist or it is already enabled or it has already - // been seen or it cannot be enabled then this UI is useless, just close it. - // This shouldn't normally happen unless session restore restores the tab. - if (!aAddon || !aAddon.userDisabled || aAddon.seen || + AddonManager.getAddonByID(id, function initialize_getAddonByID(aAddon) { + // If the add-on doesn't exist or it is already enabled or it cannot be + // enabled then this UI is useless, just close it. This shouldn't normally + // happen unless session restore restores the tab + if (!aAddon || !aAddon.userDisabled || !(aAddon.permissions & AddonManager.PERM_CAN_ENABLE)) { window.close(); return; @@ -79,14 +79,6 @@ function initialize() { document.getElementById("location").hidden = true; } - // Only mark the add-on as seen if the page actually gets focus - if (document.hasFocus()) { - aAddon.markAsSeen(); - } - else { - document.addEventListener("focus", () => aAddon.markAsSeen(), false); - } - var event = document.createEvent("Events"); event.initEvent("AddonDisplayed", true, true); document.dispatchEvent(event); diff --git a/toolkit/mozapps/extensions/content/newaddon.xul b/toolkit/mozapps/extensions/content/newaddon.xul index 1d8545249..0806f2799 100644 --- a/toolkit/mozapps/extensions/content/newaddon.xul +++ b/toolkit/mozapps/extensions/content/newaddon.xul @@ -52,13 +52,12 @@ <button id="continue-button" label="&continue;" oncommand="continueClicked()"/> </hbox> - <vbox id="restartPanel"> - <description id="restartMessage">&restartMessage;</description> - <hbox id="restartPanelButtons"> - <button id="restart-button" label="&restartButton;" oncommand="restartClicked()"/> - <button id="cancel-button" label="&cancelButton;" oncommand="cancelClicked()"/> - </hbox> - </vbox> + <hbox id="restartPanel"> + <spacer id="restartSpacer"/> + <description id="restartMessage" flex="1">&restartMessage;</description> + <button id="restart-button" label="&restartButton;" oncommand="restartClicked()"/> + <button id="cancel-button" label="&cancelButton;" oncommand="cancelClicked()"/> + </hbox> </deck> </vbox> diff --git a/toolkit/mozapps/extensions/content/selectAddons.css b/toolkit/mozapps/extensions/content/selectAddons.css new file mode 100644 index 000000000..636757721 --- /dev/null +++ b/toolkit/mozapps/extensions/content/selectAddons.css @@ -0,0 +1,22 @@ +/* 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/. */ + +#select .addon { + -moz-binding: url("chrome://mozapps/content/extensions/selectAddons.xml#addon-select"); +} + +#confirm .addon { + -moz-binding: url("chrome://mozapps/content/extensions/selectAddons.xml#addon-confirm"); +} + +#select-scrollbox, +#confirm-scrollbox { + overflow-y: auto; + -moz-box-orient: vertical; +} + +.addon:not([optionalupdate]) .addon-action-update, +.addon[optionalupdate] .addon-action-message { + display: none; +} diff --git a/toolkit/mozapps/extensions/content/selectAddons.js b/toolkit/mozapps/extensions/content/selectAddons.js new file mode 100644 index 000000000..f80932b3f --- /dev/null +++ b/toolkit/mozapps/extensions/content/selectAddons.js @@ -0,0 +1,347 @@ +// -*- 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/. */ + +"use strict"; + +Components.utils.import("resource://gre/modules/AddonManager.jsm"); +Components.utils.import("resource://gre/modules/addons/AddonRepository.jsm"); +Components.utils.import("resource://gre/modules/Services.jsm"); + +const Cc = Components.classes; +const Ci = Components.interfaces; + +var gView = null; + +function showView(aView) { + gView = aView; + + gView.show(); + + // If the view's show method immediately showed a different view then don't + // do anything else + if (gView != aView) + return; + + let viewNode = document.getElementById(gView.nodeID); + viewNode.parentNode.selectedPanel = viewNode; + + // For testing dispatch an event when the view changes + var event = document.createEvent("Events"); + event.initEvent("ViewChanged", true, true); + viewNode.dispatchEvent(event); +} + +function showButtons(aCancel, aBack, aNext, aDone) { + document.getElementById("cancel").hidden = !aCancel; + document.getElementById("back").hidden = !aBack; + document.getElementById("next").hidden = !aNext; + document.getElementById("done").hidden = !aDone; +} + +function isAddonDistroInstalled(aID) { + let branch = Services.prefs.getBranch("extensions.installedDistroAddon."); + if (!branch.prefHasUserValue(aID)) + return false; + + return branch.getBoolPref(aID); +} + +function orderForScope(aScope) { + return aScope == AddonManager.SCOPE_PROFILE ? 1 : 0; +} + +var gAddons = {}; + +var gChecking = { + nodeID: "checking", + + _progress: null, + _addonCount: 0, + _completeCount: 0, + + show: function gChecking_show() { + showButtons(true, false, false, false); + this._progress = document.getElementById("checking-progress"); + + AddonManager.getAllAddons(aAddons => { + if (aAddons.length == 0) { + window.close(); + return; + } + + aAddons = aAddons.filter(function gChecking_filterAddons(aAddon) { + if (aAddon.type == "plugin" || aAddon.type == "service") + return false; + + if (aAddon.type == "theme") { + // Don't show application shipped themes + if (aAddon.scope == AddonManager.SCOPE_APPLICATION) + return false; + // Don't show already disabled themes + if (aAddon.userDisabled) + return false; + } + + return true; + }); + + this._addonCount = aAddons.length; + this._progress.value = 0; + this._progress.max = aAddons.length; + this._progress.mode = "determined"; + + AddonRepository.repopulateCache().then(() => { + for (let addonItem of aAddons) { + // Ignore disabled themes + if (addonItem.type != "theme" || !addonItem.userDisabled) { + gAddons[addonItem.id] = { + addon: addonItem, + install: null, + wasActive: addonItem.isActive + } + } + + addonItem.findUpdates(this, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED); + } + }); + }); + }, + + onUpdateAvailable: function gChecking_onUpdateAvailable(aAddon, aInstall) { + // If the add-on can be upgraded then remember the new version + if (aAddon.permissions & AddonManager.PERM_CAN_UPGRADE) + gAddons[aAddon.id].install = aInstall; + }, + + onUpdateFinished: function gChecking_onUpdateFinished(aAddon, aError) { + this._completeCount++; + this._progress.value = this._completeCount; + + if (this._completeCount < this._addonCount) + return; + + // Tycho: var addons = [gAddons[id] for (id in gAddons)]; + var addons = []; + for (let id in gAddons) { + addons.push(gAddons[id]) + } + + addons.sort(function sortAddons(a, b) { + let orderA = orderForScope(a.addon.scope); + let orderB = orderForScope(b.addon.scope); + + if (orderA != orderB) + return orderA - orderB; + + return String.localeCompare(a.addon.name, b.addon.name); + }); + + let rows = document.getElementById("select-rows"); + let lastAddon = null; + for (let entry of addons) { + if (lastAddon && + orderForScope(entry.addon.scope) != orderForScope(lastAddon.scope)) { + let separator = document.createElement("separator"); + rows.appendChild(separator); + } + + let row = document.createElement("row"); + row.setAttribute("id", entry.addon.id); + row.setAttribute("class", "addon"); + rows.appendChild(row); + row.setAddon(entry.addon, entry.install, entry.wasActive, + isAddonDistroInstalled(entry.addon.id)); + + if (entry.install) + entry.install.addListener(gUpdate); + + lastAddon = entry.addon; + } + + showView(gSelect); + } +}; + +var gSelect = { + nodeID: "select", + + show: function gSelect_show() { + this.updateButtons(); + }, + + updateButtons: function gSelect_updateButtons() { + for (let row = document.getElementById("select-rows").firstChild; + row; row = row.nextSibling) { + if (row.localName == "separator") + continue; + + if (row.action) { + showButtons(false, false, true, false); + return; + } + } + + showButtons(false, false, false, true); + }, + + next: function gSelect_next() { + showView(gConfirm); + }, + + done: function gSelect_done() { + window.close(); + } +}; + +var gConfirm = { + nodeID: "confirm", + + show: function gConfirm_show() { + showButtons(false, true, false, true); + + let box = document.getElementById("confirm-scrollbox").firstChild; + while (box) { + box.hidden = true; + while (box.lastChild != box.firstChild) + box.removeChild(box.lastChild); + box = box.nextSibling; + } + + for (let row = document.getElementById("select-rows").firstChild; + row; row = row.nextSibling) { + if (row.localName == "separator") + continue; + + let action = row.action; + if (!action) + continue; + + let list = document.getElementById(action + "-list"); + + list.hidden = false; + let item = document.createElement("hbox"); + item.setAttribute("id", row._addon.id); + item.setAttribute("class", "addon"); + item.setAttribute("type", row._addon.type); + item.setAttribute("name", row._addon.name); + if (action == "update" || action == "enable") + item.setAttribute("active", "true"); + list.appendChild(item); + + if (action == "update") + showButtons(false, true, true, false); + } + }, + + back: function gConfirm_back() { + showView(gSelect); + }, + + next: function gConfirm_next() { + showView(gUpdate); + }, + + done: function gConfirm_done() { + for (let row = document.getElementById("select-rows").firstChild; + row; row = row.nextSibling) { + if (row.localName != "separator") + row.apply(); + } + + window.close(); + } +} + +var gUpdate = { + nodeID: "update", + + _progress: null, + _waitingCount: 0, + _completeCount: 0, + _errorCount: 0, + + show: function gUpdate_show() { + showButtons(true, false, false, false); + + this._progress = document.getElementById("update-progress"); + + for (let row = document.getElementById("select-rows").firstChild; + row; row = row.nextSibling) { + if (row.localName != "separator") + row.apply(); + } + + this._progress.mode = "determined"; + this._progress.max = this._waitingCount; + this._progress.value = this._completeCount; + }, + + checkComplete: function gUpdate_checkComplete() { + this._progress.value = this._completeCount; + if (this._completeCount < this._waitingCount) + return; + + if (this._errorCount > 0) { + showView(gErrors); + return; + } + + window.close(); + }, + + onDownloadStarted: function gUpdate_onDownloadStarted(aInstall) { + this._waitingCount++; + }, + + onDownloadFailed: function gUpdate_onDownloadFailed(aInstall) { + this._errorCount++; + this._completeCount++; + this.checkComplete(); + }, + + onInstallFailed: function gUpdate_onInstallFailed(aInstall) { + this._errorCount++; + this._completeCount++; + this.checkComplete(); + }, + + onInstallEnded: function gUpdate_onInstallEnded(aInstall) { + this._completeCount++; + this.checkComplete(); + } +}; + +var gErrors = { + nodeID: "errors", + + show: function gErrors_show() { + showButtons(false, false, false, true); + }, + + done: function gErrors_done() { + window.close(); + } +}; + +window.addEventListener("load", function loadEventListener() { + showView(gChecking); }, false); + +// When closing the window cancel any pending or in-progress installs +window.addEventListener("unload", function unloadEventListener() { + for (let id in gAddons) { + let entry = gAddons[id]; + if (!entry.install) + return; + + aEntry.install.removeListener(gUpdate); + + if (entry.install.state != AddonManager.STATE_INSTALLED && + entry.install.state != AddonManager.STATE_DOWNLOAD_FAILED && + entry.install.state != AddonManager.STATE_INSTALL_FAILED) { + entry.install.cancel(); + } + } +}, false); diff --git a/toolkit/mozapps/extensions/content/selectAddons.xml b/toolkit/mozapps/extensions/content/selectAddons.xml new file mode 100644 index 000000000..dbfc0d400 --- /dev/null +++ b/toolkit/mozapps/extensions/content/selectAddons.xml @@ -0,0 +1,235 @@ +<?xml version="1.0"?> + +<!-- 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/. --> + +<!DOCTYPE window [ +<!ENTITY % updateDTD SYSTEM "chrome://mozapps/locale/extensions/selectAddons.dtd"> +<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd"> +%updateDTD; +%brandDTD; +]> + +<bindings xmlns="http://www.mozilla.org/xbl" + xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + xmlns:xbl="http://www.mozilla.org/xbl"> + + <binding id="addon-select"> + <content> + <xul:hbox class="select-keep select-cell"> + <xul:checkbox class="addon-keep-checkbox" anonid="keep" + xbl:inherits="tooltiptext=name" + oncommand="document.getBindingParent(this).keepChanged();"/> + </xul:hbox> + <xul:hbox class="select-icon select-cell"> + <xul:image class="addon-icon" xbl:inherits="type"/> + </xul:hbox> + <xul:hbox class="select-name select-cell"> + <xul:label class="addon-name" crop="end" style="&select.name.style;" + xbl:inherits="xbl:text=name"/> + </xul:hbox> + <xul:hbox class="select-action select-cell"> + <xul:label class="addon-action-message" style="&select.action.style;" + xbl:inherits="xbl:text=action"/> + <xul:checkbox anonid="update" checked="true" class="addon-action-update" + oncommand="document.getBindingParent(this).updateChanged();" + style="&select.action.style;" xbl:inherits="label=action"/> + </xul:hbox> + <xul:hbox class="select-source select-cell"> + <xul:label class="addon-source" xbl:inherits="xbl:text=source"/> + </xul:hbox> + </content> + + <implementation> + <field name="_addon"/> + <field name="_disabled"/> + <field name="_install"/> + <field name="_wasActive"/> + <field name="_keep">document.getAnonymousElementByAttribute(this, "anonid", "keep");</field> + <field name="_update">document.getAnonymousElementByAttribute(this, "anonid", "update");</field> + <field name="_strings">document.getElementById("strings");</field> + + <property name="action" readonly="true"> + <getter><![CDATA[ + if (!this._keep.checked) { + if (this._wasActive) + return "disable"; + else + return null; + } + + if (this._addon.appDisabled && !this._install) + return "incompatible"; + + if (this._install && (AddonManager.shouldAutoUpdate(this._addon) || this._update.checked)) + return "update"; + + if (this._addon.permissions & AddonManager.PERM_CAN_ENABLE) + return "enable"; + + return null; + ]]></getter> + </property> + + <method name="setAddon"> + <parameter name="aAddon"/> + <parameter name="aInstall"/> + <parameter name="aWasActive"/> + <parameter name="aDistroInstalled"/> + <body><![CDATA[ + this._addon = aAddon; + this._install = aInstall; + this._wasActive = aWasActive; + + this.setAttribute("name", aAddon.name); + this.setAttribute("type", aAddon.type); + + // User and bundled add-ons default to staying enabled, + // others default to disabled. + switch (aAddon.scope) { + case AddonManager.SCOPE_PROFILE: + this._keep.checked = !aAddon.userDisabled; + if (aDistroInstalled) + this.setAttribute("source", this._strings.getString("source.bundled")); + else + this.setAttribute("source", this._strings.getString("source.profile")); + break; + default: + this._keep.checked = false; + this.setAttribute("source", this._strings.getString("source.other")); + } + + this.updateAction(); + ]]></body> + </method> + + <method name="setActionMessage"> + <body><![CDATA[ + if (!this._keep.checked) { + // If the user no longer wants this add-on then it is either being + // disabled or nothing is changing. Don't complicate matters by + // talking about updates for this case + + if (this._wasActive) + this.setAttribute("action", this._strings.getString("action.disabled")); + else + this.setAttribute("action", ""); + + this.removeAttribute("optionalupdate"); + return; + } + + if (this._addon.appDisabled && !this._install) { + // If the add-on is incompatible and there is no update available + // then it will remain disabled + + this.setAttribute("action", this._strings.getString("action.incompatible")); + + this.removeAttribute("optionalupdate"); + return; + } + + if (this._install) { + if (!AddonManager.shouldAutoUpdate(this._addon)) { + this.setAttribute("optionalupdate", "true"); + + // If manual updating for the add-on then display the right + // text depending on whether the update is required to make + // the add-on work or not + if (this._addon.appDisabled) + this.setAttribute("action", this._strings.getString("action.neededupdate")); + else + this.setAttribute("action", this._strings.getString("action.unneededupdate")); + return; + } + + this.removeAttribute("optionalupdate"); + + // If the update is needed to make the add-on compatible then + // say so otherwise just say nothing about it + if (this._addon.appDisabled) { + this.setAttribute("action", this._strings.getString("action.autoupdate")); + return; + } + } + else { + this.removeAttribute("optionalupdate"); + } + + // If the add-on didn't used to be active and it now is (via a + // compatibility update) or it can be enabled then the action is to + // enable the add-on + if (!this._wasActive && (this._addon.isActive || this._addon.permissions & AddonManager.PERM_CAN_ENABLE)) { + this.setAttribute("action", this._strings.getString("action.enabled")); + return; + } + + // In all other cases the add-on is simply remaining enabled + this.setAttribute("action", ""); + ]]></body> + </method> + + <method name="updateAction"> + <body><![CDATA[ + this.setActionMessage(); + let installingUpdate = this._install && + (AddonManager.shouldAutoUpdate(this._addon) || + this._update.checked); + + if (this._keep.checked && (!this._addon.appDisabled || installingUpdate)) + this.setAttribute("active", "true"); + else + this.removeAttribute("active"); + + gSelect.updateButtons(); + ]]></body> + </method> + + <method name="updateChanged"> + <body><![CDATA[ + this.updateAction(); + ]]></body> + </method> + + <method name="keepChanged"> + <body><![CDATA[ + this.updateAction(); + ]]></body> + </method> + + <method name="keep"> + <body><![CDATA[ + this._keep.checked = true; + this.keepChanged(); + ]]></body> + </method> + + <method name="disable"> + <body><![CDATA[ + this._keep.checked = false; + this.keepChanged(); + ]]></body> + </method> + + <method name="apply"> + <body><![CDATA[ + this._addon.userDisabled = !this._keep.checked; + + if (!this._install || !this._keep.checked) + return; + + if (AddonManager.shouldAutoUpdate(this._addon) || this._update.checked) + this._install.install(); + ]]></body> + </method> + </implementation> + </binding> + + <binding id="addon-confirm"> + <content> + <xul:image class="addon-icon" xbl:inherits="type"/> + <xul:label class="addon-name" xbl:inherits="xbl:text=name"/> + </content> + </binding> +</bindings> diff --git a/toolkit/mozapps/extensions/content/selectAddons.xul b/toolkit/mozapps/extensions/content/selectAddons.xul new file mode 100644 index 000000000..0fa292ecf --- /dev/null +++ b/toolkit/mozapps/extensions/content/selectAddons.xul @@ -0,0 +1,124 @@ +<?xml version="1.0"?> + +<!-- 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/. --> + +<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> +<?xml-stylesheet href="chrome://mozapps/content/extensions/selectAddons.css" type="text/css"?> +<?xml-stylesheet href="chrome://mozapps/skin/extensions/selectAddons.css" type="text/css"?> + +<!DOCTYPE window [ +<!ENTITY % updateDTD SYSTEM "chrome://mozapps/locale/extensions/selectAddons.dtd"> +<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd"> +%updateDTD; +%brandDTD; +]> + +<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + style="&upgrade.style;" id="select-window"> + + <script type="application/javascript" src="chrome://mozapps/content/extensions/selectAddons.js"/> + <stringbundle id="strings" src="chrome://mozapps/locale/extensions/selectAddons.properties"/> + + <deck id="view-deck" flex="1" align="stretch" pack="stretch"> + <vbox id="checking" align="stretch"> + <vbox flex="1"> + <label id="checking-heading" class="heading">&checking.heading;</label> + </vbox> + <progressmeter id="checking-progress" class="progress" mode="undetermined"/> + <vbox flex="1"> + <label id="checking-progress-label" class="progress-label">&checking.progress.label;</label> + </vbox> + </vbox> + + <vbox id="select" align="stretch"> + <label id="select-heading" class="heading">&select.heading;</label> + + <description id="select-description">&select.description;</description> + + <vbox id="select-list" align="stretch" flex="1"> + <hbox id="select-header"> + <hbox class="select-keep select-cell" style="&select.keep.style;"> + <label value="&select.keep;"/> + </hbox> + <hbox class="select-icon select-cell"/> + <hbox id="heading-name" class="select-name select-cell" style="&select.name.style;"> + <label value="&select.name;"/> + </hbox> + <hbox id="heading-action" class="select-action select-cell" style="&select.action.style;"> + <label value="&select.action;"/> + </hbox> + <hbox class="select-source select-cell" flex="1"> + <label value="&select.source;"/> + </hbox> + </hbox> + + <scrollbox id="select-scrollbox" flex="1"> + <grid id="select-grid" flex="1"> + <columns> + <column style="&select.keep.style;"/> + <column/> + <column id="column-name"/> + <column id="column-action" class="select-action"/> + <column class="select-source" flex="1"/> + </columns> + + <rows id="select-rows"/> + </grid> + </scrollbox> + </vbox> + </vbox> + + <vbox id="confirm" align="stretch"> + <label id="confirm-heading" class="heading">&confirm.heading;</label> + + <description id="confirm-description">&confirm.description;</description> + + <scrollbox id="confirm-scrollbox" flex="1"> + <vbox id="disable-list" class="action-list" hidden="true"> + <label class="action-header">&action.disable.heading;</label> + </vbox> + + <vbox id="incompatible-list" class="action-list" hidden="true"> + <label class="action-header">&action.incompatible.heading;</label> + </vbox> + + <vbox id="update-list" class="action-list" hidden="true"> + <label class="action-header">&action.update.heading;</label> + </vbox> + + <vbox id="enable-list" class="action-list" hidden="true"> + <label class="action-header">&action.enable.heading;</label> + </vbox> + </scrollbox> + </vbox> + + <vbox id="update" align="stretch"> + <vbox flex="1"> + <label id="update-heading" class="heading">&update.heading;</label> + </vbox> + <progressmeter id="update-progress" class="progress" mode="undetermined"/> + <vbox flex="1"> + <label id="update-progress-label" class="progress-label">&update.progress.label;</label> + </vbox> + </vbox> + + <vbox id="errors"> + <vbox flex="1"> + <label id="errors-heading" class="heading">&errors.heading;</label> + </vbox> + <description id="errors-description" value="&errors.description;"/> + <spacer flex="1"/> + </vbox> + </deck> + + <hbox id="footer" align="center"> + <label id="footer-label" flex="1">&footer.label;</label> + <button id="cancel" label="&cancel.label;" oncommand="window.close()"/> + <button id="back" label="&back.label;" oncommand="gView.back()" hidden="true"/> + <button id="next" label="&next.label;" oncommand="gView.next()" hidden="true"/> + <button id="done" label="&done.label;" oncommand="gView.done()" hidden="true"/> + </hbox> + +</window> diff --git a/toolkit/mozapps/extensions/content/setting.xml b/toolkit/mozapps/extensions/content/setting.xml index 2b70eb0d0..c4eae1fd3 100644 --- a/toolkit/mozapps/extensions/content/setting.xml +++ b/toolkit/mozapps/extensions/content/setting.xml @@ -8,13 +8,18 @@ %extensionsDTD; ]> -<!-- import-globals-from extensions.js --> - <bindings xmlns="http://www.mozilla.org/xbl" xmlns:xbl="http://www.mozilla.org/xbl" xmlns:html="http://www.w3.org/1999/xhtml" xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <binding id="settings"> + <content orient="vertical"> + <xul:label class="settings-title" xbl:inherits="xbl:text=label" flex="1"/> + <children/> + </content> + </binding> + <binding id="setting-base"> <implementation> <constructor><![CDATA[ @@ -23,7 +28,7 @@ this.addEventListener("keypress", function(event) { event.stopPropagation(); }, false); - + if (this.usePref) Services.prefs.addObserver(this.pref, this._observer, true); ]]></constructor> @@ -206,7 +211,7 @@ <body> <![CDATA[ let val = Services.prefs.getComplexValue(this.pref, Components.interfaces.nsIPrefLocalizedString).data; - if (this.inverted) val = !val; + if(this.inverted) val = !val; this.value = (val == "true"); ]]> </body> @@ -216,7 +221,7 @@ <body> <![CDATA[ let val = this.value; - if (this.inverted) val = !val; + if(this.inverted) val = !val; let pref = Components.classes["@mozilla.org/pref-localizedstring;1"].createInstance(Components.interfaces.nsIPrefLocalizedString); pref.data = this.inverted ? (!val).toString() : val.toString(); Services.prefs.setComplexValue(this.pref, Components.interfaces.nsIPrefLocalizedString, pref); @@ -292,7 +297,8 @@ <method name="valueFromPreference"> <body> <![CDATA[ - this.value = Preferences.get(this.pref, ""); + const nsISupportsString = Components.interfaces.nsISupportsString; + this.value = Services.prefs.getComplexValue(this.pref, nsISupportsString).data; ]]> </body> </method> @@ -300,7 +306,10 @@ <method name="valueToPreference"> <body> <![CDATA[ - Preferences.set(this.pref, this.value); + const nsISupportsString = Components.interfaces.nsISupportsString; + let iss = Components.classes["@mozilla.org/supports-string;1"].createInstance(nsISupportsString); + iss.data = this.value; + Services.prefs.setComplexValue(this.pref, nsISupportsString, iss); ]]> </body> </method> @@ -386,7 +395,7 @@ <method name="valueFromPreference"> <body> <![CDATA[ - this.value = Preferences.get(this.pref, ""); + this.value = Services.prefs.getCharPref(this.pref); ]]> </body> </method> @@ -394,7 +403,7 @@ <method name="valueToPreference"> <body> <![CDATA[ - Preferences.set(this.pref, this.value); + Services.prefs.setCharPref(this.pref, this.value); ]]> </body> </method> @@ -449,7 +458,20 @@ <method name="valueFromPreference"> <body> <![CDATA[ - let val = Preferences.get(this.pref, "").toString(); + let val; + switch (Services.prefs.getPrefType(this.pref)) { + case Ci.nsIPrefBranch.PREF_STRING: + val = Services.prefs.getCharPref(this.pref); + break; + case Ci.nsIPrefBranch.PREF_INT: + val = Services.prefs.getIntPref(this.pref); + break; + case Ci.nsIPrefBranch.PREF_BOOL: + val = Services.prefs.getBoolPref(this.pref).toString(); + break; + default: + return; + } if ("itemCount" in this.control) { for (let i = 0; i < this.control.itemCount; i++) { @@ -470,12 +492,12 @@ <![CDATA[ // We might not have a pref already set, so we guess the type from the value attribute let val = this.control.selectedItem.value; - if (val == "true" || val == "false") { - val = val == "true"; - } else if (/^-?\d+$/.test(val)) { - val = parseInt(val, 10); - } - Preferences.set(this.pref, val); + if (val == "true" || val == "false") + Services.prefs.setBoolPref(this.pref, val == "true"); + else if (/^-?\d+$/.test(val)) + Services.prefs.setIntPref(this.pref, val); + else + Services.prefs.setCharPref(this.pref, val); ]]> </body> </method> diff --git a/toolkit/mozapps/extensions/content/update.js b/toolkit/mozapps/extensions/content/update.js index 80d0fa688..afc74dca8 100644 --- a/toolkit/mozapps/extensions/content/update.js +++ b/toolkit/mozapps/extensions/content/update.js @@ -50,7 +50,7 @@ var gUpdateWizard = { upgradeFailed: 0, upgradeDeclined: 0, - init: function() + init: function gUpdateWizard_init() { logger = Log.repository.getLogger("addons.update-dialog"); // XXX could we pass the addons themselves rather than the IDs? @@ -82,7 +82,7 @@ var gUpdateWizard = { Services.prefs.setBoolPref(PREF_UPDATE_EXTENSIONS_ENABLED, this.shouldAutoCheck); }, - _setUpButton: function(aButtonID, aButtonKey, aDisabled) + _setUpButton: function gUpdateWizard_setUpButton(aButtonID, aButtonKey, aDisabled) { var strings = document.getElementById("updateStrings"); var button = document.documentElement.getButton(aButtonID); @@ -97,7 +97,7 @@ var gUpdateWizard = { button.disabled = aDisabled; }, - setButtonLabels: function(aBackButton, aBackButtonIsDisabled, + setButtonLabels: function gUpdateWizard_setButtonLabels(aBackButton, aBackButtonIsDisabled, aNextButton, aNextButtonIsDisabled, aCancelButton, aCancelButtonIsDisabled) { @@ -106,21 +106,22 @@ var gUpdateWizard = { this._setUpButton("cancel", aCancelButton, aCancelButtonIsDisabled); }, + ///////////////////////////////////////////////////////////////////////////// // Update Errors errorItems: [], - checkForErrors: function(aElementIDToShow) + checkForErrors: function gUpdateWizard_checkForErrors(aElementIDToShow) { if (this.errorItems.length > 0) document.getElementById(aElementIDToShow).hidden = false; }, - onWizardClose: function(aEvent) + onWizardClose: function gUpdateWizard_onWizardClose(aEvent) { return this.onWizardCancel(); }, - onWizardCancel: function() + onWizardCancel: function gUpdateWizard_onWizardCancel() { gUpdateWizard.shuttingDown = true; // Allow add-ons to continue downloading and installing @@ -130,8 +131,13 @@ var gUpdateWizard = { if (gMismatchPage.waiting) { logger.info("Dialog closed in mismatch page"); if (gUpdateWizard.addonInstalls.size > 0) { - gInstallingPage.startInstalls( - Array.from(gUpdateWizard.addonInstalls.values())); + // Tycho: gInstallingPage.startInstalls([i for ([, i] of gUpdateWizard.addonInstalls)]); + let results = []; + for (let [, i] of gUpdateWizard.addonInstalls) { + results.push(i); + } + + gInstallingPage.startInstalls(results); } return true; } @@ -149,13 +155,13 @@ var gUpdateWizard = { }; var gOfflinePage = { - onPageAdvanced: function() + onPageAdvanced: function gOfflinePage_onPageAdvanced() { Services.io.offline = false; return true; }, - toggleOffline: function() + toggleOffline: function gOfflinePage_toggleOffline() { var nextbtn = document.documentElement.getButton("next"); nextbtn.disabled = !nextbtn.disabled; @@ -164,11 +170,11 @@ var gOfflinePage = { // Addon listener to count addons enabled/disabled by metadata checks var listener = { - onDisabled: function(aAddon) { + onDisabled: function listener_onDisabled(aAddon) { gUpdateWizard.affectedAddonIDs.add(aAddon.id); gUpdateWizard.metadataDisabled++; }, - onEnabled: function(aAddon) { + onEnabled: function listener_onEnabled(aAddon) { gUpdateWizard.affectedAddonIDs.delete(aAddon.id); gUpdateWizard.metadataEnabled++; } @@ -178,7 +184,7 @@ var gVersionInfoPage = { _completeCount: 0, _totalCount: 0, _versionInfoDone: false, - onPageShow: Task.async(function*() { + onPageShow: Task.async(function* gVersionInfoPage_onPageShow() { gUpdateWizard.setButtonLabels(null, true, "nextButtonText", true, "cancelButtonText", false); @@ -195,10 +201,14 @@ var gVersionInfoPage = { logger.debug("repopulateCache completed after dialog closed"); } } - // Fetch the add-ons that are still affected by this update, - // excluding the hotfix add-on. - let idlist = Array.from(gUpdateWizard.affectedAddonIDs).filter( - a => a.id != AddonManager.hotfixID); + // Fetch the add-ons that are still affected by this update. + // Tycho: let idlist = [id for (id of gUpdateWizard.affectedAddonIDs)]; + + let idlist = []; + for (let id of gUpdateWizard.affectedAddonIDs) { + idlist.push(id); + } + if (idlist.length < 1) { gVersionInfoPage.onAllUpdatesFinished(); return; @@ -208,7 +218,16 @@ var gVersionInfoPage = { let fetchedAddons = yield new Promise((resolve, reject) => AddonManager.getAddonsByIDs(idlist, resolve)); // We shouldn't get nulls here, but let's be paranoid... - gUpdateWizard.addons = fetchedAddons.filter(a => a); + // Tycho: gUpdateWizard.addons = [a for (a of fetchedAddons) if (a)]; + let results = []; + for (let a of fetchedAddons) { + if (a) { + results.push(a); + } + } + + gUpdateWizard.addons = results; + if (gUpdateWizard.addons.length < 1) { gVersionInfoPage.onAllUpdatesFinished(); return; @@ -222,7 +241,7 @@ var gVersionInfoPage = { } }), - onAllUpdatesFinished: function() { + onAllUpdatesFinished: function gVersionInfoPage_onAllUpdatesFinished() { AddonManager.removeAddonListener(listener); AddonManagerPrivate.recordSimpleMeasure("appUpdate_disabled", gUpdateWizard.disabled); @@ -236,8 +255,18 @@ var gVersionInfoPage = { AddonManagerPrivate.recordSimpleMeasure("appUpdate_upgradeFailed", 0); AddonManagerPrivate.recordSimpleMeasure("appUpdate_upgradeDeclined", 0); // Filter out any add-ons that are now enabled. - let addonList = gUpdateWizard.addons.map(a => a.id + ":" + a.appDisabled); - logger.debug("VersionInfo updates finished: found " + addonList.toSource()); + // Tycho: + // logger.debug("VersionInfo updates finished: found " + + // [addon.id + ":" + addon.appDisabled for (addon of gUpdateWizard.addons)].toSource()); + + let logDisabledAddons = []; + for (let addon of gUpdateWizard.addons) { + if (addon.appDisabled) { + logDisabledAddons.push(addon.id + ":" + addon.appDisabled); + } + } + logger.debug("VersionInfo updates finished: found " + logDisabledAddons.toSource()); + let filteredAddons = []; for (let a of gUpdateWizard.addons) { if (a.appDisabled) { @@ -254,8 +283,13 @@ var gVersionInfoPage = { if (gUpdateWizard.shuttingDown) { // jump directly to updating auto-update add-ons in the background if (gUpdateWizard.addonInstalls.size > 0) { - let installs = Array.from(gUpdateWizard.addonInstalls.values()); - gInstallingPage.startInstalls(installs); + // Tycho: gInstallingPage.startInstalls([i for ([, i] of gUpdateWizard.addonInstalls)]); + let results = []; + for (let [, i] of gUpdateWizard.addonInstalls) { + results.push(i); + } + + gInstallingPage.startInstalls(results); } return; } @@ -271,14 +305,15 @@ var gVersionInfoPage = { logger.info("VersionInfo: No updates require further action"); // VersionInfo compatibility updates resolved all compatibility problems, // close this window and continue starting the application... - // XXX Bug 314754 - We need to use setTimeout to close the window due to + //XXX Bug 314754 - We need to use setTimeout to close the window due to // the EM using xmlHttpRequest when checking for updates. setTimeout(close, 0); } }, + ///////////////////////////////////////////////////////////////////////////// // UpdateListener - onUpdateFinished: function(aAddon, status) { + onUpdateFinished: function gVersionInfoPage_onUpdateFinished(aAddon, status) { ++this._completeCount; if (status != AddonManager.UPDATE_STATUS_NO_ERROR) { @@ -317,7 +352,7 @@ var gVersionInfoPage = { this.onAllUpdatesFinished(); }, - onUpdateAvailable: function(aAddon, aInstall) { + onUpdateAvailable: function gVersionInfoPage_onUpdateAvailable(aAddon, aInstall) { logger.debug("VersionInfo got an install for " + aAddon.id + ": " + aAddon.version); gUpdateWizard.addonInstalls.set(aAddon.id, aInstall); }, @@ -326,7 +361,7 @@ var gVersionInfoPage = { var gMismatchPage = { waiting: false, - onPageShow: function() + onPageShow: function gMismatchPage_onPageShow() { gMismatchPage.waiting = true; gUpdateWizard.setButtonLabels(null, true, @@ -346,7 +381,7 @@ var gMismatchPage = { var gUpdatePage = { _totalCount: 0, _completeCount: 0, - onPageShow: function() + onPageShow: function gUpdatePage_onPageShow() { gMismatchPage.waiting = false; gUpdateWizard.setButtonLabels(null, true, @@ -365,7 +400,7 @@ var gUpdatePage = { } }, - onAllUpdatesFinished: function() { + onAllUpdatesFinished: function gUpdatePage_onAllUpdatesFinished() { if (gUpdateWizard.shuttingDown) return; @@ -375,13 +410,14 @@ var gUpdatePage = { document.documentElement.currentPage = nextPage; }, + ///////////////////////////////////////////////////////////////////////////// // UpdateListener - onUpdateAvailable: function(aAddon, aInstall) { + onUpdateAvailable: function gUpdatePage_onUpdateAvailable(aAddon, aInstall) { logger.debug("UpdatePage got an update for " + aAddon.id + ": " + aAddon.version); gUpdateWizard.addonsToUpdate.push(aInstall); }, - onUpdateFinished: function(aAddon, status) { + onUpdateFinished: function gUpdatePage_onUpdateFinished(aAddon, status) { if (status != AddonManager.UPDATE_STATUS_NO_ERROR) gUpdateWizard.errorItems.push(aAddon); @@ -404,7 +440,7 @@ var gUpdatePage = { }; var gFoundPage = { - onPageShow: function() + onPageShow: function gFoundPage_onPageShow() { gUpdateWizard.setButtonLabels(null, true, "installButtonText", false, @@ -430,7 +466,7 @@ var gFoundPage = { } }, - toggleXPInstallEnable: function(aEvent) + toggleXPInstallEnable: function gFoundPage_toggleXPInstallEnable(aEvent) { var enabled = aEvent.target.checked; gUpdateWizard.xpinstallEnabled = enabled; @@ -440,7 +476,7 @@ var gFoundPage = { this.updateNextButton(); }, - updateNextButton: function() + updateNextButton: function gFoundPage_updateNextButton() { if (!gUpdateWizard.xpinstallEnabled) { document.documentElement.getButton("next").disabled = true; @@ -474,20 +510,28 @@ var gInstallingPage = { // Initialize fields we need for installing and tracking progress, // and start iterating through the installations - startInstalls: function(aInstallList) { + startInstalls: function gInstallingPage_startInstalls(aInstallList) { if (!gUpdateWizard.xpinstallEnabled) { return; } - let installs = Array.from(aInstallList).map(a => a.existingAddon.id); - logger.debug("Start installs for " + installs.toSource()); + // Tycho: + // logger.debug("Start installs for " + // + [i.existingAddon.id for (i of aInstallList)].toSource()); + + let logInstallAddons = []; + for (let i of aInstallList) { + logInstallAddons.push(i.existingAddon.id); + } + logger.debug("Start installs for " + logInstallAddons.toSource()); + this._errors = []; this._installs = aInstallList; this._installing = true; this.startNextInstall(); }, - onPageShow: function() + onPageShow: function gInstallingPage_onPageShow() { gUpdateWizard.setButtonLabels(null, true, "nextButtonText", true, @@ -510,7 +554,7 @@ var gInstallingPage = { this.startInstalls(toInstall); }, - startNextInstall: function() { + startNextInstall: function gInstallingPage_startNextInstall() { if (this._currentInstall >= 0) { this._installs[this._currentInstall].removeListener(this); } @@ -548,8 +592,9 @@ var gInstallingPage = { install.install(); }, + ///////////////////////////////////////////////////////////////////////////// // InstallListener - onDownloadStarted: function(aInstall) { + onDownloadStarted: function gInstallingPage_onDownloadStarted(aInstall) { if (gUpdateWizard.shuttingDown) { return; } @@ -559,7 +604,7 @@ var gInstallingPage = { actionItem.value = label; }, - onDownloadProgress: function(aInstall) { + onDownloadProgress: function gInstallingPage_onDownloadProgress(aInstall) { if (gUpdateWizard.shuttingDown) { return; } @@ -567,17 +612,17 @@ var gInstallingPage = { downloadProgress.value = Math.ceil(100 * aInstall.progress / aInstall.maxProgress); }, - onDownloadEnded: function(aInstall) { + onDownloadEnded: function gInstallingPage_onDownloadEnded(aInstall) { }, - onDownloadFailed: function(aInstall) { + onDownloadFailed: function gInstallingPage_onDownloadFailed(aInstall) { this._errors.push(aInstall); gUpdateWizard.upgradeFailed++; this.startNextInstall(); }, - onInstallStarted: function(aInstall) { + onInstallStarted: function gInstallingPage_onInstallStarted(aInstall) { if (gUpdateWizard.shuttingDown) { return; } @@ -587,7 +632,7 @@ var gInstallingPage = { actionItem.value = label; }, - onInstallEnded: function(aInstall, aAddon) { + onInstallEnded: function gInstallingPage_onInstallEnded(aInstall, aAddon) { if (!gUpdateWizard.shuttingDown) { // Remember that this add-on was updated during startup AddonManagerPrivate.addStartupChange(AddonManager.STARTUP_CHANGE_CHANGED, @@ -598,7 +643,7 @@ var gInstallingPage = { this.startNextInstall(); }, - onInstallFailed: function(aInstall) { + onInstallFailed: function gInstallingPage_onInstallFailed(aInstall) { this._errors.push(aInstall); gUpdateWizard.upgradeFailed++; @@ -607,7 +652,7 @@ var gInstallingPage = { }; var gInstallErrorsPage = { - onPageShow: function() + onPageShow: function gInstallErrorsPage_onPageShow() { gUpdateWizard.setButtonLabels(null, true, null, true, null, true); document.documentElement.getButton("finish").focus(); @@ -617,7 +662,7 @@ var gInstallErrorsPage = { // Displayed when there are incompatible add-ons and the xpinstall.enabled // pref is false and locked. var gAdminDisabledPage = { - onPageShow: function() + onPageShow: function gAdminDisabledPage_onPageShow() { gUpdateWizard.setButtonLabels(null, true, null, true, "cancelButtonText", true); @@ -628,7 +673,7 @@ var gAdminDisabledPage = { // Displayed when selected add-on updates have been installed without error. // There can still be add-ons that are not compatible and don't have an update. var gFinishedPage = { - onPageShow: function() + onPageShow: function gFinishedPage_onPageShow() { gUpdateWizard.setButtonLabels(null, true, null, true, null, true); document.documentElement.getButton("finish").focus(); @@ -647,7 +692,7 @@ var gFinishedPage = { // Displayed when there are incompatible add-ons and there are no available // updates. var gNoUpdatesPage = { - onPageShow: function(aEvent) + onPageShow: function gNoUpdatesPage_onPageLoad(aEvent) { gUpdateWizard.setButtonLabels(null, true, null, true, null, true); if (gUpdateWizard.shouldSuggestAutoChecking) { diff --git a/toolkit/mozapps/extensions/content/update.xul b/toolkit/mozapps/extensions/content/update.xul index 745983814..094651fa5 100644 --- a/toolkit/mozapps/extensions/content/update.xul +++ b/toolkit/mozapps/extensions/content/update.xul @@ -87,6 +87,7 @@ <description>&noupdates.intro.desc;</description> <separator class="thin"/> <hbox id="updateCheckErrorNotFound" class="alertBox" hidden="true" align="top"> + <image id="alert"/> <description flex="1">&noupdates.error.desc;</description> </hbox> <separator class="thin"/> @@ -156,6 +157,7 @@ onpageshow="gAdminDisabledPage.onPageShow();"> <separator/> <hbox class="alertBox" align="top"> + <image id="alert"/> <description flex="1">&adminDisabled.warning.label;</description> </hbox> <separator flex="1"/> diff --git a/toolkit/mozapps/extensions/content/xpinstallConfirm.js b/toolkit/mozapps/extensions/content/xpinstallConfirm.js index 5660cdaaf..678e37001 100644 --- a/toolkit/mozapps/extensions/content/xpinstallConfirm.js +++ b/toolkit/mozapps/extensions/content/xpinstallConfirm.js @@ -6,7 +6,7 @@ var XPInstallConfirm = {}; -XPInstallConfirm.init = function() +XPInstallConfirm.init = function XPInstallConfirm_init() { Components.utils.import("resource://gre/modules/AddonManager.jsm"); @@ -36,7 +36,7 @@ XPInstallConfirm.init = function() var delay_in_milliseconds = prefs.getIntPref("security.dialog_enable_delay"); _installCountdownLength = Math.round(delay_in_milliseconds / 500); } catch (ex) { } - + var itemList = document.getElementById("itemList"); let installMap = new WeakMap(); @@ -47,7 +47,7 @@ XPInstallConfirm.init = function() window.close(); } }; - + var numItemsToInstall = args.installs.length; for (let install of args.installs) { var installItem = document.createElement("installitem"); @@ -72,7 +72,7 @@ XPInstallConfirm.init = function() installMap.set(install, installItem); install.addListener(installListener); } - + var introString = bundle.getString("itemWarnIntroSingle"); if (numItemsToInstall > 4) introString = bundle.getFormattedString("itemWarnIntroMultiple", [numItemsToInstall]); @@ -81,7 +81,7 @@ XPInstallConfirm.init = function() while (introNode.hasChildNodes()) introNode.removeChild(introNode.firstChild); introNode.appendChild(textNode); - + var okButton = document.documentElement.getButton("accept"); okButton.focus(); @@ -177,7 +177,7 @@ XPInstallConfirm.init = function() okButton.label = bundle.getString("installButtonLabel"); } -XPInstallConfirm.onOK = function() +XPInstallConfirm.onOK = function XPInstallConfirm_onOk() { Components.classes["@mozilla.org/base/telemetry;1"]. getService(Components.interfaces.nsITelemetry). @@ -188,7 +188,7 @@ XPInstallConfirm.onOK = function() return true; } -XPInstallConfirm.onCancel = function() +XPInstallConfirm.onCancel = function XPInstallConfirm_onCancel() { // Perform the install or cancel after the window has unloaded XPInstallConfirm._installOK = false; diff --git a/toolkit/mozapps/extensions/docs/SystemAddons.rst b/toolkit/mozapps/extensions/docs/SystemAddons.rst deleted file mode 100644 index 5f724e9ef..000000000 --- a/toolkit/mozapps/extensions/docs/SystemAddons.rst +++ /dev/null @@ -1,224 +0,0 @@ -Firefox System Add-on Update Protocol -===================================== -This document describes the protocol that Firefox uses when retrieving updates -for System Add-ons from the automatic update service (AUS, currently `Balrog`_), -and the expected behavior of Firefox based on the updater service's response. - -.. _Balrog: https://wiki.mozilla.org/Balrog - -System Add-ons --------------- -System add-ons: - -* Are add-ons that ship with Firefox, are hidden from the UI, and cannot be - disabled -* Can be updated by Firefox depending on the AUS response to Firefox's update - request -* Are stored in two locations: - - * The **default** set ships with Firefox and is stored in the application - directory. - * The **update** set is stored in the user’s profile directory. If an add-on - is both in the update and default set, the update version gets precedence. - -Update Request --------------- -To determine what updates to install, Firefox makes an HTTP **GET** request to -AUS once a day via a URL of the form:: - - https://aus5.mozilla.org/update/3/SystemAddons/%VERSION%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/update.xml - -The path segments surrounded by ``%`` symbols are variable fields that Firefox -fills in with information about itself and the environment it's running in: - -``VERSION`` - Firefox version number -``BUILD_ID`` - Build ID -``BUILD_TARGET`` - Build target -``LOCALE`` - Build locale -``CHANNEL`` - Update channel -``OS_VERSION`` - OS Version -``DISTRIBUTION`` - Firefox Distribution -``DISTRIBUTION_VERSION`` - Firefox Distribution version - -Update Response ---------------- -AUS should respond with an XML document that looks something like this: - -.. code-block:: xml - - <?xml version="1.0"?> - <updates> - <addons> - <addon id="flyweb@mozilla.org" URL="https://ftp.mozilla.org/pub/system-addons/flyweb/flyweb@mozilla.org-1.0.xpi" hashFunction="sha512" hashValue="abcdef123" size="1234" version="1.0"/> - <addon id="pocket@mozilla.org" URL="https://ftp.mozilla.org/pub/system-addons/pocket/pocket@mozilla.org-1.0.xpi" hashFunction="sha512" hashValue="abcdef123" size="1234" version="1.0"/> - </addons> - </updates> - -* The root element is ``<updates>``, used for all updater responses. -* The only child of ``<updates>`` is ``<addons>``, which represents a list of - system add-ons to update. -* Within ``<addons>`` are several ``<addon>`` tags, each one corresponding to a - system add-on to update. - -``<addon>`` tags **must** have the following attributes: - -``id`` - The extension ID -``URL`` - URL to a signed XPI of the specified add-on version to download -``hashFunction`` - Identifier of the hash function used to generate the hashValue attribute. -``hashValue`` - Hash of the XPI file linked from the URL attribute, calculated using the function specified in the hashValue attribute. -``size`` - Size (in bytes) of the XPI file linked from the URL attribute. -``version`` - Version number of the add-on - -Update Behavior ---------------- -After receiving the update response, Firefox modifies the **update** add-ons -according to the following algorithm: - -1. If the ``<addons>`` tag is empty (``<addons></addons>``) in the response, - **remove all system add-on updates**. -2. If no add-ons were specified in the response (i.e. the ``<addons>`` tag - is not present), do nothing and finish. -3. If the **update** add-on set is equal to the set of add-ons specified in the - update response, do nothing and finish. -4. If the set of **default** add-ons is equal to the set of add-ons specified in - the update response, remove all the **update** add-ons and finish. -5. Download each add-on specified in the update response and store them in the - "downloaded add-on set". A failed download **must** abort the entire system - add-on update. -6. Validate the downloaded add-ons. The following **must** be true for all - downloaded add-ons, or the update process is aborted: - - a. The ID and version of the downloaded add-on must match the specified ID or - version in the update response. - b. The hash provided in the update response must match the downloaded add-on - file. - c. The downloaded add-on file size must match the size given in the update - response. - d. The add-on must be compatible with Firefox (i.e. it must not be for a - different application, such as Thunderbird). - e. The add-on must be packed (i.e. be an XPI file). - f. The add-on must be restartless. - g. The add-on must be signed by the system add-on root certificate. - -6. Once all downloaded add-ons are validated, install them into the profile - directory as part of the **update** set. - -Notes on the update process: - -* Add-ons are considered "equal" if they have the same ID and version number. - -Examples --------- -The follow section describes common situations that we have or expect to run -into and how the protocol described above handles them. - -For simplicity, unless otherwise specified, all examples assume that there are -two system add-ons in existence: **FlyWeb** and **Pocket**. - -Basic -~~~~~ -A user has Firefox 45, which shipped with FlyWeb 1.0 and Pocket 1.0. We want to -update users to FlyWeb 2.0. AUS sends out the following update response: - -.. code-block:: xml - - <updates> - <addons> - <addon id="flyweb@mozilla.org" URL="https://ftp.mozilla.org/pub/system-addons/flyweb/flyweb@mozilla.org-2.0.xpi" hashFunction="sha512" hashValue="abcdef123" size="1234" version="2.0"/> - <addon id="pocket@mozilla.org" URL="https://ftp.mozilla.org/pub/system-addons/pocket/pocket@mozilla.org-1.0.xpi" hashFunction="sha512" hashValue="abcdef123" size="1234" version="1.0"/> - </addons> - </updates> - -Firefox will download FlyWeb 2.0 and Pocket 1.0 and store them in the profile directory. - -Missing Add-on -~~~~~~~~~~~~~~ -A user has Firefox 45, which shipped with FlyWeb 1.0 and Pocket 1.0. We want to -update users to FlyWeb 2.0, but accidentally forget to specify Pocket in the -update response. AUS sends out the following: - -.. code-block:: xml - - <updates> - <addons> - <addon id="flyweb@mozilla.org" URL="https://ftp.mozilla.org/pub/system-addons/flyweb/flyweb@mozilla.org-2.0.xpi" hashFunction="sha512" hashValue="abcdef123" size="1234" version="2.0"/> - </addons> - </updates> - -Firefox will download FlyWeb 2.0 and store it in the profile directory. Pocket -1.0 from the **default** location will be used. - -Remove all system add-on updates -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -A response from AUS with an empty add-on set will *remove all system add-on -updates*: - -.. code-block:: xml - - <updates> - <addons></addons> - </updates> - -Rollout -~~~~~~~ -A user has Firefox 45, which shipped with FlyWeb 1.0 and Pocket 1.0. We want to -rollout FlyWeb 2.0 at a 10% sample rate. 10% of the time, AUS sends out: - -.. code-block:: xml - - <updates> - <addons> - <addon id="flyweb@mozilla.org" URL="https://ftp.mozilla.org/pub/system-addons/flyweb/flyweb@mozilla.org-2.0.xpi" hashFunction="sha512" hashValue="abcdef123" size="1234" version="2.0"/> - <addon id="pocket@mozilla.org" URL="https://ftp.mozilla.org/pub/system-addons/pocket/pocket@mozilla.org-1.0.xpi" hashFunction="sha512" hashValue="abcdef123" size="1234" version="1.0"/> - </addons> - </updates> - -With this response, Firefox will download Pocket 1.0 and FlyWeb 2.0 and install -them into the profile directory. - -The other 90% of the time, AUS sends out an empty response: - -.. code-block:: xml - - <updates></updates> - -With the empty response, Firefox will not make any changes. This means users who -haven’t seen the 10% update response will stay on FlyWeb 1.0, and users who have -seen it will stay on FlyWeb 2.0. - -Once we’re happy with the rollout and want to switch to 100%, AUS will send the -10% update response to 100% of users, upgrading everyone to FlyWeb 2.0. - -Rollback -~~~~~~~~ -This example continues from the “Rollout” example. If, during the 10% rollout, -we find a major issue with FlyWeb 2.0, we want to roll all users back to FlyWeb 1.0. -AUS sends out the following: - -.. code-block:: xml - - <updates> - <addons> - <addon id="flyweb@mozilla.org" URL="https://ftp.mozilla.org/pub/system-addons/flyweb/flyweb@mozilla.org-1.0.xpi" hashFunction="sha512" hashValue="abcdef123" size="1234" version="1.0"/> - <addon id="pocket@mozilla.org" URL="https://ftp.mozilla.org/pub/system-addons/pocket/pocket@mozilla.org-1.0.xpi" hashFunction="sha512" hashValue="abcdef123" size="1234" version="1.0"/> - </addons> - </updates> - -For users who have updated, Firefox will download FlyWeb 1.0 and Pocket 1.0 and -install them into the profile directory. For users that haven’t yet updated, -Firefox will see that the **default** add-on set matches the set in the update -ping and clear the **update** add-on set. diff --git a/toolkit/mozapps/extensions/docs/index.rst b/toolkit/mozapps/extensions/docs/index.rst deleted file mode 100644 index ab6ed3c70..000000000 --- a/toolkit/mozapps/extensions/docs/index.rst +++ /dev/null @@ -1,14 +0,0 @@ -============== -Add-on Manager -============== - -This is the nascent documentation of the Add-on Manager code. - -The public Add-on Manager interfaces are documented on MDN: - -https://developer.mozilla.org/en-US/Add-ons/Add-on_Manager - -.. toctree:: - :maxdepth: 1 - - SystemAddons diff --git a/toolkit/mozapps/extensions/extensions.manifest b/toolkit/mozapps/extensions/extensions.manifest index c7d2ee386..f0f00545f 100644 --- a/toolkit/mozapps/extensions/extensions.manifest +++ b/toolkit/mozapps/extensions/extensions.manifest @@ -1,16 +1,11 @@ -component {66354bc9-7ed1-4692-ae1d-8da97d6b205e} nsBlocklistService.js process=main -contract @mozilla.org/extensions/blocklist;1 {66354bc9-7ed1-4692-ae1d-8da97d6b205e} process=main -category profile-after-change nsBlocklistService @mozilla.org/extensions/blocklist;1 process=main -component {e0a106ed-6ad4-47a4-b6af-2f1c8aa4712d} nsBlocklistServiceContent.js process=content -contract @mozilla.org/extensions/blocklist;1 {e0a106ed-6ad4-47a4-b6af-2f1c8aa4712d} process=content - -category update-timer nsBlocklistService @mozilla.org/extensions/blocklist;1,getService,blocklist-background-update-timer,extensions.blocklist.interval,86400 +component {66354bc9-7ed1-4692-ae1d-8da97d6b205e} nsBlocklistService.js +contract @mozilla.org/extensions/blocklist;1 {66354bc9-7ed1-4692-ae1d-8da97d6b205e} +category profile-after-change nsBlocklistService @mozilla.org/extensions/blocklist;1 #ifndef MOZ_WIDGET_GONK +category update-timer nsBlocklistService @mozilla.org/extensions/blocklist;1,getService,blocklist-background-update-timer,extensions.blocklist.interval,86400 component {4399533d-08d1-458c-a87a-235f74451cfa} addonManager.js contract @mozilla.org/addons/integration;1 {4399533d-08d1-458c-a87a-235f74451cfa} -#ifndef MOZ_WIDGET_ANDROID category update-timer addonManager @mozilla.org/addons/integration;1,getService,addon-background-update-timer,extensions.update.interval,86400 -#endif component {7beb3ba8-6ec3-41b4-b67c-da89b8518922} amContentHandler.js contract @mozilla.org/uriloader/content-handler;1?type=application/x-xpinstall {7beb3ba8-6ec3-41b4-b67c-da89b8518922} component {0f38e086-89a3-40a5-8ffc-9b694de1d04a} amWebInstallListener.js @@ -23,5 +18,3 @@ category addon-provider-module PluginProvider resource://gre/modules/addons/Plug #endif category addon-provider-module GMPProvider resource://gre/modules/addons/GMPProvider.jsm #endif -component {8866d8e3-4ea5-48b7-a891-13ba0ac15235} amWebAPI.js -contract @mozilla.org/addon-web-api/manager;1 {8866d8e3-4ea5-48b7-a891-13ba0ac15235} diff --git a/toolkit/mozapps/extensions/internal/APIExtensionBootstrap.js b/toolkit/mozapps/extensions/internal/APIExtensionBootstrap.js deleted file mode 100644 index 0eae2475c..000000000 --- a/toolkit/mozapps/extensions/internal/APIExtensionBootstrap.js +++ /dev/null @@ -1,39 +0,0 @@ -/* 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/. */ - -"use strict"; - -Components.utils.import("resource://gre/modules/ExtensionManagement.jsm"); -Components.utils.import("resource://gre/modules/Services.jsm"); - -var namespace; -var resource; -var resProto; - -function install(data, reason) { -} - -function startup(data, reason) { - namespace = data.id.replace(/@.*/, ""); - resource = `extension-${namespace}-api`; - - resProto = Services.io.getProtocolHandler("resource") - .QueryInterface(Components.interfaces.nsIResProtocolHandler); - - resProto.setSubstitution(resource, data.resourceURI); - - ExtensionManagement.registerAPI( - namespace, - `resource://${resource}/schema.json`, - `resource://${resource}/api.js`); -} - -function shutdown(data, reason) { - resProto.setSubstitution(resource, null); - - ExtensionManagement.unregisterAPI(namespace); -} - -function uninstall(data, reason) { -} diff --git a/toolkit/mozapps/extensions/internal/AddonConstants.jsm b/toolkit/mozapps/extensions/internal/AddonConstants.jsm deleted file mode 100644 index 22d91fdf5..000000000 --- a/toolkit/mozapps/extensions/internal/AddonConstants.jsm +++ /dev/null @@ -1,31 +0,0 @@ -/* 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/. */ - -"use strict"; - -this.EXPORTED_SYMBOLS = [ "ADDON_SIGNING", "REQUIRE_SIGNING" ]; - -// Make these non-changable properties so they can't be manipulated from other -// code in the app. -Object.defineProperty(this, "ADDON_SIGNING", { - configurable: false, - enumerable: false, - writable: false, -#ifdef MOZ_ADDON_SIGNING - value: true, -#else - value: false, -#endif -}); - -Object.defineProperty(this, "REQUIRE_SIGNING", { - configurable: false, - enumerable: false, - writable: false, -#ifdef MOZ_REQUIRE_SIGNING - value: true, -#else - value: false, -#endif -}); diff --git a/toolkit/mozapps/extensions/internal/AddonLogging.jsm b/toolkit/mozapps/extensions/internal/AddonLogging.jsm index f05a6fe6c..362439bae 100644 --- a/toolkit/mozapps/extensions/internal/AddonLogging.jsm +++ b/toolkit/mozapps/extensions/internal/AddonLogging.jsm @@ -81,7 +81,7 @@ function AddonLogger(aName) { AddonLogger.prototype = { name: null, - error: function(aStr, aException) { + error: function AddonLogger_error(aStr, aException) { let message = formatLogMessage("error", this.name, aStr, aException); let stack = getStackDetails(aException); @@ -95,18 +95,6 @@ AddonLogger.prototype = { // Always dump errors, in case the Console Service isn't listening yet dump("*** " + message + "\n"); - function formatTimestamp(date) { - // Format timestamp as: "%Y-%m-%d %H:%M:%S" - let year = String(date.getFullYear()); - let month = String(date.getMonth() + 1).padStart(2, "0"); - let day = String(date.getDate()).padStart(2, "0"); - let hours = String(date.getHours()).padStart(2, "0"); - let minutes = String(date.getMinutes()).padStart(2, "0"); - let seconds = String(date.getSeconds()).padStart(2, "0"); - - return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; - } - try { var tstamp = new Date(); var logfile = FileUtils.getFile(KEY_PROFILEDIR, [FILE_EXTENSIONS_LOG]); @@ -116,7 +104,7 @@ AddonLogger.prototype = { var writer = Cc["@mozilla.org/intl/converter-output-stream;1"]. createInstance(Ci.nsIConverterOutputStream); writer.init(stream, "UTF-8", 0, 0x0000); - writer.writeString(formatTimestamp(tstamp) + " " + + writer.writeString(tstamp.toLocaleFormat("%Y-%m-%d %H:%M:%S ") + message + " at " + stack.sourceName + ":" + stack.lineNumber + "\n"); writer.close(); @@ -124,7 +112,7 @@ AddonLogger.prototype = { catch (e) { } }, - warn: function(aStr, aException) { + warn: function AddonLogger_warn(aStr, aException) { let message = formatLogMessage("warn", this.name, aStr, aException); let stack = getStackDetails(aException); @@ -139,7 +127,7 @@ AddonLogger.prototype = { dump("*** " + message + "\n"); }, - log: function(aStr, aException) { + log: function AddonLogger_log(aStr, aException) { if (gDebugLogEnabled) { let message = formatLogMessage("log", this.name, aStr, aException); dump("*** " + message + "\n"); @@ -149,14 +137,14 @@ AddonLogger.prototype = { }; this.LogManager = { - getLogger: function(aName, aTarget) { + getLogger: function LogManager_getLogger(aName, aTarget) { let logger = new AddonLogger(aName); if (aTarget) { ["error", "warn", "log"].forEach(function(name) { let fname = name.toUpperCase(); delete aTarget[fname]; - aTarget[fname] = function(aStr, aException) { + aTarget[fname] = function LogManager_targetName(aStr, aException) { logger[name](aStr, aException); }; }); @@ -167,13 +155,13 @@ this.LogManager = { }; var PrefObserver = { - init: function() { + init: function PrefObserver_init() { Services.prefs.addObserver(PREF_LOGGING_ENABLED, this, false); Services.obs.addObserver(this, "xpcom-shutdown", false); this.observe(null, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, PREF_LOGGING_ENABLED); }, - observe: function(aSubject, aTopic, aData) { + observe: function PrefObserver_observe(aSubject, aTopic, aData) { if (aTopic == "xpcom-shutdown") { Services.prefs.removeObserver(PREF_LOGGING_ENABLED, this); Services.obs.removeObserver(this, "xpcom-shutdown"); diff --git a/toolkit/mozapps/extensions/internal/AddonRepository.jsm b/toolkit/mozapps/extensions/internal/AddonRepository.jsm index 7f88d44ad..76a7528c7 100644 --- a/toolkit/mozapps/extensions/internal/AddonRepository.jsm +++ b/toolkit/mozapps/extensions/internal/AddonRepository.jsm @@ -11,7 +11,6 @@ const Cr = Components.results; Components.utils.import("resource://gre/modules/Services.jsm"); Components.utils.import("resource://gre/modules/AddonManager.jsm"); -/* globals AddonManagerPrivate*/ Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "NetUtil", @@ -24,8 +23,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "AddonRepository_SQLiteMigrator", "resource://gre/modules/addons/AddonRepository_SQLiteMigrator.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "Promise", "resource://gre/modules/Promise.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "ServiceRequest", - "resource://gre/modules/ServiceRequest.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "Task", "resource://gre/modules/Task.jsm"); @@ -67,7 +64,9 @@ const BLANK_DB = function() { } const TOOLKIT_ID = "toolkit@mozilla.org"; - +#ifdef MOZ_PHOENIX_EXTENSIONS +const FIREFOX_ID = "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"; +#endif Cu.import("resource://gre/modules/Log.jsm"); const LOGGER_ID = "addons.repository"; @@ -101,6 +100,10 @@ const INTEGER_KEY_MAP = { daily_users: "dailyUsers" }; +// Wrap the XHR factory so that tests can override with a mock +var XHRequest = Components.Constructor("@mozilla.org/xmlextras/xmlhttprequest;1", + "nsIXMLHttpRequest"); + function convertHTMLToPlainText(html) { if (!html) return html; @@ -130,14 +133,14 @@ function getAddonsToCache(aIds, aCallback) { types = types.split(","); - AddonManager.getAddonsByIDs(aIds, function(aAddons) { + AddonManager.getAddonsByIDs(aIds, function getAddonsToCache_getAddonsByIDs(aAddons) { let enabledIds = []; for (var i = 0; i < aIds.length; i++) { var preference = PREF_GETADDONS_CACHE_ID_ENABLED.replace("%ID%", aIds[i]); try { if (!Services.prefs.getBoolPref(preference)) continue; - } catch (e) { + } catch(e) { // If the preference doesn't exist caching is enabled by default } @@ -398,7 +401,7 @@ AddonSearchResult.prototype = { * A platform version to test against * @return Boolean representing if the add-on is compatible */ - isCompatibleWith: function(aAppVersion, aPlatformVersion) { + isCompatibleWith: function ASR_isCompatibleWith(aAppVerison, aPlatformVersion) { return true; }, @@ -415,7 +418,7 @@ AddonSearchResult.prototype = { * @param aPlatformVersion * A platform version to check for updates for */ - findUpdates: function(aListener, aReason, aAppVersion, aPlatformVersion) { + findUpdates: function ASR_findUpdates(aListener, aReason, aAppVersion, aPlatformVersion) { if ("onNoCompatibilityUpdateAvailable" in aListener) aListener.onNoCompatibilityUpdateAvailable(this); if ("onNoUpdateAvailable" in aListener) @@ -427,8 +430,7 @@ AddonSearchResult.prototype = { toJSON: function() { let json = {}; - for (let property of Object.keys(this)) { - let value = this[property]; + for (let [property, value] of Iterator(this)) { if (property.startsWith("_") || typeof(value) === "function") continue; @@ -451,8 +453,7 @@ AddonSearchResult.prototype = { } } - for (let property of Object.keys(this._unsupportedProperties)) { - let value = this._unsupportedProperties[property]; + for (let [property, value] of Iterator(this._unsupportedProperties)) { if (!property.startsWith("_")) json[property] = value; } @@ -477,11 +478,18 @@ this.AddonRepository = { * Whether caching is currently enabled */ get cacheEnabled() { + // Act as though caching is disabled if there was an unrecoverable error + // openning the database. + if (!AddonDatabase.databaseOk) { + logger.warn("Cache is disabled because database is not OK"); + return false; + } + let preference = PREF_GETADDONS_CACHE_ENABLED; let enabled = false; try { enabled = Services.prefs.getBoolPref(preference); - } catch (e) { + } catch(e) { logger.warn("cacheEnabled: Couldn't get pref: " + preference); } @@ -524,7 +532,7 @@ this.AddonRepository = { * return: promise{integer} resolves with the result of flushing * the AddonRepository database */ - shutdown: function() { + shutdown: function AddonRepo_shutdown() { this.cancelSearch(); this._addons = null; @@ -546,7 +554,7 @@ this.AddonRepository = { return now - lastUpdate; }, - isMetadataStale: function() { + isMetadataStale: function AddonRepo_isMetadataStale() { let threshold = DEFAULT_METADATA_UPDATETHRESHOLD_SEC; try { threshold = Services.prefs.getIntPref(PREF_METADATA_UPDATETHRESHOLD_SEC); @@ -564,7 +572,7 @@ this.AddonRepository = { * @param aCallback * The callback to pass the result back to */ - getCachedAddonByID: Task.async(function*(aId, aCallback) { + getCachedAddonByID: Task.async(function* (aId, aCallback) { if (!aId || !this.cacheEnabled) { aCallback(null); return; @@ -605,7 +613,7 @@ this.AddonRepository = { * Clear and delete the AddonRepository database * @return Promise{null} resolves when the database is deleted */ - _clearCache: function() { + _clearCache: function () { this._addons = null; return AddonDatabase.delete().then(() => new Promise((resolve, reject) => @@ -613,43 +621,44 @@ this.AddonRepository = { ); }, - _repopulateCacheInternal: Task.async(function*(aSendPerformance, aTimeout) { + _repopulateCacheInternal: Task.async(function* (aSendPerformance, aTimeout) { let allAddons = yield new Promise((resolve, reject) => AddonManager.getAllAddons(resolve)); - // Filter the hotfix out of our list of add-ons - allAddons = allAddons.filter(a => a.id != AddonManager.hotfixID); - // Completely remove cache if caching is not enabled if (!this.cacheEnabled) { logger.debug("Clearing cache because it is disabled"); - yield this._clearCache(); - return; + return this._clearCache(); } - let ids = allAddons.map(a => a.id); + // Tycho: let ids = [a.id for (a of allAddons)]; + let ids = []; + for (let a of allAddons) { + ids.push(a.id); + } + logger.debug("Repopulate add-on cache with " + ids.toSource()); + let self = this; let addonsToCache = yield new Promise((resolve, reject) => getAddonsToCache(ids, resolve)); // Completely remove cache if there are no add-ons to cache if (addonsToCache.length == 0) { logger.debug("Clearing cache because 0 add-ons were requested"); - yield this._clearCache(); - return; + return this._clearCache(); } yield new Promise((resolve, reject) => - this._beginGetAddons(addonsToCache, { - searchSucceeded: aAddons => { - this._addons = new Map(); + self._beginGetAddons(addonsToCache, { + searchSucceeded: function repopulateCacheInternal_searchSucceeded(aAddons) { + self._addons = new Map(); for (let addon of aAddons) { - this._addons.set(addon.id, addon); + self._addons.set(addon.id, addon); } AddonDatabase.repopulate(aAddons, resolve); }, - searchFailed: () => { + searchFailed: function repopulateCacheInternal_searchFailed() { logger.warn("Search failed when repopulating cache"); resolve(); } @@ -670,7 +679,7 @@ this.AddonRepository = { * @param aCallback * The optional callback to call once complete */ - cacheAddons: function(aIds, aCallback) { + cacheAddons: function AddonRepo_cacheAddons(aIds, aCallback) { logger.debug("cacheAddons: enabled " + this.cacheEnabled + " IDs " + aIds.toSource()); if (!this.cacheEnabled) { if (aCallback) @@ -678,7 +687,8 @@ this.AddonRepository = { return; } - getAddonsToCache(aIds, aAddons => { + let self = this; + getAddonsToCache(aIds, function cacheAddons_getAddonsToCache(aAddons) { // If there are no add-ons to cache, act as if caching is disabled if (aAddons.length == 0) { if (aCallback) @@ -686,14 +696,14 @@ this.AddonRepository = { return; } - this.getAddonsByIDs(aAddons, { - searchSucceeded: aAddons => { + self.getAddonsByIDs(aAddons, { + searchSucceeded: function cacheAddons_searchSucceeded(aAddons) { for (let addon of aAddons) { - this._addons.set(addon.id, addon); + self._addons.set(addon.id, addon); } AddonDatabase.insertAddons(aAddons, aCallback); }, - searchFailed: () => { + searchFailed: function cacheAddons_searchFailed() { logger.warn("Search failed when adding add-ons to cache"); if (aCallback) aCallback(); @@ -723,7 +733,7 @@ this.AddonRepository = { * The url that can be visited to see recommended add-ons in this repository. * If the corresponding preference is not defined, defaults to about:blank. */ - getRecommendedURL: function() { + getRecommendedURL: function AddonRepo_getRecommendedURL() { let url = this._formatURLPref(PREF_GETADDONS_BROWSERECOMMENDED, {}); return (url != null) ? url : "about:blank"; }, @@ -736,7 +746,7 @@ this.AddonRepository = { * @param aSearchTerms * Search terms used to search the repository */ - getSearchURL: function(aSearchTerms) { + getSearchURL: function AddonRepo_getSearchURL(aSearchTerms) { let url = this._formatURLPref(PREF_GETADDONS_BROWSESEARCHRESULTS, { TERMS : encodeURIComponent(aSearchTerms) }); @@ -747,7 +757,7 @@ this.AddonRepository = { * Cancels the search in progress. If there is no search in progress this * does nothing. */ - cancelSearch: function() { + cancelSearch: function AddonRepo_cancelSearch() { this._searching = false; if (this._request) { this._request.abort(); @@ -765,7 +775,7 @@ this.AddonRepository = { * @param aCallback * The callback to pass results to */ - getAddonsByIDs: function(aIDs, aCallback) { + getAddonsByIDs: function AddonRepo_getAddonsByIDs(aIDs, aCallback) { return this._beginGetAddons(aIDs, aCallback, false); }, @@ -823,12 +833,13 @@ this.AddonRepository = { let url = this._formatURLPref(pref, params); - let handleResults = (aElements, aTotalResults, aCompatData) => { + let self = this; + function handleResults(aElements, aTotalResults, aCompatData) { // Don't use this._parseAddons() so that, for example, // incompatible add-ons are not filtered out let results = []; - for (let i = 0; i < aElements.length && results.length < this._maxResults; i++) { - let result = this._parseAddon(aElements[i], null, aCompatData); + for (let i = 0; i < aElements.length && results.length < self._maxResults; i++) { + let result = self._parseAddon(aElements[i], null, aCompatData); if (result == null) continue; @@ -849,8 +860,7 @@ this.AddonRepository = { // Include any compatibility overrides for addons not hosted by the // remote repository. - for (let id in aCompatData) { - let addonCompat = aCompatData[id]; + for each (let addonCompat in aCompatData) { if (addonCompat.hosted) continue; @@ -867,7 +877,7 @@ this.AddonRepository = { } // aTotalResults irrelevant - this._reportSuccess(results, -1); + self._reportSuccess(results, -1); } this._beginSearch(url, ids.length, aCallback, handleResults, aTimeout); @@ -882,7 +892,7 @@ this.AddonRepository = { * * @return Promise{null} Resolves when the metadata update is complete. */ - backgroundUpdateCheck: function() { + backgroundUpdateCheck: function () { return this._repopulateCacheInternal(true); }, @@ -895,7 +905,7 @@ this.AddonRepository = { * @param aCallback * The callback to pass results to */ - retrieveRecommendedAddons: function(aMaxResults, aCallback) { + retrieveRecommendedAddons: function AddonRepo_retrieveRecommendedAddons(aMaxResults, aCallback) { let url = this._formatURLPref(PREF_GETADDONS_GETRECOMMENDED, { API_VERSION : API_VERSION, @@ -903,10 +913,11 @@ this.AddonRepository = { MAX_RESULTS : 2 * aMaxResults }); - let handleResults = (aElements, aTotalResults) => { - this._getLocalAddonIds(aLocalAddonIds => { + let self = this; + function handleResults(aElements, aTotalResults) { + self._getLocalAddonIds(function retrieveRecommendedAddons_getLocalAddonIds(aLocalAddonIds) { // aTotalResults irrelevant - this._parseAddons(aElements, -1, aLocalAddonIds); + self._parseAddons(aElements, -1, aLocalAddonIds); }); } @@ -924,7 +935,7 @@ this.AddonRepository = { * @param aCallback * The callback to pass results to */ - searchAddons: function(aSearchTerms, aMaxResults, aCallback) { + searchAddons: function AddonRepo_searchAddons(aSearchTerms, aMaxResults, aCallback) { let compatMode = "normal"; if (!AddonManager.checkCompatibility) compatMode = "ignore"; @@ -941,9 +952,10 @@ this.AddonRepository = { let url = this._formatURLPref(PREF_GETADDONS_GETSEARCHRESULTS, substitutions); - let handleResults = (aElements, aTotalResults) => { - this._getLocalAddonIds(aLocalAddonIds => { - this._parseAddons(aElements, aTotalResults, aLocalAddonIds); + let self = this; + function handleResults(aElements, aTotalResults) { + self._getLocalAddonIds(function searchAddons_getLocalAddonIds(aLocalAddonIds) { + self._parseAddons(aElements, aTotalResults, aLocalAddonIds); }); } @@ -951,18 +963,23 @@ this.AddonRepository = { }, // Posts results to the callback - _reportSuccess: function(aResults, aTotalResults) { + _reportSuccess: function AddonRepo_reportSuccess(aResults, aTotalResults) { this._searching = false; this._request = null; // The callback may want to trigger a new search so clear references early - let addons = aResults.map(result => result.addon); + // Tycho: let addons = [result.addon for each(result in aResults)]; + let addons = []; + for each(let result in aResults) { + addons.push(result.addon); + } + let callback = this._callback; this._callback = null; callback.searchSucceeded(addons, addons.length, aTotalResults); }, // Notifies the callback of a failure - _reportFailure: function() { + _reportFailure: function AddonRepo_reportFailure() { this._searching = false; this._request = null; // The callback may want to trigger a new search so clear references early @@ -972,28 +989,28 @@ this.AddonRepository = { }, // Get descendant by unique tag name. Returns null if not unique tag name. - _getUniqueDescendant: function(aElement, aTagName) { + _getUniqueDescendant: function AddonRepo_getUniqueDescendant(aElement, aTagName) { let elementsList = aElement.getElementsByTagName(aTagName); return (elementsList.length == 1) ? elementsList[0] : null; }, // Get direct descendant by unique tag name. // Returns null if not unique tag name. - _getUniqueDirectDescendant: function(aElement, aTagName) { + _getUniqueDirectDescendant: function AddonRepo_getUniqueDirectDescendant(aElement, aTagName) { let elementsList = Array.filter(aElement.children, - aChild => aChild.tagName == aTagName); + function arrayFiltering(aChild) aChild.tagName == aTagName); return (elementsList.length == 1) ? elementsList[0] : null; }, // Parse out trimmed text content. Returns null if text content empty. - _getTextContent: function(aElement) { + _getTextContent: function AddonRepo_getTextContent(aElement) { let textContent = aElement.textContent.trim(); return (textContent.length > 0) ? textContent : null; }, // Parse out trimmed text content of a descendant with the specified tag name // Returns null if the parsing unsuccessful. - _getDescendantTextContent: function(aElement, aTagName) { + _getDescendantTextContent: function AddonRepo_getDescendantTextContent(aElement, aTagName) { let descendant = this._getUniqueDescendant(aElement, aTagName); return (descendant != null) ? this._getTextContent(descendant) : null; }, @@ -1001,7 +1018,7 @@ this.AddonRepository = { // Parse out trimmed text content of a direct descendant with the specified // tag name. // Returns null if the parsing unsuccessful. - _getDirectDescendantTextContent: function(aElement, aTagName) { + _getDirectDescendantTextContent: function AddonRepo_getDirectDescendantTextContent(aElement, aTagName) { let descendant = this._getUniqueDirectDescendant(aElement, aTagName); return (descendant != null) ? this._getTextContent(descendant) : null; }, @@ -1019,7 +1036,7 @@ this.AddonRepository = { * @return Result object containing the parsed AddonSearchResult, xpiURL and * xpiHash if the parsing was successful. Otherwise returns null. */ - _parseAddon: function(aElement, aSkip, aCompatData) { + _parseAddon: function AddonRepo_parseAddon(aElement, aSkip, aCompatData) { let skipIDs = (aSkip && aSkip.ids) ? aSkip.ids : []; let skipSourceURIs = (aSkip && aSkip.sourceURIs) ? aSkip.sourceURIs : []; @@ -1037,6 +1054,7 @@ this.AddonRepository = { if (aCompatData && guid in aCompatData) addon.compatibilityOverrides = aCompatData[guid].compatRanges; + let self = this; for (let node = aElement.firstChild; node; node = node.nextSibling) { if (!(node instanceof Ci.nsIDOMElement)) continue; @@ -1107,8 +1125,8 @@ this.AddonRepository = { case "authors": let authorNodes = node.getElementsByTagName("author"); for (let authorNode of authorNodes) { - let name = this._getDescendantTextContent(authorNode, "name"); - let link = this._getDescendantTextContent(authorNode, "link"); + let name = self._getDescendantTextContent(authorNode, "name"); + let link = self._getDescendantTextContent(authorNode, "link"); if (name == null || link == null) continue; @@ -1126,22 +1144,22 @@ this.AddonRepository = { case "previews": let previewNodes = node.getElementsByTagName("preview"); for (let previewNode of previewNodes) { - let full = this._getUniqueDescendant(previewNode, "full"); + let full = self._getUniqueDescendant(previewNode, "full"); if (full == null) continue; - let fullURL = this._getTextContent(full); + let fullURL = self._getTextContent(full); let fullWidth = full.getAttribute("width"); let fullHeight = full.getAttribute("height"); let thumbnailURL, thumbnailWidth, thumbnailHeight; - let thumbnail = this._getUniqueDescendant(previewNode, "thumbnail"); + let thumbnail = self._getUniqueDescendant(previewNode, "thumbnail"); if (thumbnail) { - thumbnailURL = this._getTextContent(thumbnail); + thumbnailURL = self._getTextContent(thumbnail); thumbnailWidth = thumbnail.getAttribute("width"); thumbnailHeight = thumbnail.getAttribute("height"); } - let caption = this._getDescendantTextContent(previewNode, "caption"); + let caption = self._getDescendantTextContent(previewNode, "caption"); let screenshot = new AddonManagerPrivate.AddonScreenshot(fullURL, fullWidth, fullHeight, thumbnailURL, thumbnailWidth, thumbnailHeight, caption); @@ -1198,7 +1216,7 @@ this.AddonRepository = { break; case "all_compatible_os": let nodes = node.getElementsByTagName("os"); - addon.isPlatformCompatible = Array.some(nodes, function(aNode) { + addon.isPlatformCompatible = Array.some(nodes, function parseAddon_platformCompatFilter(aNode) { let text = aNode.textContent.toLowerCase().trim(); return text == "all" || text == Services.appinfo.OS.toLowerCase(); }); @@ -1244,10 +1262,21 @@ this.AddonRepository = { return result; }, - _parseAddons: function(aElements, aTotalResults, aSkip) { + _parseAddons: function AddonRepo_parseAddons(aElements, aTotalResults, aSkip) { + let self = this; let results = []; - let isSameApplication = aAppNode => this._getTextContent(aAppNode) == Services.appinfo.ID; + function isSameApplication(aAppNode) { +#ifdef MOZ_PHOENIX_EXTENSIONS + if (self._getTextContent(aAppNode) == Services.appinfo.ID || + self._getTextContent(aAppNode) == FIREFOX_ID) { +#else + if (self._getTextContent(aAppNode) == Services.appinfo.ID) { +#endif + return true; + } + return false; + } for (let i = 0; i < aElements.length && results.length < this._maxResults; i++) { let element = aElements[i]; @@ -1257,13 +1286,13 @@ this.AddonRepository = { continue; let applications = tags.getElementsByTagName("appID"); - let compatible = Array.some(applications, aAppNode => { + let compatible = Array.some(applications, function parseAddons_applicationsCompatFilter(aAppNode) { if (!isSameApplication(aAppNode)) return false; let parent = aAppNode.parentNode; - let minVersion = this._getDescendantTextContent(parent, "min_version"); - let maxVersion = this._getDescendantTextContent(parent, "max_version"); + let minVersion = self._getDescendantTextContent(parent, "min_version"); + let maxVersion = self._getDescendantTextContent(parent, "max_version"); if (minVersion == null || maxVersion == null) return false; @@ -1291,7 +1320,7 @@ this.AddonRepository = { // Ignore add-on missing a required attribute let requiredAttributes = ["id", "name", "version", "type", "creator"]; - if (requiredAttributes.some(aAttribute => !result.addon[aAttribute])) + if (requiredAttributes.some(function parseAddons_attributeFilter(aAttribute) !result.addon[aAttribute])) continue; // Ignore add-on with a type AddonManager doesn't understand: @@ -1322,28 +1351,28 @@ this.AddonRepository = { } // Create an AddonInstall for each result - for (let result of results) { - let addon = result.addon; - let callback = aInstall => { + results.forEach(function(aResult) { + let addon = aResult.addon; + let callback = function addonInstallCallback(aInstall) { addon.install = aInstall; pendingResults--; if (pendingResults == 0) - this._reportSuccess(results, aTotalResults); + self._reportSuccess(results, aTotalResults); } - if (result.xpiURL) { - AddonManager.getInstallForURL(result.xpiURL, callback, - "application/x-xpinstall", result.xpiHash, + if (aResult.xpiURL) { + AddonManager.getInstallForURL(aResult.xpiURL, callback, + "application/x-xpinstall", aResult.xpiHash, addon.name, addon.icons, addon.version); } else { callback(null); } - } + }); }, // Parses addon_compatibility nodes, that describe compatibility overrides. - _parseAddonCompatElement: function(aResultObj, aElement) { + _parseAddonCompatElement: function AddonRepo_parseAddonCompatElement(aResultObj, aElement) { let guid = this._getDescendantTextContent(aElement, "guid"); if (!guid) { logger.debug("Compatibility override is missing guid."); @@ -1416,7 +1445,7 @@ this.AddonRepository = { let rangeNodes = aElement.querySelectorAll("version_ranges > version_range"); compat.compatRanges = Array.map(rangeNodes, parseRangeNode.bind(this)) - .filter(aItem => !!aItem); + .filter(function compatRangesFilter(aItem) !!aItem); if (compat.compatRanges.length == 0) return; @@ -1424,7 +1453,7 @@ this.AddonRepository = { }, // Parses addon_compatibility elements. - _parseAddonCompatData: function(aElements) { + _parseAddonCompatData: function AddonRepo_parseAddonCompatData(aElements) { let compatData = {}; Array.forEach(aElements, this._parseAddonCompatElement.bind(this, compatData)); return compatData; @@ -1445,7 +1474,7 @@ this.AddonRepository = { logger.debug("Requesting " + aURI); - this._request = new ServiceRequest(); + this._request = new XHRequest(); this._request.mozBackgroundRequest = true; this._request.open("GET", aURI, true); this._request.overrideMimeType("text/xml"); @@ -1484,21 +1513,28 @@ this.AddonRepository = { // Gets the id's of local add-ons, and the sourceURI's of local installs, // passing the results to aCallback - _getLocalAddonIds: function(aCallback) { + _getLocalAddonIds: function AddonRepo_getLocalAddonIds(aCallback) { + let self = this; let localAddonIds = {ids: null, sourceURIs: null}; - AddonManager.getAllAddons(function(aAddons) { - localAddonIds.ids = aAddons.map(a => a.id); + AddonManager.getAllAddons(function getLocalAddonIds_getAllAddons(aAddons) { + // Tycho: localAddonIds.ids = [a.id for each (a in aAddons)]; + localAddonIds.ids = []; + + for each(let a in aAddons) { + localAddonIds.ids.push(a.id); + } + if (localAddonIds.sourceURIs) aCallback(localAddonIds); }); - AddonManager.getAllInstalls(function(aInstalls) { + AddonManager.getAllInstalls(function getLocalAddonIds_getAllInstalls(aInstalls) { localAddonIds.sourceURIs = []; - for (let install of aInstalls) { - if (install.state != AddonManager.STATE_AVAILABLE) - localAddonIds.sourceURIs.push(install.sourceURI.spec); - } + aInstalls.forEach(function(aInstall) { + if (aInstall.state != AddonManager.STATE_AVAILABLE) + localAddonIds.sourceURIs.push(aInstall.sourceURI.spec); + }); if (localAddonIds.ids) aCallback(localAddonIds); @@ -1506,16 +1542,16 @@ this.AddonRepository = { }, // Create url from preference, returning null if preference does not exist - _formatURLPref: function(aPreference, aSubstitutions) { + _formatURLPref: function AddonRepo_formatURLPref(aPreference, aSubstitutions) { let url = null; try { url = Services.prefs.getCharPref(aPreference); - } catch (e) { + } catch(e) { logger.warn("_formatURLPref: Couldn't get pref: " + aPreference); return null; } - url = url.replace(/%([A-Z_]+)%/g, function(aMatch, aKey) { + url = url.replace(/%([A-Z_]+)%/g, function urlSubstitution(aMatch, aKey) { return (aKey in aSubstitutions) ? aSubstitutions[aKey] : aMatch; }); @@ -1524,7 +1560,7 @@ this.AddonRepository = { // Find a AddonCompatibilityOverride that matches a given aAddonVersion and // application/platform version. - findMatchingCompatOverride: function(aAddonVersion, + findMatchingCompatOverride: function AddonRepo_findMatchingCompatOverride(aAddonVersion, aCompatOverrides, aAppVersion, aPlatformVersion) { @@ -1552,6 +1588,9 @@ this.AddonRepository = { }; var AddonDatabase = { + // false if there was an unrecoverable error opening the database + databaseOk: true, + connectionPromise: null, // the in-memory database DB: BLANK_DB(), @@ -1594,12 +1633,8 @@ var AddonDatabase = { schema < DB_MIN_JSON_SCHEMA) { throw new Error("Invalid schema value."); } - } catch (e) { - if (e instanceof OS.File.Error && e.becauseNoSuchFile) { - logger.debug("No " + FILE_DATABASE + " found."); - } else { - logger.error(`Malformed ${FILE_DATABASE}: ${e} - resetting to empty`); - } + } catch (e if e instanceof OS.File.Error && e.becauseNoSuchFile) { + logger.debug("No " + FILE_DATABASE + " found."); // Create a blank addons.json file this._saveDBToDisk(); @@ -1618,9 +1653,14 @@ var AddonDatabase = { yield this._insertAddons(results); } + Services.prefs.setIntPref(PREF_GETADDONS_DB_SCHEMA, DB_SCHEMA); } - Services.prefs.setIntPref(PREF_GETADDONS_DB_SCHEMA, DB_SCHEMA); + return this.DB; + } catch (e) { + logger.error("Malformed " + FILE_DATABASE + ": " + e); + this.databaseOk = false; + return this.DB; } @@ -1657,7 +1697,9 @@ var AddonDatabase = { * An optional boolean to skip flushing data to disk. Useful * when the database is going to be deleted afterwards. */ - shutdown: function(aSkipFlush) { + shutdown: function AD_shutdown(aSkipFlush) { + this.databaseOk = true; + if (!this.connectionPromise) { return Promise.resolve(); } @@ -1666,8 +1708,9 @@ var AddonDatabase = { if (aSkipFlush) { return Promise.resolve(); + } else { + return this.Writer.flush(); } - return this.Writer.flush(); }, /** @@ -1678,7 +1721,7 @@ var AddonDatabase = { * An optional callback to call once complete * @return Promise{null} resolves when the database has been deleted */ - delete: function(aCallback) { + delete: function AD_delete(aCallback) { this.DB = BLANK_DB(); this._deleting = this.Writer.flush() @@ -1693,7 +1736,7 @@ var AddonDatabase = { return this._deleting; }, - toJSON: function() { + toJSON: function AD_toJSON() { let json = { schema: this.DB.schema, addons: [] @@ -1738,7 +1781,7 @@ var AddonDatabase = { * @return: Promise{Map} * Resolves when the add-ons are retrieved from the database */ - retrieveStoredData: function() { + retrieveStoredData: function (){ return this.openConnection().then(db => db.addons); }, @@ -1751,9 +1794,9 @@ var AddonDatabase = { * @param aCallback * An optional callback to call once complete */ - repopulate: function(aAddons, aCallback) { + repopulate: function AD_repopulate(aAddons, aCallback) { this.DB.addons.clear(); - this.insertAddons(aAddons, function() { + this.insertAddons(aAddons, function repopulate_insertAddons() { let now = Math.round(Date.now() / 1000); logger.debug("Cache repopulated, setting " + PREF_METADATA_LASTUPDATE + " to " + now); Services.prefs.setIntPref(PREF_METADATA_LASTUPDATE, now); @@ -1770,12 +1813,12 @@ var AddonDatabase = { * @param aCallback * An optional callback to call once complete */ - insertAddons: Task.async(function*(aAddons, aCallback) { + insertAddons: Task.async(function* (aAddons, aCallback) { yield this.openConnection(); yield this._insertAddons(aAddons, aCallback); }), - _insertAddons: Task.async(function*(aAddons, aCallback) { + _insertAddons: Task.async(function* (aAddons, aCallback) { for (let addon of aAddons) { this._insertAddon(addon); } @@ -1794,7 +1837,7 @@ var AddonDatabase = { * @param aCallback * The callback to call once complete */ - _insertAddon: function(aAddon) { + _insertAddon: function AD__insertAddon(aAddon) { let newAddon = this._parseAddon(aAddon); if (!newAddon || !newAddon.id || @@ -1812,7 +1855,7 @@ var AddonDatabase = { * The object to parse * @return Returns an AddonSearchResult object. */ - _parseAddon: function(aObj) { + _parseAddon: function (aObj) { if (aObj instanceof AddonSearchResult) return aObj; @@ -1822,7 +1865,7 @@ var AddonDatabase = { let addon = new AddonSearchResult(id); - for (let expectedProperty of Object.keys(AddonSearchResult.prototype)) { + for (let [expectedProperty,] of Iterator(AddonSearchResult.prototype)) { if (!(expectedProperty in aObj) || typeof(aObj[expectedProperty]) === "function") continue; @@ -1870,8 +1913,8 @@ var AddonDatabase = { case "icons": if (!addon.icons) addon.icons = {}; - for (let size of Object.keys(aObj.icons)) { - addon.icons[size] = aObj.icons[size]; + for (let [size, url] of Iterator(aObj.icons)) { + addon.icons[size] = url; } break; @@ -1937,7 +1980,7 @@ var AddonDatabase = { * The JS object to use * @return The created developer */ - _makeDeveloper: function(aObj) { + _makeDeveloper: function (aObj) { let name = aObj.name; let url = aObj.url; return new AddonManagerPrivate.AddonAuthor(name, url); @@ -1951,7 +1994,7 @@ var AddonDatabase = { * The JS object to use * @return The created screenshot */ - _makeScreenshot: function(aObj) { + _makeScreenshot: function (aObj) { let url = aObj.url; let width = aObj.width; let height = aObj.height; @@ -1971,7 +2014,7 @@ var AddonDatabase = { * The JS object to use * @return The created CompatibilityOverride */ - _makeCompatOverride: function(aObj) { + _makeCompatOverride: function (aObj) { let type = aObj.type; let minVersion = aObj.minVersion; let maxVersion = aObj.maxVersion; diff --git a/toolkit/mozapps/extensions/internal/AddonRepository_SQLiteMigrator.jsm b/toolkit/mozapps/extensions/internal/AddonRepository_SQLiteMigrator.jsm index e3479643b..66147b9aa 100644 --- a/toolkit/mozapps/extensions/internal/AddonRepository_SQLiteMigrator.jsm +++ b/toolkit/mozapps/extensions/internal/AddonRepository_SQLiteMigrator.jsm @@ -10,7 +10,6 @@ const Cu = Components.utils; Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/AddonManager.jsm"); -/* globals AddonManagerPrivate*/ Cu.import("resource://gre/modules/FileUtils.jsm"); const KEY_PROFILEDIR = "ProfD"; @@ -61,7 +60,11 @@ this.AddonRepository_SQLiteMigrator = { this._retrieveStoredData((results) => { this._closeConnection(); - let resultArray = Object.keys(results).map(k => results[k]); + // Tycho: let resultArray = [addon for ([,addon] of Iterator(results))]; + let resultArray = []; + for (let [,addon] of Iterator(results)) { + resultArray.push(addon); + } logger.debug(resultArray.length + " addons imported.") aCallback(resultArray); }); @@ -74,7 +77,7 @@ this.AddonRepository_SQLiteMigrator = { * * @return bool Whether the DB was opened successfully. */ - _openConnection: function() { + _openConnection: function AD_openConnection() { delete this.connection; let dbfile = FileUtils.getFile(KEY_PROFILEDIR, [FILE_DATABASE], true); @@ -142,10 +145,8 @@ this.AddonRepository_SQLiteMigrator = { }, _closeConnection: function() { - for (let key in this.asyncStatementsCache) { - let stmt = this.asyncStatementsCache[key]; + for each (let stmt in this.asyncStatementsCache) stmt.finalize(); - } this.asyncStatementsCache = {}; if (this.connection) @@ -161,23 +162,24 @@ this.AddonRepository_SQLiteMigrator = { * @param aCallback * The callback to pass the add-ons back to */ - _retrieveStoredData: function(aCallback) { + _retrieveStoredData: function AD_retrieveStoredData(aCallback) { + let self = this; let addons = {}; // Retrieve all data from the addon table - let getAllAddons = () => { - this.getAsyncStatement("getAllAddons").executeAsync({ - handleResult: aResults => { + function getAllAddons() { + self.getAsyncStatement("getAllAddons").executeAsync({ + handleResult: function getAllAddons_handleResult(aResults) { let row = null; while ((row = aResults.getNextRow())) { let internal_id = row.getResultByName("internal_id"); - addons[internal_id] = this._makeAddonFromAsyncRow(row); + addons[internal_id] = self._makeAddonFromAsyncRow(row); } }, - handleError: this.asyncErrorLogger, + handleError: self.asyncErrorLogger, - handleCompletion: function(aReason) { + handleCompletion: function getAllAddons_handleCompletion(aReason) { if (aReason != Ci.mozIStorageStatementCallback.REASON_FINISHED) { logger.error("Error retrieving add-ons from database. Returning empty results"); aCallback({}); @@ -190,9 +192,9 @@ this.AddonRepository_SQLiteMigrator = { } // Retrieve all data from the developer table - let getAllDevelopers = () => { - this.getAsyncStatement("getAllDevelopers").executeAsync({ - handleResult: aResults => { + function getAllDevelopers() { + self.getAsyncStatement("getAllDevelopers").executeAsync({ + handleResult: function getAllDevelopers_handleResult(aResults) { let row = null; while ((row = aResults.getNextRow())) { let addon_internal_id = row.getResultByName("addon_internal_id"); @@ -205,13 +207,13 @@ this.AddonRepository_SQLiteMigrator = { if (!addon.developers) addon.developers = []; - addon.developers.push(this._makeDeveloperFromAsyncRow(row)); + addon.developers.push(self._makeDeveloperFromAsyncRow(row)); } }, - handleError: this.asyncErrorLogger, + handleError: self.asyncErrorLogger, - handleCompletion: function(aReason) { + handleCompletion: function getAllDevelopers_handleCompletion(aReason) { if (aReason != Ci.mozIStorageStatementCallback.REASON_FINISHED) { logger.error("Error retrieving developers from database. Returning empty results"); aCallback({}); @@ -224,9 +226,9 @@ this.AddonRepository_SQLiteMigrator = { } // Retrieve all data from the screenshot table - let getAllScreenshots = () => { - this.getAsyncStatement("getAllScreenshots").executeAsync({ - handleResult: aResults => { + function getAllScreenshots() { + self.getAsyncStatement("getAllScreenshots").executeAsync({ + handleResult: function getAllScreenshots_handleResult(aResults) { let row = null; while ((row = aResults.getNextRow())) { let addon_internal_id = row.getResultByName("addon_internal_id"); @@ -238,13 +240,13 @@ this.AddonRepository_SQLiteMigrator = { let addon = addons[addon_internal_id]; if (!addon.screenshots) addon.screenshots = []; - addon.screenshots.push(this._makeScreenshotFromAsyncRow(row)); + addon.screenshots.push(self._makeScreenshotFromAsyncRow(row)); } }, - handleError: this.asyncErrorLogger, + handleError: self.asyncErrorLogger, - handleCompletion: function(aReason) { + handleCompletion: function getAllScreenshots_handleCompletion(aReason) { if (aReason != Ci.mozIStorageStatementCallback.REASON_FINISHED) { logger.error("Error retrieving screenshots from database. Returning empty results"); aCallback({}); @@ -256,9 +258,9 @@ this.AddonRepository_SQLiteMigrator = { }); } - let getAllCompatOverrides = () => { - this.getAsyncStatement("getAllCompatOverrides").executeAsync({ - handleResult: aResults => { + function getAllCompatOverrides() { + self.getAsyncStatement("getAllCompatOverrides").executeAsync({ + handleResult: function getAllCompatOverrides_handleResult(aResults) { let row = null; while ((row = aResults.getNextRow())) { let addon_internal_id = row.getResultByName("addon_internal_id"); @@ -270,13 +272,13 @@ this.AddonRepository_SQLiteMigrator = { let addon = addons[addon_internal_id]; if (!addon.compatibilityOverrides) addon.compatibilityOverrides = []; - addon.compatibilityOverrides.push(this._makeCompatOverrideFromAsyncRow(row)); + addon.compatibilityOverrides.push(self._makeCompatOverrideFromAsyncRow(row)); } }, - handleError: this.asyncErrorLogger, + handleError: self.asyncErrorLogger, - handleCompletion: function(aReason) { + handleCompletion: function getAllCompatOverrides_handleCompletion(aReason) { if (aReason != Ci.mozIStorageStatementCallback.REASON_FINISHED) { logger.error("Error retrieving compatibility overrides from database. Returning empty results"); aCallback({}); @@ -288,9 +290,9 @@ this.AddonRepository_SQLiteMigrator = { }); } - let getAllIcons = () => { - this.getAsyncStatement("getAllIcons").executeAsync({ - handleResult: aResults => { + function getAllIcons() { + self.getAsyncStatement("getAllIcons").executeAsync({ + handleResult: function getAllIcons_handleResult(aResults) { let row = null; while ((row = aResults.getNextRow())) { let addon_internal_id = row.getResultByName("addon_internal_id"); @@ -300,16 +302,16 @@ this.AddonRepository_SQLiteMigrator = { } let addon = addons[addon_internal_id]; - let { size, url } = this._makeIconFromAsyncRow(row); + let { size, url } = self._makeIconFromAsyncRow(row); addon.icons[size] = url; if (size == 32) addon.iconURL = url; } }, - handleError: this.asyncErrorLogger, + handleError: self.asyncErrorLogger, - handleCompletion: function(aReason) { + handleCompletion: function getAllIcons_handleCompletion(aReason) { if (aReason != Ci.mozIStorageStatementCallback.REASON_FINISHED) { logger.error("Error retrieving icons from database. Returning empty results"); aCallback({}); @@ -317,10 +319,8 @@ this.AddonRepository_SQLiteMigrator = { } let returnedAddons = {}; - for (let id in addons) { - let addon = addons[id]; + for each (let addon in addons) returnedAddons[addon.id] = addon; - } aCallback(returnedAddons); } }); @@ -342,7 +342,7 @@ this.AddonRepository_SQLiteMigrator = { * @return a mozIStorageAsyncStatement for the SQL corresponding to the * unique key */ - getAsyncStatement: function(aKey) { + getAsyncStatement: function AD_getAsyncStatement(aKey) { if (aKey in this.asyncStatementsCache) return this.asyncStatementsCache[aKey]; @@ -389,7 +389,7 @@ this.AddonRepository_SQLiteMigrator = { * The asynchronous row to use * @return The created add-on */ - _makeAddonFromAsyncRow: function(aRow) { + _makeAddonFromAsyncRow: function AD__makeAddonFromAsyncRow(aRow) { // This is intentionally not an AddonSearchResult object in order // to allow AddonDatabase._parseAddon to parse it, same as if it // was read from the JSON database. @@ -398,7 +398,7 @@ this.AddonRepository_SQLiteMigrator = { for (let prop of PROP_SINGLE) { addon[prop] = aRow.getResultByName(prop) - } + }; return addon; }, @@ -410,7 +410,7 @@ this.AddonRepository_SQLiteMigrator = { * The asynchronous row to use * @return The created developer */ - _makeDeveloperFromAsyncRow: function(aRow) { + _makeDeveloperFromAsyncRow: function AD__makeDeveloperFromAsyncRow(aRow) { let name = aRow.getResultByName("name"); let url = aRow.getResultByName("url") return new AddonManagerPrivate.AddonAuthor(name, url); @@ -423,7 +423,7 @@ this.AddonRepository_SQLiteMigrator = { * The asynchronous row to use * @return The created screenshot */ - _makeScreenshotFromAsyncRow: function(aRow) { + _makeScreenshotFromAsyncRow: function AD__makeScreenshotFromAsyncRow(aRow) { let url = aRow.getResultByName("url"); let width = aRow.getResultByName("width"); let height = aRow.getResultByName("height"); @@ -442,7 +442,7 @@ this.AddonRepository_SQLiteMigrator = { * The asynchronous row to use * @return The created CompatibilityOverride */ - _makeCompatOverrideFromAsyncRow: function(aRow) { + _makeCompatOverrideFromAsyncRow: function AD_makeCompatOverrideFromAsyncRow(aRow) { let type = aRow.getResultByName("type"); let minVersion = aRow.getResultByName("minVersion"); let maxVersion = aRow.getResultByName("maxVersion"); @@ -464,7 +464,7 @@ this.AddonRepository_SQLiteMigrator = { * The asynchronous row to use * @return An object containing the size and URL of the icon */ - _makeIconFromAsyncRow: function(aRow) { + _makeIconFromAsyncRow: function AD_makeIconFromAsyncRow(aRow) { let size = aRow.getResultByName("size"); let url = aRow.getResultByName("url"); return { size: size, url: url }; @@ -478,7 +478,7 @@ this.AddonRepository_SQLiteMigrator = { * @param aErrorString * An error message */ - logSQLError: function(aError, aErrorString) { + logSQLError: function AD_logSQLError(aError, aErrorString) { logger.error("SQL error " + aError + ": " + aErrorString); }, @@ -488,14 +488,14 @@ this.AddonRepository_SQLiteMigrator = { * @param aError * A mozIStorageError to log */ - asyncErrorLogger: function(aError) { + asyncErrorLogger: function AD_asyncErrorLogger(aError) { logger.error("Async SQL error " + aError.result + ": " + aError.message); }, /** * Synchronously creates the triggers in the database. */ - _createTriggers: function() { + _createTriggers: function AD__createTriggers() { this.connection.executeSimpleSQL("DROP TRIGGER IF EXISTS delete_addon"); this.connection.executeSimpleSQL("CREATE TRIGGER delete_addon AFTER DELETE " + "ON addon BEGIN " + @@ -509,7 +509,7 @@ this.AddonRepository_SQLiteMigrator = { /** * Synchronously creates the indices in the database. */ - _createIndices: function() { + _createIndices: function AD__createIndices() { this.connection.executeSimpleSQL("CREATE INDEX IF NOT EXISTS developer_idx " + "ON developer (addon_internal_id)"); this.connection.executeSimpleSQL("CREATE INDEX IF NOT EXISTS screenshot_idx " + diff --git a/toolkit/mozapps/extensions/internal/AddonTestUtils.jsm b/toolkit/mozapps/extensions/internal/AddonTestUtils.jsm deleted file mode 100644 index 6422929b1..000000000 --- a/toolkit/mozapps/extensions/internal/AddonTestUtils.jsm +++ /dev/null @@ -1,1231 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -/* eslint "mozilla/no-aArgs": 1 */ -/* eslint "no-unused-vars": [2, {"args": "none", "varsIgnorePattern": "^(Cc|Ci|Cr|Cu|EXPORTED_SYMBOLS)$"}] */ -/* eslint "semi": [2, "always"] */ -/* eslint "valid-jsdoc": [2, {requireReturn: false}] */ - -var EXPORTED_SYMBOLS = ["AddonTestUtils", "MockAsyncShutdown"]; - -const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; - -const CERTDB_CONTRACTID = "@mozilla.org/security/x509certdb;1"; -const CERTDB_CID = Components.ID("{fb0bbc5c-452e-4783-b32c-80124693d871}"); - - -Cu.importGlobalProperties(["fetch", "TextEncoder"]); - -Cu.import("resource://gre/modules/AsyncShutdown.jsm"); -Cu.import("resource://gre/modules/FileUtils.jsm"); -Cu.import("resource://gre/modules/NetUtil.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/Task.jsm"); -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); - -const {EventEmitter} = Cu.import("resource://devtools/shared/event-emitter.js", {}); -const {OS} = Cu.import("resource://gre/modules/osfile.jsm", {}); - -XPCOMUtils.defineLazyModuleGetter(this, "Extension", - "resource://gre/modules/Extension.jsm"); - -XPCOMUtils.defineLazyServiceGetter(this, "rdfService", - "@mozilla.org/rdf/rdf-service;1", "nsIRDFService"); -XPCOMUtils.defineLazyServiceGetter(this, "uuidGen", - "@mozilla.org/uuid-generator;1", "nsIUUIDGenerator"); - - -XPCOMUtils.defineLazyGetter(this, "AppInfo", () => { - let AppInfo = {}; - Cu.import("resource://testing-common/AppInfo.jsm", AppInfo); - return AppInfo; -}); - - -const ArrayBufferInputStream = Components.Constructor( - "@mozilla.org/io/arraybuffer-input-stream;1", - "nsIArrayBufferInputStream", "setData"); - -const nsFile = Components.Constructor( - "@mozilla.org/file/local;1", - "nsIFile", "initWithPath"); - -const RDFXMLParser = Components.Constructor( - "@mozilla.org/rdf/xml-parser;1", - "nsIRDFXMLParser", "parseString"); - -const RDFDataSource = Components.Constructor( - "@mozilla.org/rdf/datasource;1?name=in-memory-datasource", - "nsIRDFDataSource"); - -const ZipReader = Components.Constructor( - "@mozilla.org/libjar/zip-reader;1", - "nsIZipReader", "open"); - -const ZipWriter = Components.Constructor( - "@mozilla.org/zipwriter;1", - "nsIZipWriter", "open"); - - -// We need some internal bits of AddonManager -var AMscope = Cu.import("resource://gre/modules/AddonManager.jsm", {}); -var {AddonManager, AddonManagerPrivate} = AMscope; - - -// Mock out AddonManager's reference to the AsyncShutdown module so we can shut -// down AddonManager from the test -var MockAsyncShutdown = { - hook: null, - status: null, - profileBeforeChange: { - addBlocker: function(name, blocker, options) { - MockAsyncShutdown.hook = blocker; - MockAsyncShutdown.status = options.fetchState; - } - }, - // We can use the real Barrier - Barrier: AsyncShutdown.Barrier, -}; - -AMscope.AsyncShutdown = MockAsyncShutdown; - - -/** - * Escapes any occurances of &, ", < or > with XML entities. - * - * @param {string} str - * The string to escape. - * @return {string} The escaped string. - */ -function escapeXML(str) { - let replacements = {"&": "&", '"': """, "'": "'", "<": "<", ">": ">"}; - return String(str).replace(/[&"''<>]/g, m => replacements[m]); -} - -/** - * A tagged template function which escapes any XML metacharacters in - * interpolated values. - * - * @param {Array<string>} strings - * An array of literal strings extracted from the templates. - * @param {Array} values - * An array of interpolated values extracted from the template. - * @returns {string} - * The result of the escaped values interpolated with the literal - * strings. - */ -function escaped(strings, ...values) { - let result = []; - - for (let [i, string] of strings.entries()) { - result.push(string); - if (i < values.length) - result.push(escapeXML(values[i])); - } - - return result.join(""); -} - - -class AddonsList { - constructor(extensionsINI) { - this.multiprocessIncompatibleIDs = new Set(); - - if (!extensionsINI.exists()) { - this.extensions = []; - this.themes = []; - return; - } - - let factory = Cc["@mozilla.org/xpcom/ini-parser-factory;1"] - .getService(Ci.nsIINIParserFactory); - - let parser = factory.createINIParser(extensionsINI); - - function readDirectories(section) { - var dirs = []; - var keys = parser.getKeys(section); - for (let key of XPCOMUtils.IterStringEnumerator(keys)) { - let descriptor = parser.getString(section, key); - - let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); - try { - file.persistentDescriptor = descriptor; - } catch (e) { - // Throws if the directory doesn't exist, we can ignore this since the - // platform will too. - continue; - } - dirs.push(file); - } - return dirs; - } - - this.extensions = readDirectories("ExtensionDirs"); - this.themes = readDirectories("ThemeDirs"); - - var keys = parser.getKeys("MultiprocessIncompatibleExtensions"); - for (let key of XPCOMUtils.IterStringEnumerator(keys)) { - let id = parser.getString("MultiprocessIncompatibleExtensions", key); - this.multiprocessIncompatibleIDs.add(id); - } - } - - hasItem(type, dir, id) { - var path = dir.clone(); - path.append(id); - - var xpiPath = dir.clone(); - xpiPath.append(`${id}.xpi`); - - return this[type].some(file => { - if (!file.exists()) - throw new Error(`Non-existent path found in extensions.ini: ${file.path}`); - - if (file.isDirectory()) - return file.equals(path); - if (file.isFile()) - return file.equals(xpiPath); - return false; - }); - } - - isMultiprocessIncompatible(id) { - return this.multiprocessIncompatibleIDs.has(id); - } - - hasTheme(dir, id) { - return this.hasItem("themes", dir, id); - } - - hasExtension(dir, id) { - return this.hasItem("extensions", dir, id); - } -} - -var AddonTestUtils = { - addonIntegrationService: null, - addonsList: null, - appInfo: null, - extensionsINI: null, - testUnpacked: false, - useRealCertChecks: false, - - init(testScope) { - this.testScope = testScope; - - // Get the profile directory for tests to use. - this.profileDir = testScope.do_get_profile(); - - this.extensionsINI = this.profileDir.clone(); - this.extensionsINI.append("extensions.ini"); - - // Register a temporary directory for the tests. - this.tempDir = this.profileDir.clone(); - this.tempDir.append("temp"); - this.tempDir.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY); - this.registerDirectory("TmpD", this.tempDir); - - // Create a replacement app directory for the tests. - const appDirForAddons = this.profileDir.clone(); - appDirForAddons.append("appdir-addons"); - appDirForAddons.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY); - this.registerDirectory("XREAddonAppDir", appDirForAddons); - - - // Enable more extensive EM logging - Services.prefs.setBoolPref("extensions.logging.enabled", true); - - // By default only load extensions from the profile install location - Services.prefs.setIntPref("extensions.enabledScopes", AddonManager.SCOPE_PROFILE); - - // By default don't disable add-ons from any scope - Services.prefs.setIntPref("extensions.autoDisableScopes", 0); - - // By default, don't cache add-ons in AddonRepository.jsm - Services.prefs.setBoolPref("extensions.getAddons.cache.enabled", false); - - // Disable the compatibility updates window by default - Services.prefs.setBoolPref("extensions.showMismatchUI", false); - - // Point update checks to the local machine for fast failures - Services.prefs.setCharPref("extensions.update.url", "http://127.0.0.1/updateURL"); - Services.prefs.setCharPref("extensions.update.background.url", "http://127.0.0.1/updateBackgroundURL"); - Services.prefs.setCharPref("extensions.blocklist.url", "http://127.0.0.1/blocklistURL"); - - // By default ignore bundled add-ons - Services.prefs.setBoolPref("extensions.installDistroAddons", false); - - // By default don't check for hotfixes - Services.prefs.setCharPref("extensions.hotfix.id", ""); - - // Ensure signature checks are enabled by default - Services.prefs.setBoolPref("xpinstall.signatures.required", true); - - - // Write out an empty blocklist.xml file to the profile to ensure nothing - // is blocklisted by default - var blockFile = OS.Path.join(this.profileDir.path, "blocklist.xml"); - - var data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + - "<blocklist xmlns=\"http://www.mozilla.org/2006/addons-blocklist\">\n" + - "</blocklist>\n"; - - this.awaitPromise(OS.File.writeAtomic(blockFile, new TextEncoder().encode(data))); - - - // Make sure that a given path does not exist - function pathShouldntExist(file) { - if (file.exists()) { - throw new Error(`Test cleanup: path ${file.path} exists when it should not`); - } - } - - testScope.do_register_cleanup(() => { - for (let file of this.tempXPIs) { - if (file.exists()) - file.remove(false); - } - - // Check that the temporary directory is empty - var dirEntries = this.tempDir.directoryEntries - .QueryInterface(Ci.nsIDirectoryEnumerator); - var entries = []; - while (dirEntries.hasMoreElements()) - entries.push(dirEntries.nextFile.leafName); - if (entries.length) - throw new Error(`Found unexpected files in temporary directory: ${entries.join(", ")}`); - - dirEntries.close(); - - try { - appDirForAddons.remove(true); - } catch (ex) { - testScope.do_print(`Got exception removing addon app dir: ${ex}`); - } - - // ensure no leftover files in the system addon upgrade location - let featuresDir = this.profileDir.clone(); - featuresDir.append("features"); - // upgrade directories will be in UUID folders under features/ - let systemAddonDirs = []; - if (featuresDir.exists()) { - let featuresDirEntries = featuresDir.directoryEntries - .QueryInterface(Ci.nsIDirectoryEnumerator); - while (featuresDirEntries.hasMoreElements()) { - let entry = featuresDirEntries.getNext(); - entry.QueryInterface(Components.interfaces.nsIFile); - systemAddonDirs.push(entry); - } - - systemAddonDirs.map(dir => { - dir.append("stage"); - pathShouldntExist(dir); - }); - } - - // ensure no leftover files in the user addon location - let testDir = this.profileDir.clone(); - testDir.append("extensions"); - testDir.append("trash"); - pathShouldntExist(testDir); - - testDir.leafName = "staged"; - pathShouldntExist(testDir); - - return this.promiseShutdownManager(); - }); - }, - - /** - * Helper to spin the event loop until a promise resolves or rejects - * - * @param {Promise} promise - * The promise to wait on. - * @returns {*} The promise's resolution value. - * @throws The promise's rejection value, if it rejects. - */ - awaitPromise(promise) { - let done = false; - let result; - let error; - promise.then( - val => { result = val; }, - err => { error = err; } - ).then(() => { - done = true; - }); - - while (!done) - Services.tm.mainThread.processNextEvent(true); - - if (error !== undefined) - throw error; - return result; - }, - - createAppInfo(ID, name, version, platformVersion = "1.0") { - AppInfo.updateAppInfo({ - ID, name, version, platformVersion, - crashReporter: true, - extraProps: { - browserTabsRemoteAutostart: false, - }, - }); - this.appInfo = AppInfo.getAppInfo(); - }, - - getManifestURI(file) { - if (file.isDirectory()) { - file.append("install.rdf"); - if (file.exists()) { - return NetUtil.newURI(file); - } - - file.leafName = "manifest.json"; - if (file.exists()) - return NetUtil.newURI(file); - - throw new Error("No manifest file present"); - } - - let zip = ZipReader(file); - try { - let uri = NetUtil.newURI(file); - - if (zip.hasEntry("install.rdf")) { - return NetUtil.newURI(`jar:${uri.spec}!/install.rdf`); - } - - if (zip.hasEntry("manifest.json")) { - return NetUtil.newURI(`jar:${uri.spec}!/manifest.json`); - } - - throw new Error("No manifest file present"); - } finally { - zip.close(); - } - }, - - getIDFromManifest: Task.async(function*(manifestURI) { - let body = yield fetch(manifestURI.spec); - - if (manifestURI.spec.endsWith(".rdf")) { - let data = yield body.text(); - - let ds = new RDFDataSource(); - new RDFXMLParser(ds, manifestURI, data); - - let rdfID = ds.GetTarget(rdfService.GetResource("urn:mozilla:install-manifest"), - rdfService.GetResource("http://www.mozilla.org/2004/em-rdf#id"), - true); - return rdfID.QueryInterface(Ci.nsIRDFLiteral).Value; - } - - let manifest = yield body.json(); - try { - return manifest.applications.gecko.id; - } catch (e) { - // IDs for WebExtensions are extracted from the certificate when - // not present in the manifest, so just generate a random one. - return uuidGen.generateUUID().number; - } - }), - - overrideCertDB() { - // Unregister the real database. This only works because the add-ons manager - // hasn't started up and grabbed the certificate database yet. - let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); - let factory = registrar.getClassObject(CERTDB_CID, Ci.nsIFactory); - registrar.unregisterFactory(CERTDB_CID, factory); - - // Get the real DB - let realCertDB = factory.createInstance(null, Ci.nsIX509CertDB); - - - let verifyCert = Task.async(function*(file, result, cert, callback) { - if (result == Cr.NS_ERROR_SIGNED_JAR_NOT_SIGNED && - !this.useRealCertChecks && callback.wrappedJSObject) { - // Bypassing XPConnect allows us to create a fake x509 certificate from JS - callback = callback.wrappedJSObject; - - try { - let manifestURI = this.getManifestURI(file); - - let id = yield this.getIDFromManifest(manifestURI); - - let fakeCert = {commonName: id}; - - return [callback, Cr.NS_OK, fakeCert]; - } catch (e) { - // If there is any error then just pass along the original results - } finally { - // Make sure to close the open zip file or it will be locked. - if (file.isFile()) - Services.obs.notifyObservers(file, "flush-cache-entry", "cert-override"); - } - } - - return [callback, result, cert]; - }).bind(this); - - - function FakeCertDB() { - for (let property of Object.keys(realCertDB)) { - if (property in this) - continue; - - if (typeof realCertDB[property] == "function") - this[property] = realCertDB[property].bind(realCertDB); - } - } - FakeCertDB.prototype = { - openSignedAppFileAsync(root, file, callback) { - // First try calling the real cert DB - realCertDB.openSignedAppFileAsync(root, file, (result, zipReader, cert) => { - verifyCert(file.clone(), result, cert, callback) - .then(([callback, result, cert]) => { - callback.openSignedAppFileFinished(result, zipReader, cert); - }); - }); - }, - - verifySignedDirectoryAsync(root, dir, callback) { - // First try calling the real cert DB - realCertDB.verifySignedDirectoryAsync(root, dir, (result, cert) => { - verifyCert(dir.clone(), result, cert, callback) - .then(([callback, result, cert]) => { - callback.verifySignedDirectoryFinished(result, cert); - }); - }); - }, - - QueryInterface: XPCOMUtils.generateQI([Ci.nsIX509CertDB]), - }; - - let certDBFactory = XPCOMUtils.generateSingletonFactory(FakeCertDB); - registrar.registerFactory(CERTDB_CID, "CertDB", - CERTDB_CONTRACTID, certDBFactory); - }, - - /** - * Starts up the add-on manager as if it was started by the application. - * - * @param {boolean} [appChanged = true] - * An optional boolean parameter to simulate the case where the - * application has changed version since the last run. If not passed it - * defaults to true - * @returns {Promise} - * Resolves when the add-on manager's startup has completed. - */ - promiseStartupManager(appChanged = true) { - if (this.addonIntegrationService) - throw new Error("Attempting to startup manager that was already started."); - - if (appChanged && this.extensionsINI.exists()) - this.extensionsINI.remove(true); - - this.addonIntegrationService = Cc["@mozilla.org/addons/integration;1"] - .getService(Ci.nsIObserver); - - this.addonIntegrationService.observe(null, "addons-startup", null); - - this.emit("addon-manager-started"); - - // Load the add-ons list as it was after extension registration - this.loadAddonsList(); - - return Promise.resolve(); - }, - - promiseShutdownManager() { - if (!this.addonIntegrationService) - return Promise.resolve(false); - - Services.obs.notifyObservers(null, "quit-application-granted", null); - return MockAsyncShutdown.hook() - .then(() => { - this.emit("addon-manager-shutdown"); - - this.addonIntegrationService = null; - - // Load the add-ons list as it was after application shutdown - this.loadAddonsList(); - - // Clear any crash report annotations - this.appInfo.annotations = {}; - - // Force the XPIProvider provider to reload to better - // simulate real-world usage. - let XPIscope = Cu.import("resource://gre/modules/addons/XPIProvider.jsm"); - // This would be cleaner if I could get it as the rejection reason from - // the AddonManagerInternal.shutdown() promise - let shutdownError = XPIscope.XPIProvider._shutdownError; - - AddonManagerPrivate.unregisterProvider(XPIscope.XPIProvider); - Cu.unload("resource://gre/modules/addons/XPIProvider.jsm"); - - if (shutdownError) - throw shutdownError; - - return true; - }); - }, - - promiseRestartManager(newVersion) { - return this.promiseShutdownManager() - .then(() => { - if (newVersion) - this.appInfo.version = newVersion; - - return this.promiseStartupManager(!!newVersion); - }); - }, - - loadAddonsList() { - this.addonsList = new AddonsList(this.extensionsINI); - }, - - /** - * Creates an update.rdf structure as a string using for the update data passed. - * - * @param {Object} data - * The update data as a JS object. Each property name is an add-on ID, - * the property value is an array of each version of the add-on. Each - * array value is a JS object containing the data for the version, at - * minimum a "version" and "targetApplications" property should be - * included to create a functional update manifest. - * @return {string} The update.rdf structure as a string. - */ - createUpdateRDF(data) { - var rdf = '<?xml version="1.0"?>\n'; - rdf += '<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"\n' + - ' xmlns:em="http://www.mozilla.org/2004/em-rdf#">\n'; - - for (let addon in data) { - rdf += escaped` <Description about="urn:mozilla:extension:${addon}"><em:updates><Seq>\n`; - - for (let versionData of data[addon]) { - rdf += ' <li><Description>\n'; - rdf += this._writeProps(versionData, ["version", "multiprocessCompatible"], - ` `); - for (let app of versionData.targetApplications || []) { - rdf += " <em:targetApplication><Description>\n"; - rdf += this._writeProps(app, ["id", "minVersion", "maxVersion", "updateLink", "updateHash"], - ` `); - rdf += " </Description></em:targetApplication>\n"; - } - rdf += ' </Description></li>\n'; - } - rdf += ' </Seq></em:updates></Description>\n'; - } - rdf += "</RDF>\n"; - - return rdf; - }, - - _writeProps(obj, props, indent = " ") { - let items = []; - for (let prop of props) { - if (prop in obj) - items.push(escaped`${indent}<em:${prop}>${obj[prop]}</em:${prop}>\n`); - } - return items.join(""); - }, - - _writeArrayProps(obj, props, indent = " ") { - let items = []; - for (let prop of props) { - for (let val of obj[prop] || []) - items.push(escaped`${indent}<em:${prop}>${val}</em:${prop}>\n`); - } - return items.join(""); - }, - - _writeLocaleStrings(data) { - let items = []; - - items.push(this._writeProps(data, ["name", "description", "creator", "homepageURL"])); - items.push(this._writeArrayProps(data, ["developer", "translator", "contributor"])); - - return items.join(""); - }, - - createInstallRDF(data) { - var rdf = '<?xml version="1.0"?>\n'; - rdf += '<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"\n' + - ' xmlns:em="http://www.mozilla.org/2004/em-rdf#">\n'; - - rdf += '<Description about="urn:mozilla:install-manifest">\n'; - - let props = ["id", "version", "type", "internalName", "updateURL", "updateKey", - "optionsURL", "optionsType", "aboutURL", "iconURL", "icon64URL", - "skinnable", "bootstrap", "unpack", "strictCompatibility", - "multiprocessCompatible", "hasEmbeddedWebExtension"]; - rdf += this._writeProps(data, props); - - rdf += this._writeLocaleStrings(data); - - for (let platform of data.targetPlatforms || []) - rdf += escaped`<em:targetPlatform>${platform}</em:targetPlatform>\n`; - - for (let app of data.targetApplications || []) { - rdf += "<em:targetApplication><Description>\n"; - rdf += this._writeProps(app, ["id", "minVersion", "maxVersion"]); - rdf += "</Description></em:targetApplication>\n"; - } - - for (let localized of data.localized || []) { - rdf += "<em:localized><Description>\n"; - rdf += this._writeArrayProps(localized, ["locale"]); - rdf += this._writeLocaleStrings(localized); - rdf += "</Description></em:localized>\n"; - } - - for (let dep of data.dependencies || []) - rdf += escaped`<em:dependency><Description em:id="${dep}"/></em:dependency>\n`; - - rdf += "</Description>\n</RDF>\n"; - return rdf; - }, - - /** - * Recursively create all directories upto and including the given - * path, if they do not exist. - * - * @param {string} path The path of the directory to create. - * @returns {Promise} Resolves when all directories have been created. - */ - recursiveMakeDir(path) { - let paths = []; - for (let lastPath; path != lastPath; lastPath = path, path = OS.Path.dirname(path)) - paths.push(path); - - return Promise.all(paths.reverse().map(path => - OS.File.makeDir(path, {ignoreExisting: true}).catch(() => {}))); - }, - - /** - * Writes the given data to a file in the given zip file. - * - * @param {string|nsIFile} zipFile - * The zip file to write to. - * @param {Object} files - * An object containing filenames and the data to write to the - * corresponding paths in the zip file. - * @param {integer} [flags = 0] - * Additional flags to open the file with. - */ - writeFilesToZip(zipFile, files, flags = 0) { - if (typeof zipFile == "string") - zipFile = nsFile(zipFile); - - var zipW = ZipWriter(zipFile, FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE | flags); - - for (let [path, data] of Object.entries(files)) { - if (!(data instanceof ArrayBuffer)) - data = new TextEncoder("utf-8").encode(data).buffer; - - let stream = ArrayBufferInputStream(data, 0, data.byteLength); - - // Note these files are being created in the XPI archive with date "0" which is 1970-01-01. - zipW.addEntryStream(path, 0, Ci.nsIZipWriter.COMPRESSION_NONE, - stream, false); - } - - zipW.close(); - }, - - promiseWriteFilesToZip: Task.async(function*(zip, files, flags) { - yield this.recursiveMakeDir(OS.Path.dirname(zip)); - - this.writeFilesToZip(zip, files, flags); - - return Promise.resolve(nsFile(zip)); - }), - - promiseWriteFilesToDir: Task.async(function*(dir, files) { - yield this.recursiveMakeDir(dir); - - for (let [path, data] of Object.entries(files)) { - path = path.split("/"); - let leafName = path.pop(); - - // Create parent directories, if necessary. - let dirPath = dir; - for (let subDir of path) { - dirPath = OS.Path.join(dirPath, subDir); - yield OS.Path.makeDir(dirPath, {ignoreExisting: true}); - } - - if (typeof data == "string") - data = new TextEncoder("utf-8").encode(data); - - yield OS.File.writeAtomic(OS.Path.join(dirPath, leafName), data); - } - - return nsFile(dir); - }), - - promiseWriteFilesToExtension(dir, id, files, unpacked = this.testUnpacked) { - if (typeof files["install.rdf"] === "object") - files["install.rdf"] = this.createInstallRDF(files["install.rdf"]); - - if (unpacked) { - let path = OS.Path.join(dir, id); - - return this.promiseWriteFilesToDir(path, files); - } - - let xpi = OS.Path.join(dir, `${id}.xpi`); - - return this.promiseWriteFilesToZip(xpi, files); - }, - - tempXPIs: [], - /** - * Creates an XPI file for some manifest data in the temporary directory and - * returns the nsIFile for it. The file will be deleted when the test completes. - * - * @param {object} files - * The object holding data about the add-on - * @return {nsIFile} A file pointing to the created XPI file - */ - createTempXPIFile(files) { - var file = this.tempDir.clone(); - let uuid = uuidGen.generateUUID().number.slice(1, -1); - file.append(`${uuid}.xpi`); - - this.tempXPIs.push(file); - - if (typeof files["install.rdf"] === "object") - files["install.rdf"] = this.createInstallRDF(files["install.rdf"]); - - this.writeFilesToZip(file.path, files); - return file; - }, - - /** - * Creates an XPI file for some WebExtension data in the temporary directory and - * returns the nsIFile for it. The file will be deleted when the test completes. - * - * @param {Object} data - * The object holding data about the add-on, as expected by - * |Extension.generateXPI|. - * @return {nsIFile} A file pointing to the created XPI file - */ - createTempWebExtensionFile(data) { - let file = Extension.generateXPI(data); - this.tempXPIs.push(file); - return file; - }, - - /** - * Creates an extension proxy file. - * See: https://developer.mozilla.org/en-US/Add-ons/Setting_up_extension_development_environment#Firefox_extension_proxy_file - * - * @param {nsIFile} dir - * The directory to add the proxy file to. - * @param {nsIFile} addon - * An nsIFile for the add-on file that this is a proxy file for. - * @param {string} id - * A string to use for the add-on ID. - * @returns {Promise} Resolves when the file has been created. - */ - promiseWriteProxyFileToDir(dir, addon, id) { - let files = { - [id]: addon.path, - }; - - return this.promiseWriteFilesToDir(dir.path, files); - }, - - /** - * Manually installs an XPI file into an install location by either copying the - * XPI there or extracting it depending on whether unpacking is being tested - * or not. - * - * @param {nsIFile} xpiFile - * The XPI file to install. - * @param {nsIFile} installLocation - * The install location (an nsIFile) to install into. - * @param {string} id - * The ID to install as. - * @param {boolean} [unpacked = this.testUnpacked] - * If true, install as an unpacked directory, rather than a - * packed XPI. - * @returns {nsIFile} - * A file pointing to the installed location of the XPI file or - * unpacked directory. - */ - manuallyInstall(xpiFile, installLocation, id, unpacked = this.testUnpacked) { - if (unpacked) { - let dir = installLocation.clone(); - dir.append(id); - dir.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY); - - let zip = ZipReader(xpiFile); - let entries = zip.findEntries(null); - while (entries.hasMore()) { - let entry = entries.getNext(); - let target = dir.clone(); - for (let part of entry.split("/")) - target.append(part); - zip.extract(entry, target); - } - zip.close(); - - return dir; - } - - let target = installLocation.clone(); - target.append(`${id}.xpi`); - xpiFile.copyTo(target.parent, target.leafName); - return target; - }, - - /** - * Manually uninstalls an add-on by removing its files from the install - * location. - * - * @param {nsIFile} installLocation - * The nsIFile of the install location to remove from. - * @param {string} id - * The ID of the add-on to remove. - * @param {boolean} [unpacked = this.testUnpacked] - * If true, uninstall an unpacked directory, rather than a - * packed XPI. - */ - manuallyUninstall(installLocation, id, unpacked = this.testUnpacked) { - let file = this.getFileForAddon(installLocation, id, unpacked); - - // In reality because the app is restarted a flush isn't necessary for XPIs - // removed outside the app, but for testing we must flush manually. - if (file.isFile()) - Services.obs.notifyObservers(file, "flush-cache-entry", null); - - file.remove(true); - }, - - /** - * Gets the nsIFile for where an add-on is installed. It may point to a file or - * a directory depending on whether add-ons are being installed unpacked or not. - * - * @param {nsIFile} dir - * The nsIFile for the install location - * @param {string} id - * The ID of the add-on - * @param {boolean} [unpacked = this.testUnpacked] - * If true, return the path to an unpacked directory, rather than a - * packed XPI. - * @returns {nsIFile} - * A file pointing to the XPI file or unpacked directory where - * the add-on should be installed. - */ - getFileForAddon(dir, id, unpacked = this.testUnpacked) { - dir = dir.clone(); - if (unpacked) - dir.append(id); - else - dir.append(`${id}.xpi`); - return dir; - }, - - /** - * Sets the last modified time of the extension, usually to trigger an update - * of its metadata. If the extension is unpacked, this function assumes that - * the extension contains only the install.rdf file. - * - * @param {nsIFile} ext A file pointing to either the packed extension or its unpacked directory. - * @param {number} time The time to which we set the lastModifiedTime of the extension - * - * @deprecated Please use promiseSetExtensionModifiedTime instead - */ - setExtensionModifiedTime(ext, time) { - ext.lastModifiedTime = time; - if (ext.isDirectory()) { - let entries = ext.directoryEntries - .QueryInterface(Ci.nsIDirectoryEnumerator); - while (entries.hasMoreElements()) - this.setExtensionModifiedTime(entries.nextFile, time); - entries.close(); - } - }, - - promiseSetExtensionModifiedTime: Task.async(function*(path, time) { - yield OS.File.setDates(path, time, time); - - let iterator = new OS.File.DirectoryIterator(path); - try { - yield iterator.forEach(entry => { - return this.promiseSetExtensionModifiedTime(entry.path, time); - }); - } catch (ex) { - if (ex instanceof OS.File.Error) - return; - throw ex; - } finally { - iterator.close().catch(() => {}); - } - }), - - registerDirectory(key, dir) { - var dirProvider = { - getFile(prop, persistent) { - persistent.value = false; - if (prop == key) - return dir.clone(); - return null; - }, - - QueryInterface: XPCOMUtils.generateQI([Ci.nsIDirectoryServiceProvider]), - }; - Services.dirsvc.registerProvider(dirProvider); - }, - - /** - * Returns a promise that resolves when the given add-on event is fired. The - * resolved value is an array of arguments passed for the event. - * - * @param {string} event - * The name of the AddonListener event handler method for which - * an event is expected. - * @returns {Promise<Array>} - * Resolves to an array containing the event handler's - * arguments the first time it is called. - */ - promiseAddonEvent(event) { - return new Promise(resolve => { - let listener = { - [event](...args) { - AddonManager.removeAddonListener(listener); - resolve(args); - }, - }; - - AddonManager.addAddonListener(listener); - }); - }, - - /** - * A helper method to install AddonInstall and wait for completion. - * - * @param {AddonInstall} install - * The add-on to install. - * @returns {Promise} - * Resolves when the install completes, either successfully or - * in failure. - */ - promiseCompleteInstall(install) { - let listener; - return new Promise(resolve => { - listener = { - onDownloadFailed: resolve, - onDownloadCancelled: resolve, - onInstallFailed: resolve, - onInstallCancelled: resolve, - onInstallEnded: resolve, - onInstallPostponed: resolve, - }; - - install.addListener(listener); - install.install(); - }).then(() => { - install.removeListener(listener); - }); - }, - - /** - * A helper method to install a file. - * - * @param {nsIFile} file - * The file to install - * @param {boolean} [ignoreIncompatible = false] - * Optional parameter to ignore add-ons that are incompatible - * with the application - * @returns {Promise} - * Resolves when the install has completed. - */ - promiseInstallFile(file, ignoreIncompatible = false) { - return new Promise((resolve, reject) => { - AddonManager.getInstallForFile(file, install => { - if (!install) - reject(new Error(`No AddonInstall created for ${file.path}`)); - else if (install.state != AddonManager.STATE_DOWNLOADED) - reject(new Error(`Expected file to be downloaded for install of ${file.path}`)); - else if (ignoreIncompatible && install.addon.appDisabled) - resolve(); - else - resolve(this.promiseCompleteInstall(install)); - }); - }); - }, - - /** - * A helper method to install an array of files. - * - * @param {Iterable<nsIFile>} files - * The files to install - * @param {boolean} [ignoreIncompatible = false] - * Optional parameter to ignore add-ons that are incompatible - * with the application - * @returns {Promise} - * Resolves when the installs have completed. - */ - promiseInstallAllFiles(files, ignoreIncompatible = false) { - return Promise.all(Array.from( - files, - file => this.promiseInstallFile(file, ignoreIncompatible))); - }, - - promiseCompleteAllInstalls(installs) { - return Promise.all(Array.from(installs, this.promiseCompleteInstall)); - }, - - /** - * A promise-based variant of AddonManager.getAddonsByIDs. - * - * @param {Array<string>} list - * As the first argument of AddonManager.getAddonsByIDs - * @return {Promise<Array<Addon>>} - * Resolves to the array of add-ons for the given IDs. - */ - promiseAddonsByIDs(list) { - return new Promise(resolve => AddonManager.getAddonsByIDs(list, resolve)); - }, - - /** - * A promise-based variant of AddonManager.getAddonByID. - * - * @param {string} id - * The ID of the add-on. - * @return {Promise<Addon>} - * Resolves to the add-on with the given ID. - */ - promiseAddonByID(id) { - return new Promise(resolve => AddonManager.getAddonByID(id, resolve)); - }, - - /** - * Returns a promise that will be resolved when an add-on update check is - * complete. The value resolved will be an AddonInstall if a new version was - * found. - * - * @param {object} addon The add-on to find updates for. - * @param {integer} reason The type of update to find. - * @return {Promise<object>} an object containing information about the update. - */ - promiseFindAddonUpdates(addon, reason = AddonManager.UPDATE_WHEN_PERIODIC_UPDATE) { - let equal = this.testScope.equal; - return new Promise((resolve, reject) => { - let result = {}; - addon.findUpdates({ - onNoCompatibilityUpdateAvailable: function(addon2) { - if ("compatibilityUpdate" in result) { - throw new Error("Saw multiple compatibility update events"); - } - equal(addon, addon2, "onNoCompatibilityUpdateAvailable"); - result.compatibilityUpdate = false; - }, - - onCompatibilityUpdateAvailable: function(addon2) { - if ("compatibilityUpdate" in result) { - throw new Error("Saw multiple compatibility update events"); - } - equal(addon, addon2, "onCompatibilityUpdateAvailable"); - result.compatibilityUpdate = true; - }, - - onNoUpdateAvailable: function(addon2) { - if ("updateAvailable" in result) { - throw new Error("Saw multiple update available events"); - } - equal(addon, addon2, "onNoUpdateAvailable"); - result.updateAvailable = false; - }, - - onUpdateAvailable: function(addon2, install) { - if ("updateAvailable" in result) { - throw new Error("Saw multiple update available events"); - } - equal(addon, addon2, "onUpdateAvailable"); - result.updateAvailable = install; - }, - - onUpdateFinished: function(addon2, error) { - equal(addon, addon2, "onUpdateFinished"); - if (error == AddonManager.UPDATE_STATUS_NO_ERROR) { - resolve(result); - } else { - result.error = error; - reject(result); - } - } - }, reason); - }); - }, - - /** - * A promise-based variant of AddonManager.getAddonsWithOperationsByTypes - * - * @param {Array<string>} types - * The first argument to AddonManager.getAddonsWithOperationsByTypes - * @return {Promise<Array<Addon>>} - * Resolves to an array of add-ons with the given operations - * pending. - */ - promiseAddonsWithOperationsByTypes(types) { - return new Promise(resolve => AddonManager.getAddonsWithOperationsByTypes(types, resolve)); - }, - - /** - * Monitors console output for the duration of a task, and returns a promise - * which resolves to a tuple containing a list of all console messages - * generated during the task's execution, and the result of the task itself. - * - * @param {function} task - * The task to run while monitoring console output. May be - * either a generator function, per Task.jsm, or an ordinary - * function which returns promose. - * @return {Promise<[Array<nsIConsoleMessage>, *]>} - * Resolves to an object containing a `messages` property, with - * the array of console messages emitted during the execution - * of the task, and a `result` property, containing the task's - * return value. - */ - promiseConsoleOutput: Task.async(function*(task) { - const DONE = "=== xpcshell test console listener done ==="; - - let listener, messages = []; - let awaitListener = new Promise(resolve => { - listener = msg => { - if (msg == DONE) { - resolve(); - } else { - msg instanceof Ci.nsIScriptError; - messages.push(msg); - } - }; - }); - - Services.console.registerListener(listener); - try { - let result = yield task(); - - Services.console.logStringMessage(DONE); - yield awaitListener; - - return {messages, result}; - } finally { - Services.console.unregisterListener(listener); - } - }), -}; - -for (let [key, val] of Object.entries(AddonTestUtils)) { - if (typeof val == "function") - AddonTestUtils[key] = val.bind(AddonTestUtils); -} - -EventEmitter.decorate(AddonTestUtils); diff --git a/toolkit/mozapps/extensions/internal/AddonUpdateChecker.jsm b/toolkit/mozapps/extensions/internal/AddonUpdateChecker.jsm index 63c16737c..939e2e269 100644 --- a/toolkit/mozapps/extensions/internal/AddonUpdateChecker.jsm +++ b/toolkit/mozapps/extensions/internal/AddonUpdateChecker.jsm @@ -22,6 +22,9 @@ const PREFIX_ITEM = "urn:mozilla:item:"; const PREFIX_EXTENSION = "urn:mozilla:extension:"; const PREFIX_THEME = "urn:mozilla:theme:"; const TOOLKIT_ID = "toolkit@mozilla.org" +#ifdef MOZ_PHOENIX_EXTENSIONS +const FIREFOX_ID = "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}" +#endif const XMLURI_PARSE_ERROR = "http://www.mozilla.org/newlayout/xml/parsererror.xml" const PREF_UPDATE_REQUIREBUILTINCERTS = "extensions.update.requireBuiltInCerts"; @@ -31,16 +34,11 @@ Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "AddonManager", "resource://gre/modules/AddonManager.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "AddonManagerPrivate", - "resource://gre/modules/AddonManager.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "AddonRepository", "resource://gre/modules/addons/AddonRepository.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "ServiceRequest", - "resource://gre/modules/ServiceRequest.jsm"); - // Shared code for suppressing bad cert dialogs. -XPCOMUtils.defineLazyGetter(this, "CertUtils", function() { +XPCOMUtils.defineLazyGetter(this, "CertUtils", function certUtilsLazyGetter() { let certUtils = {}; Components.utils.import("resource://gre/modules/CertUtils.jsm", certUtils); return certUtils; @@ -82,7 +80,7 @@ RDFSerializer.prototype = { * @return a string with all characters invalid in XML character data * converted to entity references. */ - escapeEntities: function(aString) { + escapeEntities: function RDFS_escapeEntities(aString) { aString = aString.replace(/&/g, "&"); aString = aString.replace(/</g, "<"); aString = aString.replace(/>/g, ">"); @@ -100,7 +98,8 @@ RDFSerializer.prototype = { * The current level of indent for pretty-printing * @return a string containing the serialized elements. */ - serializeContainerItems: function(aDs, aContainer, aIndent) { + serializeContainerItems: function RDFS_serializeContainerItems(aDs, aContainer, + aIndent) { var result = ""; var items = aContainer.GetElements(); while (items.hasMoreElements()) { @@ -126,7 +125,9 @@ RDFSerializer.prototype = { * @return a string containing the serialized properties. * @throws if the resource contains a property that cannot be serialized */ - serializeResourceProperties: function(aDs, aResource, aIndent) { + serializeResourceProperties: function RDFS_serializeResourceProperties(aDs, + aResource, + aIndent) { var result = ""; var items = []; var arcs = aDs.ArcLabelsOut(aResource); @@ -180,7 +181,7 @@ RDFSerializer.prototype = { * @return a string containing the serialized resource. * @throws if the RDF data contains multiple references to the same resource. */ - serializeResource: function(aDs, aResource, aIndent) { + serializeResource: function RDFS_serializeResource(aDs, aResource, aIndent) { if (this.resources.indexOf(aResource) != -1 ) { // We cannot output multiple references to the same resource. throw Components.Exception("Cannot serialize multiple references to " + aResource.Value); @@ -220,48 +221,6 @@ RDFSerializer.prototype = { } /** - * Sanitizes the update URL in an update item, as returned by - * parseRDFManifest and parseJSONManifest. Ensures that: - * - * - The URL is secure, or secured by a strong enough hash. - * - The security principal of the update manifest has permission to - * load the URL. - * - * @param aUpdate - * The update item to sanitize. - * @param aRequest - * The XMLHttpRequest used to load the manifest. - * @param aHashPattern - * The regular expression used to validate the update hash. - * @param aHashString - * The human-readable string specifying which hash functions - * are accepted. - */ -function sanitizeUpdateURL(aUpdate, aRequest, aHashPattern, aHashString) { - if (aUpdate.updateURL) { - let scriptSecurity = Services.scriptSecurityManager; - let principal = scriptSecurity.getChannelURIPrincipal(aRequest.channel); - try { - // This logs an error on failure, so no need to log it a second time - scriptSecurity.checkLoadURIStrWithPrincipal(principal, aUpdate.updateURL, - scriptSecurity.DISALLOW_SCRIPT); - } catch (e) { - delete aUpdate.updateURL; - return; - } - - if (AddonManager.checkUpdateSecurity && - !aUpdate.updateURL.startsWith("https:") && - !aHashPattern.test(aUpdate.updateHash)) { - logger.warn(`Update link ${aUpdate.updateURL} is not secure and is not verified ` + - `by a strong enough hash (needs to be ${aHashString}).`); - delete aUpdate.updateURL; - delete aUpdate.updateHash; - } - } -} - -/** * Parses an RDF style update manifest into an array of update objects. * * @param aId @@ -270,17 +229,10 @@ function sanitizeUpdateURL(aUpdate, aRequest, aHashPattern, aHashString) { * An optional update key for the add-on * @param aRequest * The XMLHttpRequest that has retrieved the update manifest - * @param aManifestData - * The pre-parsed manifest, as a bare XML DOM document * @return an array of update objects * @throws if the update manifest is invalid in any way */ -function parseRDFManifest(aId, aUpdateKey, aRequest, aManifestData) { - if (aManifestData.documentElement.namespaceURI != PREFIX_NS_RDF) { - throw Components.Exception("Update manifest had an unrecognised namespace: " + - aManifestData.documentElement.namespaceURI); - } - +function parseRDFManifest(aId, aUpdateKey, aRequest) { function EM_R(aProp) { return gRDF.GetResource(PREFIX_NS_EM + aProp); } @@ -323,13 +275,9 @@ function parseRDFManifest(aId, aUpdateKey, aRequest, aManifestData) { let extensionRes = gRDF.GetResource(PREFIX_EXTENSION + aId); let themeRes = gRDF.GetResource(PREFIX_THEME + aId); let itemRes = gRDF.GetResource(PREFIX_ITEM + aId); - let addonRes; - if (ds.ArcLabelsOut(extensionRes).hasMoreElements()) - addonRes = extensionRes; - else if (ds.ArcLabelsOut(themeRes).hasMoreElements()) - addonRes = themeRes; - else - addonRes = itemRes; + let addonRes = ds.ArcLabelsOut(extensionRes).hasMoreElements() ? extensionRes + : ds.ArcLabelsOut(themeRes).hasMoreElements() ? themeRes + : itemRes; // If we have an update key then the update manifest must be signed if (aUpdateKey) { @@ -421,134 +369,16 @@ function parseRDFManifest(aId, aUpdateKey, aRequest, aManifestData) { targetApplications: [appEntry] }; - // The JSON update protocol requires an SHA-2 hash. RDF still - // supports SHA-1, for compatibility reasons. - sanitizeUpdateURL(result, aRequest, /^sha/, "sha1 or stronger"); - - results.push(result); - } - } - return results; -} - -/** - * Parses an JSON update manifest into an array of update objects. - * - * @param aId - * The ID of the add-on being checked for updates - * @param aUpdateKey - * An optional update key for the add-on - * @param aRequest - * The XMLHttpRequest that has retrieved the update manifest - * @param aManifestData - * The pre-parsed manifest, as a JSON object tree - * @return an array of update objects - * @throws if the update manifest is invalid in any way - */ -function parseJSONManifest(aId, aUpdateKey, aRequest, aManifestData) { - if (aUpdateKey) - throw Components.Exception("Update keys are not supported for JSON update manifests"); - - let TYPE_CHECK = { - "array": val => Array.isArray(val), - "object": val => val && typeof val == "object" && !Array.isArray(val), - }; - - function getProperty(aObj, aProperty, aType, aDefault = undefined) { - if (!(aProperty in aObj)) - return aDefault; - - let value = aObj[aProperty]; - - let matchesType = aType in TYPE_CHECK ? TYPE_CHECK[aType](value) : typeof value == aType; - if (!matchesType) - throw Components.Exception(`Update manifest property '${aProperty}' has incorrect type (expected ${aType})`); - - return value; - } - - function getRequiredProperty(aObj, aProperty, aType) { - let value = getProperty(aObj, aProperty, aType); - if (value === undefined) - throw Components.Exception(`Update manifest is missing a required ${aProperty} property.`); - return value; - } - - let manifest = aManifestData; - - if (!TYPE_CHECK["object"](manifest)) - throw Components.Exception("Root element of update manifest must be a JSON object literal"); - - // The set of add-ons this manifest has updates for - let addons = getRequiredProperty(manifest, "addons", "object"); - - // The entry for this particular add-on - let addon = getProperty(addons, aId, "object"); - - // A missing entry doesn't count as a failure, just as no avialable update - // information - if (!addon) { - logger.warn("Update manifest did not contain an entry for " + aId); - return []; - } - - // The list of available updates - let updates = getProperty(addon, "updates", "array", []); - - let results = []; - - for (let update of updates) { - let version = getRequiredProperty(update, "version", "string"); - - logger.debug(`Found an update entry for ${aId} version ${version}`); - - let applications = getProperty(update, "applications", "object", - { gecko: {} }); - - // "gecko" is currently the only supported application entry. If - // it's missing, skip this update. - if (!("gecko" in applications)) { - logger.debug("gecko not in application entry, skipping update of ${addon}") - continue; - } - - let app = getProperty(applications, "gecko", "object"); - - let appEntry = { - id: TOOLKIT_ID, - minVersion: getProperty(app, "strict_min_version", "string", - AddonManagerPrivate.webExtensionsMinPlatformVersion), - maxVersion: "*", - }; - - let result = { - id: aId, - version: version, - multiprocessCompatible: getProperty(update, "multiprocess_compatible", "boolean", true), - updateURL: getProperty(update, "update_link", "string"), - updateHash: getProperty(update, "update_hash", "string"), - updateInfoURL: getProperty(update, "update_info_url", "string"), - strictCompatibility: false, - targetApplications: [appEntry], - }; - - if ("strict_max_version" in app) { - if ("advisory_max_version" in app) { - logger.warn("Ignoring 'advisory_max_version' update manifest property for " + - aId + " property since 'strict_max_version' also present"); + if (result.updateURL && AddonManager.checkUpdateSecurity && + result.updateURL.substring(0, 6) != "https:" && + (!result.updateHash || result.updateHash.substring(0, 3) != "sha")) { + logger.warn("updateLink " + result.updateURL + " is not secure and is not verified" + + " by a strong enough hash (needs to be sha1 or stronger)."); + delete result.updateURL; + delete result.updateHash; } - - appEntry.maxVersion = getProperty(app, "strict_max_version", "string"); - result.strictCompatibility = appEntry.maxVersion != "*"; - } else if ("advisory_max_version" in app) { - appEntry.maxVersion = getProperty(app, "advisory_max_version", "string"); + results.push(result); } - - // The JSON update protocol requires an SHA-2 hash. RDF still - // supports SHA-1, for compatibility reasons. - sanitizeUpdateURL(result, aRequest, /^sha(256|512):/, "sha256 or sha512"); - - results.push(result); } return results; } @@ -581,18 +411,20 @@ function UpdateParser(aId, aUpdateKey, aUrl, aObserver) { logger.debug("Requesting " + aUrl); try { - this.request = new ServiceRequest(); + this.request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]. + createInstance(Ci.nsIXMLHttpRequest); this.request.open("GET", this.url, true); this.request.channel.notificationCallbacks = new CertUtils.BadCertHandler(!requireBuiltIn); this.request.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE; // Prevent the request from writing to cache. this.request.channel.loadFlags |= Ci.nsIRequest.INHIBIT_CACHING; - this.request.overrideMimeType("text/plain"); + this.request.overrideMimeType("text/xml"); this.request.setRequestHeader("Moz-XPI-Update", "1", true); this.request.timeout = TIMEOUT; - this.request.addEventListener("load", () => this.onLoad(), false); - this.request.addEventListener("error", () => this.onError(), false); - this.request.addEventListener("timeout", () => this.onTimeout(), false); + var self = this; + this.request.addEventListener("load", function loadEventListener(event) { self.onLoad() }, false); + this.request.addEventListener("error", function errorEventListener(event) { self.onError() }, false); + this.request.addEventListener("timeout", function timeoutEventListener(event) { self.onTimeout() }, false); this.request.send(null); } catch (e) { @@ -610,7 +442,7 @@ UpdateParser.prototype = { /** * Called when the manifest has been successfully loaded. */ - onLoad: function() { + onLoad: function UP_onLoad() { let request = this.request; this.request = null; this._doneAt = new Error("place holder"); @@ -626,7 +458,6 @@ UpdateParser.prototype = { CertUtils.checkCert(request.channel, !requireBuiltIn); } catch (e) { - logger.warn("Request failed: " + this.url + " - " + e); this.notifyError(AddonUpdateChecker.ERROR_DOWNLOAD_ERROR); return; } @@ -645,52 +476,41 @@ UpdateParser.prototype = { return; } - // Detect the manifest type by first attempting to parse it as - // JSON, and falling back to parsing it as XML if that fails. - let parser; - try { - try { - let json = JSON.parse(request.responseText); - - parser = () => parseJSONManifest(this.id, this.updateKey, request, json); - } catch (e) { - if (!(e instanceof SyntaxError)) - throw e; - let domParser = Cc["@mozilla.org/xmlextras/domparser;1"].createInstance(Ci.nsIDOMParser); - let xml = domParser.parseFromString(request.responseText, "text/xml"); - - if (xml.documentElement.namespaceURI == XMLURI_PARSE_ERROR) - throw new Error("Update manifest was not valid XML or JSON"); - - parser = () => parseRDFManifest(this.id, this.updateKey, request, xml); - } - } catch (e) { - logger.warn("onUpdateCheckComplete failed to determine manifest type"); - this.notifyError(AddonUpdateChecker.ERROR_UNKNOWN_FORMAT); - return; - } - - let results; - try { - results = parser(); - } - catch (e) { - logger.warn("onUpdateCheckComplete failed to parse update manifest", e); + let xml = request.responseXML; + if (!xml || xml.documentElement.namespaceURI == XMLURI_PARSE_ERROR) { + logger.warn("Update manifest was not valid XML"); this.notifyError(AddonUpdateChecker.ERROR_PARSE_ERROR); return; } - if ("onUpdateCheckComplete" in this.observer) { + // We currently only know about RDF update manifests + if (xml.documentElement.namespaceURI == PREFIX_NS_RDF) { + let results = null; + try { - this.observer.onUpdateCheckComplete(results); + results = parseRDFManifest(this.id, this.updateKey, request); } catch (e) { - logger.warn("onUpdateCheckComplete notification failed", e); + logger.warn("onUpdateCheckComplete failed to parse RDF manifest", e); + this.notifyError(AddonUpdateChecker.ERROR_PARSE_ERROR); + return; } + if ("onUpdateCheckComplete" in this.observer) { + try { + this.observer.onUpdateCheckComplete(results); + } + catch (e) { + logger.warn("onUpdateCheckComplete notification failed", e); + } + } + else { + logger.warn("onUpdateCheckComplete may not properly cancel", new Error("stack marker")); + } + return; } - else { - logger.warn("onUpdateCheckComplete may not properly cancel", new Error("stack marker")); - } + + logger.warn("Update manifest had an unrecognised namespace: " + xml.documentElement.namespaceURI); + this.notifyError(AddonUpdateChecker.ERROR_UNKNOWN_FORMAT); }, /** @@ -706,7 +526,7 @@ UpdateParser.prototype = { /** * Called when the manifest failed to load. */ - onError: function() { + onError: function UP_onError() { if (!Components.isSuccessCode(this.request.status)) { logger.warn("Request failed: " + this.url + " - " + this.request.status); } @@ -735,7 +555,7 @@ UpdateParser.prototype = { /** * Helper method to notify the observer that an error occured. */ - notifyError: function(aStatus) { + notifyError: function UP_notifyError(aStatus) { if ("onUpdateCheckError" in this.observer) { try { this.observer.onUpdateCheckError(aStatus); @@ -749,7 +569,7 @@ UpdateParser.prototype = { /** * Called to cancel an in-progress update check. */ - cancel: function() { + cancel: function UP_cancel() { if (!this.request) { logger.error("Trying to cancel already-complete request", this._doneAt); return; @@ -799,6 +619,12 @@ function matchesVersions(aUpdate, aAppVersion, aPlatformVersion, return (Services.vc.compare(aAppVersion, app.minVersion) >= 0) && (aIgnoreMaxVersion || (Services.vc.compare(aAppVersion, app.maxVersion) <= 0)); } +#ifdef MOZ_PHOENIX_EXTENSIONS + if (app.id == FIREFOX_ID) { + return (Services.vc.compare(aAppVersion, app.minVersion) >= 0) && + (aIgnoreMaxVersion || (Services.vc.compare(aAppVersion, app.maxVersion) <= 0)); + } +#endif if (app.id == TOOLKIT_ID) { result = (Services.vc.compare(aPlatformVersion, app.minVersion) >= 0) && (aIgnoreMaxVersion || (Services.vc.compare(aPlatformVersion, app.maxVersion) <= 0)); @@ -843,9 +669,12 @@ this.AddonUpdateChecker = { * Ignore strictCompatibility when testing if an update matches. Optional. * @return an update object if one matches or null if not */ - getCompatibilityUpdate: function(aUpdates, aVersion, aIgnoreCompatibility, - aAppVersion, aPlatformVersion, - aIgnoreMaxVersion, aIgnoreStrictCompat) { + getCompatibilityUpdate: function AUC_getCompatibilityUpdate(aUpdates, aVersion, + aIgnoreCompatibility, + aAppVersion, + aPlatformVersion, + aIgnoreMaxVersion, + aIgnoreStrictCompat) { if (!aAppVersion) aAppVersion = Services.appinfo.version; if (!aPlatformVersion) @@ -856,7 +685,12 @@ this.AddonUpdateChecker = { if (aIgnoreCompatibility) { for (let targetApp of update.targetApplications) { let id = targetApp.id; +#ifdef MOZ_PHOENIX_EXTENSIONS + if (id == Services.appinfo.ID || id == FIREFOX_ID || + id == TOOLKIT_ID) +#else if (id == Services.appinfo.ID || id == TOOLKIT_ID) +#endif return update; } } @@ -886,9 +720,12 @@ this.AddonUpdateChecker = { * Array of AddonCompatibilityOverride to take into account. Optional. * @return an update object if one matches or null if not */ - getNewestCompatibleUpdate: function(aUpdates, aAppVersion, aPlatformVersion, - aIgnoreMaxVersion, aIgnoreStrictCompat, - aCompatOverrides) { + getNewestCompatibleUpdate: function AUC_getNewestCompatibleUpdate(aUpdates, + aAppVersion, + aPlatformVersion, + aIgnoreMaxVersion, + aIgnoreStrictCompat, + aCompatOverrides) { if (!aAppVersion) aAppVersion = Services.appinfo.version; if (!aPlatformVersion) @@ -928,7 +765,9 @@ this.AddonUpdateChecker = { * @return UpdateParser so that the caller can use UpdateParser.cancel() to shut * down in-progress update requests */ - checkForUpdates: function(aId, aUpdateKey, aUrl, aObserver) { - return new UpdateParser(aId, aUpdateKey, aUrl, aObserver); + checkForUpdates: function AUC_checkForUpdates(aId, aUpdateKey, aUrl, aObserver) { + // Exclude default theme + if (aId != "{972ce4c6-7e08-4474-a285-3208198ce6fd}") + return new UpdateParser(aId, aUpdateKey, aUrl, aObserver); } }; diff --git a/toolkit/mozapps/extensions/internal/Content.js b/toolkit/mozapps/extensions/internal/Content.js index 9f366ba32..61a8b0323 100644 --- a/toolkit/mozapps/extensions/internal/Content.js +++ b/toolkit/mozapps/extensions/internal/Content.js @@ -2,13 +2,11 @@ * 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/. */ -/* globals addMessageListener*/ - "use strict"; (function() { -var {classes: Cc, interfaces: Ci, utils: Cu} = Components; +const {classes: Cc, interfaces: Ci, utils: Cu} = Components; var {Services} = Cu.import("resource://gre/modules/Services.jsm", {}); @@ -16,22 +14,17 @@ var nsIFile = Components.Constructor("@mozilla.org/file/local;1", "nsIFile", "initWithPath"); const MSG_JAR_FLUSH = "AddonJarFlush"; -const MSG_MESSAGE_MANAGER_CACHES_FLUSH = "AddonMessageManagerCachesFlush"; try { if (Services.appinfo.processType !== Services.appinfo.PROCESS_TYPE_DEFAULT) { - // Propagate JAR cache flush notifications across process boundaries. - addMessageListener(MSG_JAR_FLUSH, function(message) { + // Propagate JAR cache flush notifications across process boundaries. + addMessageListener(MSG_JAR_FLUSH, function jar_flushMessageListener(message) { let file = new nsIFile(message.data); Services.obs.notifyObservers(file, "flush-cache-entry", null); }); - // Propagate message manager caches flush notifications across processes. - addMessageListener(MSG_MESSAGE_MANAGER_CACHES_FLUSH, function() { - Services.obs.notifyObservers(null, "message-manager-flush-caches", null); - }); } -} catch (e) { +} catch(e) { Cu.reportError(e); } diff --git a/toolkit/mozapps/extensions/internal/E10SAddonsRollout.jsm b/toolkit/mozapps/extensions/internal/E10SAddonsRollout.jsm deleted file mode 100644 index 3bcee44d3..000000000 --- a/toolkit/mozapps/extensions/internal/E10SAddonsRollout.jsm +++ /dev/null @@ -1,982 +0,0 @@ -/* 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/. */ - -"use strict"; - -this.EXPORTED_SYMBOLS = [ "isAddonPartOfE10SRollout" ]; - -const Cu = Components.utils; -Cu.import("resource://gre/modules/Preferences.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); - -const PREF_E10S_ADDON_BLOCKLIST = "extensions.e10s.rollout.blocklist"; -const PREF_E10S_ADDON_POLICY = "extensions.e10s.rollout.policy"; - -const ADDONS = { - "Greasemonkey": { // Greasemonkey - id: "{e4a8a97b-f2ed-450b-b12d-ee082ba24781}", minVersion: "3.8", - }, - - "DYTV": { // Download YouTube Videos as MP4 - id: "{b9bfaf1c-a63f-47cd-8b9a-29526ced9060}", minVersion: "1.8.7", - }, - - "VDH": { // Video Download Helper - id: "{b9db16a4-6edc-47ec-a1f4-b86292ed211d}", minVersion: "5.6.1", - }, - - "Lightbeam": { // Lightbeam - id: "jid1-F9UJ2thwoAm5gQ@jetpack", minVersion: "1.3.0.1", - }, - - "ABP": { // Adblock Plus - id: "{d10d0bf8-f5b5-c8b4-a8b2-2b9879e08c5d}", minVersion: "2.7.3", - }, - - "uBlockOrigin": { // uBlock Origin - id: "uBlock0@raymondhill.net", minVersion: "1.7.6", - }, - - "Emoji": { // Emoji Cheatsheet - id: "jid1-Xo5SuA6qc1DFpw@jetpack", minVersion: "1.1.1", - }, - - "ASP": { // Awesome Screenshot Plus - id: "jid0-GXjLLfbCoAx0LcltEdFrEkQdQPI@jetpack", minVersion: "3.0.10", - }, - - "PersonasPlus": { // PersonasPlus - id: "personas@christopher.beard", minVersion: "1.8.0", - }, - - "ACR": { // Add-on Compatibility Reporter - id: "compatibility@addons.mozilla.org", minVersion: "2.2.0", - }, - - // Add-ons used for testing - "test1": { - id: "bootstrap1@tests.mozilla.org", minVersion: "1.0", - }, - - "test2": { - id: "bootstrap2@tests.mozilla.org", minVersion: "1.0", - }, -}; - -// NOTE: Do not modify sets or policies after they have already been -// published to users. They must remain unchanged to provide valid data. - -// Set 2 used during 48 Beta cycle. Kept here for historical reasons. -const set2 = [ADDONS.Greasemonkey, - ADDONS.DYTV, - ADDONS.VDH, - ADDONS.Lightbeam, - ADDONS.ABP, - ADDONS.uBlockOrigin, - ADDONS.Emoji, - ADDONS.ASP, - ADDONS.PersonasPlus]; - -const set49Release = [ - ADDONS.Greasemonkey, - ADDONS.DYTV, - ADDONS.VDH, - ADDONS.Lightbeam, - ADDONS.ABP, - ADDONS.uBlockOrigin, - ADDONS.Emoji, - ADDONS.ASP, - ADDONS.PersonasPlus, - ADDONS.ACR -]; - -// These are only the add-ons in the Add-Ons Manager Discovery -// pane. This set is here in case we need to reduce add-ons -// exposure live on Release. -const set49PaneOnly = [ - ADDONS.ABP, - ADDONS.VDH, - ADDONS.Emoji, - ADDONS.ASP, - ADDONS.ACR -] - -// ================== ADDONS FOR 51 RELEASE ================== -// -// During the 51 beta cycle, we tested e10s with all addons -// except those explicitly marked as being incompatible. -// For release, instead of opening this up, we assembled -// the lists below with all addons that were seen on beta -// and had over 50 installs. -// -// This list is in a new format to allow fast access and also -// to allow controlling by the number of addons installed. - -const set51Release = { - "_65Members_@download.fromdoctopdf.com": {minVersion: "7.102.10.4221", installs: 32092}, - "light_plugin_ACF0E80077C511E59DED005056C00008@kaspersky.com": {minVersion: "4.6.3-15", installs: 27758}, - "_ceMembers_@free.easypdfcombine.com": {minVersion: "7.102.10.4117", installs: 17797}, - "caa1-aDOiCAxFFMOVIX@jetpack": {minVersion: "0.1.7", installs: 13150}, - "{4ED1F68A-5463-4931-9384-8FFF5ED91D92}": {minVersion: "5.0.248.0", installs: 12774}, - "_dbMembers_@free.getformsonline.com": {minVersion: "7.102.10.4251", installs: 11909}, - "_4zMembers_@www.videodownloadconverter.com": {minVersion: "7.102.10.5033", installs: 11612}, - "light_plugin_F6F079488B53499DB99380A7E11A93F6@kaspersky.com": {minVersion: "5.0.141-4-20161031140250", installs: 10944}, - "YoutubeDownloader@PeterOlayev.com": {minVersion: "2.4.1", installs: 10722}, - "{82AF8DCA-6DE9-405D-BD5E-43525BDAD38A}": {minVersion: "8.0.0.9103", installs: 8856}, - "client@anonymox.net": {minVersion: "2.5.2", installs: 8225}, - "_8hMembers_@download.allin1convert.com": {minVersion: "7.102.10.3584", installs: 7681}, - "light_plugin_D772DC8D6FAF43A29B25C4EBAA5AD1DE@kaspersky.com": {minVersion: "4.6.2-42-20160922074409", installs: 7177}, - "_dzMembers_@www.pconverter.com": {minVersion: "7.102.10.4851", installs: 7115}, - "fxdevtools-adapters@mozilla.org": {minVersion: "0.3.5", installs: 6926}, - "_9pMembers_@free.onlinemapfinder.com": {minVersion: "7.102.10.4836", installs: 6583}, - "@DownloadManager": {minVersion: "0.2.1", installs: 6412}, - "ar1er-ewrgfdgomusix@jetpack": {minVersion: "1.0.6", installs: 5975}, - "_agMembers_@free.premierdownloadmanager.com": {minVersion: "7.102.10.4846", installs: 5605}, - "_paMembers_@www.filmfanatic.com": {minVersion: "7.102.10.4163", installs: 5448}, - "_gtMembers_@free.gamingwonderland.com": {minVersion: "7.102.10.4263", installs: 5241}, - "LVD-SAE@iacsearchandmedia.com": {minVersion: "8.5", installs: 4694}, - "_fsMembers_@free.pdfconverterhq.com": {minVersion: "7.102.10.4849", installs: 4526}, - "_6xMembers_@www.readingfanatic.com": {minVersion: "7.102.10.4914", installs: 4417}, - "@mysmartprice-ff": {minVersion: "0.0.6", installs: 4381}, - "jid1-YcMV6ngYmQRA2w@jetpack": {minVersion: "1.37.9", installs: 3899}, - "{58d735b4-9d6c-4e37-b146-7b9f7e79e318}": {minVersion: "1.6", installs: 3733}, - "anttoolbar@ant.com": {minVersion: "2.4.7.47", installs: 3720}, - "adblockpopups@jessehakanen.net": {minVersion: "0.9.2.1-signed.1-signed", installs: 3602}, - "ERAIL.IN.FFPLUGIN@jetpack": {minVersion: "6.0.rev142", installs: 3545}, - "WebProtection@360safe.com": {minVersion: "5.0.0.1005", installs: 3475}, - "yasearch@yandex.ru": {minVersion: "8.20.4", installs: 3299}, - "{19503e42-ca3c-4c27-b1e2-9cdb2170ee34}": {minVersion: "1.5.6.14", installs: 3106}, - "{C1A2A613-35F1-4FCF-B27F-2840527B6556}": {minVersion: "2016.8.1.9", installs: 3083}, - "_b7Members_@free.mytransitguide.com": {minVersion: "7.102.10.4812", installs: 3011}, - "_9tMembers_@free.internetspeedtracker.com": {minVersion: "7.102.10.4339", installs: 2828}, - "_64Members_@www.televisionfanatic.com": {minVersion: "7.102.10.4968", installs: 2821}, - "info@youtube-mp3.org": {minVersion: "1.0.9.1-signed.1-signed", installs: 2717}, - "ffext_basicvideoext@startpage24": {minVersion: "1.97.37.1-signed.1-signed", installs: 2663}, - "MUB-SAE@iacsearchandmedia.com": {minVersion: "8.7", installs: 2650}, - "_4jMembers_@www.radiorage.com": {minVersion: "7.102.10.4916", installs: 2631}, - "@Email": {minVersion: "4.0.12", installs: 2583}, - "_gcMembers_@www.weatherblink.com": {minVersion: "7.38.8.56523", installs: 2519}, - "_dqMembers_@www.downspeedtest.com": {minVersion: "7.102.10.3827", installs: 2445}, - "translator@zoli.bod": {minVersion: "2.1.0.5.1.1-signed", installs: 2310}, - "{a38384b3-2d1d-4f36-bc22-0f7ae402bcd7}": {minVersion: "1.0.0.51", installs: 2190}, - "_1eMembers_@www.videoscavenger.com": {minVersion: "7.38.8.45273", installs: 2185}, - "tvplusnewtab-the-extension1@mozilla.com": {minVersion: "0.1.5", installs: 2155}, - "homepage@mail.ru": {minVersion: "1.0.2", installs: 2124}, - "search@mail.ru": {minVersion: "1.0.7", installs: 2038}, - "_69Members_@www.packagetracer.com": {minVersion: "7.102.10.4831", installs: 2036}, - "{7b8a500a-a464-4624-bd4f-73eaafe0f766}": {minVersion: "3", installs: 2027}, - "paulsaintuzb@gmail.com": {minVersion: "8.2.1", installs: 2005}, - "k7srff_enUS@k7computing.com": {minVersion: "2.4", installs: 1929}, - "_e5Members_@www.productivityboss.com": {minVersion: "7.38.8.46590", installs: 1892}, - "vdpure@link64": {minVersion: "1.97.43", installs: 1860}, - "_9tMembers_@download.internetspeedtracker.com": {minVersion: "7.38.8.56171", installs: 1824}, - "_g3Members_@free.easyphotoedit.com": {minVersion: "7.102.10.4108", installs: 1822}, - "_64Members_@download.televisionfanatic.com": {minVersion: "7.38.9.3004", installs: 1730}, - "_8iMembers_@download.audiotoaudio.com": {minVersion: "7.102.10.3585", installs: 1704}, - "adblockultimate@adblockultimate.net": {minVersion: "2.25", installs: 1648}, - "eagleget_ffext@eagleget.com": {minVersion: "3.8", installs: 1640}, - "_9eMembers_@free.findmefreebies.com": {minVersion: "7.102.10.4193", installs: 1638}, - "content_blocker_663BE8@kaspersky.com": {minVersion: "4.5.4.19.1", installs: 1625}, - "virtual_keyboard_074028@kaspersky.com": {minVersion: "4.5.4.19.1", installs: 1624}, - "browsec@browsec.com": {minVersion: "2.0.3", installs: 1610}, - "@Maps": {minVersion: "4.0.0", installs: 1587}, - "_exMembers_@free.easydocmerge.com": {minVersion: "7.102.10.4137", installs: 1493}, - "{635abd67-4fe9-1b23-4f01-e679fa7484c1}": {minVersion: "5.0.2", installs: 1490}, - "abb@amazon.com": {minVersion: "10.1612.1.304", installs: 1463}, - "{1BC9BA34-1EED-42ca-A505-6D2F1A935BBB}": {minVersion: "6.2.18.1", installs: 1436}, - "mp4downloader@jeff.net": {minVersion: "1.3.3.1-signed.1-signed", installs: 1410}, - "jid1-16aeif9OQIRKxA@jetpack": {minVersion: "1.1.4", installs: 1399}, - "{c45c406e-ab73-11d8-be73-000a95be3b12}": {minVersion: "1.2.11", installs: 1367}, - "online_banking_08806E@kaspersky.com": {minVersion: "4.5.4.19.1", installs: 1356}, - "_ewMembers_@free.mergedocsonline.com": {minVersion: "7.102.10.4710", installs: 1337}, - "@DiscreteSearch": {minVersion: "0.2.1", installs: 1306}, - "{6AC85730-7D0F-4de0-B3FA-21142DD85326}": {minVersion: "2.8.2", installs: 1286}, - "{063DA41A-2561-401B-91FA-AC75E460F4EB}": {minVersion: "1.0.7.1", installs: 1280}, - "netvideohunter@netvideohunter.com": {minVersion: "1.2", installs: 1260}, - "_8eMembers_@download.howtosimplified.com": {minVersion: "7.102.10.4285", installs: 1230}, - "FGZ-SAE@iacsearchandmedia.com": {minVersion: "8.5", installs: 1220}, - "adguardadblocker@adguard.com": {minVersion: "2.4.14", installs: 1172}, - "_39Members_@www.mapsgalaxy.com": {minVersion: "7.102.10.4730", installs: 1171}, - "_euMembers_@free.filesendsuite.com": {minVersion: "7.102.10.4154", installs: 1166}, - "_brMembers_@free.yourtemplatefinder.com": {minVersion: "7.102.10.5047", installs: 1159}, - "_8jMembers_@download.myimageconverter.com": {minVersion: "7.102.10.4778", installs: 1150}, - "_12Members_@free.myscrapnook.com": {minVersion: "7.102.10.4739", installs: 1113}, - "_7eMembers_@www.homeworksimplified.com": {minVersion: "7.102.10.4290", installs: 1109}, - "{fe272bd1-5f76-4ea4-8501-a05d35d823fc}": {minVersion: "2.1.9.1-signed.1-let-fixed.1-signed", installs: 1108}, - "_frMembers_@free.testforspeed.com": {minVersion: "7.102.10.4993", installs: 1107}, - "{068e178c-61a9-4a63-b74f-87404a6f5ea1}": {minVersion: "2", installs: 1104}, - "@Package": {minVersion: "0.2.0", installs: 1092}, - "6asa42dfa4784fsf368g@youtubeconverter.me": {minVersion: "0.1", installs: 1071}, - "_diMembers_@www.free.easymaillogin.com": {minVersion: "7.102.10.4112", installs: 1043}, - "_v4Members_@www.dictionaryboss.com": {minVersion: "7.102.10.3797", installs: 1035}, - "colorPicker@colorPicker": {minVersion: "3.0.1-signed.1-signed", installs: 1023}, - "hotspot-shield@anchorfree.com": {minVersion: "1.2.87", installs: 1000}, - "manishjain9@hotmail.com_easiestyoutube": {minVersion: "7.2.1-signed.1-let-fixed.1-signed", installs: 993}, - "{cd617375-6743-4ee8-bac4-fbf10f35729e}": {minVersion: "2.9.6", installs: 987}, - "@Converter": {minVersion: "4.1.0", installs: 986}, - "{dd3d7613-0246-469d-bc65-2a3cc1668adc}": {minVersion: "1.1.8.1-signed.1-signed", installs: 983}, - "ubufox@ubuntu.com": {minVersion: "3.2", installs: 950}, - "jid1-lpoiffmusixlib@jetpack": {minVersion: "0.1.9", installs: 945}, - "_5aMembers_@download.mywebface.com": {minVersion: "7.102.10.4837", installs: 930}, - "leethax@leethax.net": {minVersion: "2016.12.02", installs: 930}, - "{1A2D0EC4-75F5-4c91-89C4-3656F6E44B68}": {minVersion: "0.6.3.1-signed.1-signed", installs: 885}, - "{64161300-e22b-11db-8314-0800200c9a66}": {minVersion: "0.9.6.18", installs: 875}, - "_bfMembers_@free.snapmyscreen.com": {minVersion: "7.102.10.4951", installs: 827}, - "uriloader@pdf.js": {minVersion: "1.0.277.1-signed.1-signed", installs: 815}, - "{e968fc70-8f95-4ab9-9e79-304de2a71ee1}": {minVersion: "0.7.3.1-signed.1-signed", installs: 805}, - "save-as-pdf-ff@pdfcrowd.com": {minVersion: "1.5.1-signed.1-signed", installs: 804}, - "{75CEEE46-9B64-46f8-94BF-54012DE155F0}": {minVersion: "0.4.15", installs: 794}, - "safesearchplus2@avira.com": {minVersion: "1.4.1.371", installs: 786}, - "easyscreenshot@mozillaonline.com": {minVersion: "1.2.8", installs: 785}, - "_eeMembers_@download.freeradiocast.com": {minVersion: "7.38.8.46366", installs: 783}, - "_89Members_@download.safepcrepair.com": {minVersion: "7.39.8.51080", installs: 777}, - "{a3a5c777-f583-4fef-9380-ab4add1bc2a5}": {minVersion: "2.4.2.1-signed", installs: 771}, - "content_blocker@kaspersky.com": {minVersion: "4.0.10.15", installs: 770}, - "safesearch@avira.com": {minVersion: "1.4.1.371", installs: 767}, - "youtube2mp3@mondayx.de": {minVersion: "1.2.3.1-signed.1-signed", installs: 748}, - "2020Player_IKEA@2020Technologies.com": {minVersion: "5.0.94.1", installs: 736}, - "_edMembers_@free.myradioaccess.com": {minVersion: "7.102.10.4797", installs: 734}, - "_dmMembers_@free.gounzip.com": {minVersion: "7.102.10.4277", installs: 733}, - "Media-Newtab-the-extension1@mozilla.com": {minVersion: "0.1.6", installs: 732}, - "foxmarks@kei.com": {minVersion: "4.3.19", installs: 728}, - "{e8deb9e5-5688-4655-838a-b7a121a9f16e}": {minVersion: "48.4", installs: 726}, - "{195A3098-0BD5-4e90-AE22-BA1C540AFD1E}": {minVersion: "4.1.0.1-signed.1-signed", installs: 722}, - "jid1-4P0kohSJxU1qGg@jetpack": {minVersion: "1.22.550", installs: 719}, - "DailymotionVideoDownloader@PeterOlayev.com": {minVersion: "1.0.6.1-signed.1-signed", installs: 717}, - "jid1-P34HaABBBpOerQ@jetpack": {minVersion: "0.2.1-signed.1-signed", installs: 715}, - "SQLiteManager@mrinalkant.blogspot.com": {minVersion: "0.8.3.1-signed.1-signed", installs: 700}, - "2.0@disconnect.me": {minVersion: "3.15.3.1-signed.1-signed", installs: 693}, - "multifox@hultmann": {minVersion: "3.2.3", installs: 690}, - "_5mMembers_@download.myfuncards.com": {minVersion: "7.102.10.4783", installs: 679}, - "_btMembers_@free.catsandcatapults.com": {minVersion: "7.102.10.3677", installs: 673}, - "pavel.sherbakov@gmail.com": {minVersion: "19.1.1", installs: 666}, - "_fbMembers_@free.smarterpassword.com": {minVersion: "7.102.10.4936", installs: 644}, - "jid2-l8SPBzHJWBIiHQ@jetpack": {minVersion: "3.1", installs: 639}, - "{B17C1C5A-04B1-11DB-9804-B622A1EF5492}": {minVersion: "1.3.2", installs: 633}, - "myplaycitycom@gametab": {minVersion: "1.6", installs: 616}, - "{ad0d925d-88f8-47f1-85ea-8463569e756e}": {minVersion: "2.0.5", installs: 604}, - "{37964A3C-4EE8-47b1-8321-34DE2C39BA4D}": {minVersion: "2.5.4.174", installs: 603}, - "youtubemp3podcaster@jeremy.d.gregorio.com": {minVersion: "3.9.0", installs: 601}, - "caa1-aDOiCAxFFPRIVATE@jetpack": {minVersion: "0.2.0", installs: 598}, - "_f5Members_@free.typingfanatic.com": {minVersion: "7.102.10.5014", installs: 595}, - "_94Members_@www.motitags.com": {minVersion: "7.102.10.4744", installs: 594}, - "{888d99e7-e8b5-46a3-851e-1ec45da1e644}": {minVersion: "45.0.0", installs: 581}, - "_1cMembers_@www.bringmesports.com": {minVersion: "7.102.10.3646", installs: 580}, - "{a6fd85ed-e919-4a43-a5af-8da18bda539f}": {minVersion: "2.9.1.1-signed", installs: 572}, - "{0fc22c4c-93ed-48ea-ad12-dc8039cf3795}": {minVersion: "1.3", installs: 568}, - "homeutil@yandex.ru": {minVersion: "1.0.13", installs: 565}, - "_doMembers_@free.convertanyfile.com": {minVersion: "7.38.8.45860", installs: 563}, - "SocialNewPages-the-extension1@mozilla.com": {minVersion: "0.1.9", installs: 561}, - "wappalyzer@crunchlabz.com": {minVersion: "3.2.7", installs: 557}, - "_5qMembers_@www.zwinky.com": {minVersion: "7.38.8.45270", installs: 551}, - "{0545b830-f0aa-4d7e-8820-50a4629a56fe}": {minVersion: "31.0.9", installs: 531}, - "vk@sergeykolosov.mp": {minVersion: "0.3.9.5", installs: 522}, - "{77b819fa-95ad-4f2c-ac7c-486b356188a9}": {minVersion: "4.0.20130422.1-signed.1-signed", installs: 505}, - "@true-key": {minVersion: "1.23.0.2433", installs: 501}, - "_1pMembers_@www.referenceboss.com": {minVersion: "7.102.10.4932", installs: 499}, - "{C7AE725D-FA5C-4027-BB4C-787EF9F8248A}": {minVersion: "1.0.0.4", installs: 494}, - "alx-ffdeveloper@amazon.com": {minVersion: "3.0.2", installs: 493}, - "{3d7eb24f-2740-49df-8937-200b1cc08f8a}": {minVersion: "1.5.20", installs: 491}, - "_1gMembers_@www.inboxace.com": {minVersion: "7.38.8.56535", installs: 488}, - "{7DD78D43-0962-4d9b-BC76-ABF13B3B2ED1}": {minVersion: "3.5.0.1428", installs: 484}, - "imageblock@hemantvats.com": {minVersion: "3.1", installs: 472}, - "online_banking@kaspersky.com": {minVersion: "4.0.10.15", installs: 463}, - "virtual_keyboard@kaspersky.com": {minVersion: "4.0.10.15", installs: 463}, - "button@scholar.google.com": {minVersion: "1.1.1-signed.1-signed", installs: 463}, - "anti_banner@kaspersky.com": {minVersion: "4.0.10.15", installs: 462}, - "url_advisor@kaspersky.com": {minVersion: "4.0.10.15", installs: 461}, - "{6d96bb5e-1175-4ebf-8ab5-5f56f1c79f65}": {minVersion: "0.9.8", installs: 457}, - "_14Members_@download.totalrecipesearch.com": {minVersion: "7.102.10.4983", installs: 456}, - "{394DCBA4-1F92-4f8e-8EC9-8D2CB90CB69B}": {minVersion: "5.1.1", installs: 447}, - "_57Members_@free.marineaquariumfree.com": {minVersion: "7.102.10.4716", installs: 446}, - "e67f8350-7edf-11e3-baa7-0800200c9a66@fri-gate.org": {minVersion: "2.2.1.1-signed", installs: 446}, - "FireXPath@pierre.tholence.com": {minVersion: "0.9.7.1.1-signed.1-signed", installs: 442}, - "@youtube_downloader": {minVersion: "0.0.9", installs: 435}, - "ff_hpset@jetpack": {minVersion: "1.0.8", installs: 428}, - "{d0bfdcce-52c7-4b32-bb45-948f62db8d3f}": {minVersion: "49.1", installs: 406}, - "_j2Members_@www.soccerinferno.com": {minVersion: "7.102.10.4948", installs: 405}, - "autoform@olifozzy": {minVersion: "1.2.4.1-signed.1-signed", installs: 405}, - "FunSafeTab-the-extension1@mozilla.com": {minVersion: "0.1.9", installs: 405}, - "testpilot@labs.mozilla.com": {minVersion: "1.2.3.1-signed", installs: 405}, - "vwof@drev.com": {minVersion: "3.1.2", installs: 401}, - "_ftMembers_@free.mytelevisionhq.com": {minVersion: "7.102.10.4817", installs: 397}, - "{e001c731-5e37-4538-a5cb-8168736a2360}": {minVersion: "0.9.9.152", installs: 396}, - "{95E84BD3-3604-4AAC-B2CA-D9AC3E55B64B}": {minVersion: "2.0.0.78", installs: 393}, - "_8lMembers_@free.filesharefanatic.com": {minVersion: "7.102.10.4171", installs: 389}, - "clipconverter@clipconverter.cc": {minVersion: "1.5.2", installs: 387}, - "_7jMembers_@download.gardeningenthusiast.com": {minVersion: "7.102.10.4260", installs: 383}, - "antmark@ant.com": {minVersion: "1.1.14", installs: 383}, - "_flMembers_@free.myformsfinder.com": {minVersion: "7.102.10.4784", installs: 381}, - "{c36177c0-224a-11da-8cd6-0800200c9a91}": {minVersion: "3.9.85.1-signed.1-signed", installs: 375}, - "@searchincognito": {minVersion: "0.1.0", installs: 375}, - "{f13b157f-b174-47e7-a34d-4815ddfdfeb8}": {minVersion: "0.9.89.1-signed.1-signed", installs: 373}, - "_5eMembers_@www.translationbuddy.com": {minVersion: "7.38.8.45962", installs: 372}, - "{9c51bd27-6ed8-4000-a2bf-36cb95c0c947}": {minVersion: "11.0.1.1-signed.1-signed", installs: 370}, - "clickclean@hotcleaner.com": {minVersion: "4.1.1-signed.1-signed", installs: 366}, - "jid1-xKH0EoS44u1a2w@jetpack": {minVersion: "0.1.1-signed.1-signed", installs: 366}, - "{c2056674-a37f-4b29-9300-2004759d74fe}": {minVersion: "2.0.0.1090", installs: 361}, - "newtab-tv-the-extension1@mozilla.com": {minVersion: "0.1.5", installs: 359}, - "ascsurfingprotectionnew@iobit.com": {minVersion: "2.1.3", installs: 355}, - "FunTabSafe-the-extension1@mozilla.com": {minVersion: "0.1.9", installs: 353}, - "d.lehr@chello.at": {minVersion: "1.2", installs: 350}, - "anticontainer@downthemall.net": {minVersion: "1.5", installs: 348}, - "{F8A55C97-3DB6-4961-A81D-0DE0080E53CB}": {minVersion: "1.0.10", installs: 347}, - "@FormsApp": {minVersion: "0.2.0", installs: 346}, - "multilinksplus@hugsmile.eu": {minVersion: "3.9.3", installs: 343}, - "jid1-KWFaW5zc0EbtBQ@jetpack": {minVersion: "0.2.0", installs: 335}, - "{e8f509f0-b677-11de-8a39-0800200c9a66}": {minVersion: "1.12.1-signed.1-let-fixed.1-signed", installs: 334}, - "{37E4D8EA-8BDA-4831-8EA1-89053939A250}": {minVersion: "3.0.0.2.1-signed.1-signed", installs: 333}, - "{c8d3bc80-0810-4d21-a2c2-be5f2b2832ac}": {minVersion: "0.98", installs: 332}, - "{cb40da56-497a-4add-955d-3377cae4c33b}": {minVersion: "10.2.0.271", installs: 331}, - "{5546F97E-11A5-46b0-9082-32AD74AAA920}": {minVersion: "0.76.1-signed.1-signed", installs: 325}, - "_14Members_@www.totalrecipesearch.com": {minVersion: "7.38.8.45925", installs: 324}, - "info@mp3it.eu": {minVersion: "1.4.1.1-signed.1-signed", installs: 324}, - "firefox-autofill@googlegroups.com": {minVersion: "3.6.1-signed.1-signed", installs: 317}, - "jid1-TQvJxTBYHA8qXg@jetpack": {minVersion: "0.4.1-signed.1-signed", installs: 315}, - "{8f8fe09b-0bd3-4470-bc1b-8cad42b8203a}": {minVersion: "0.17.1-signed.1-signed", installs: 311}, - "{D4DD63FA-01E4-46a7-B6B1-EDAB7D6AD389}": {minVersion: "0.9.10.1-signed.1-signed", installs: 311}, - "{d7f46ca0-899d-11da-a72b-0800200c9a65}": {minVersion: "0.1.2.1-signed.1-signed", installs: 311}, - "twoo@twoo.com": {minVersion: "1.6.0.1-signed", installs: 303}, - "_29Members_@www.headlinealley.com": {minVersion: "7.38.8.56537", installs: 302}, - "_e2Members_@free.coolpopulargames.com": {minVersion: "7.38.8.45873", installs: 300}, - "TopTVTab-the-extension1@mozilla.com": {minVersion: "0.1.9", installs: 300}, - "tmbepff@trendmicro.com": {minVersion: "9.2.0.1026", installs: 293}, - "_2vMembers_@www.dailybibleguide.com": {minVersion: "7.38.8.52880", installs: 289}, - "{54e46280-0211-11e3-b778-0800200c9a66}": {minVersion: "0.3", installs: 285}, - "_49Members_@www.utilitychest.com": {minVersion: "7.38.8.45977", installs: 284}, - "amcontextmenu@loucypher": {minVersion: "0.4.2.1-signed.1-signed", installs: 284}, - "jid1-r1tDuNiNb4SEww@jetpack": {minVersion: "1.1.2673", installs: 283}, - "_erMembers_@free.getvideoconvert.com": {minVersion: "7.102.10.5038", installs: 281}, - "{b1df372d-8b32-4c7d-b6b4-9c5b78cf6fb1}": {minVersion: "0.87.1-signed.1-signed", installs: 281}, - "jid1-cHKBMlArKdIVEg@jetpack": {minVersion: "1.24.1-signed.1-signed", installs: 281}, - "@90B817C8-8A5C-413B-9DDD-B2C61ED6E79A": {minVersion: "1.09", installs: 278}, - "smarterwiki@wikiatic.com": {minVersion: "5.2.1.1-signed.1-signed", installs: 278}, - "whatsapppanel@alejandrobrizuela.com.ar": {minVersion: "1.1.1.1-signed.1-signed", installs: 277}, - "lazarus@interclue.com": {minVersion: "2.3.1-signed.1-signed", installs: 275}, - "{DEDA1132-B316-11DD-8BC1-4E5D56D89593}": {minVersion: "0.18", installs: 274}, - "_h2Members_@free.calendarspark.com": {minVersion: "7.102.10.3641", installs: 273}, - "@youtubedownloadere": {minVersion: "0.0.1", installs: 273}, - "multirevenue@googlemail.com": {minVersion: "6.1.1", installs: 272}, - "_d9Members_@www.everydaylookup.com": {minVersion: "7.102.10.4140", installs: 271}, - "belgiumeid@eid.belgium.be": {minVersion: "1.0.21", installs: 271}, - "{62DD0A97-FDD4-421b-94A5-D1A9434450C7}": {minVersion: "3.1", installs: 270}, - "the-addon-bar@GeekInTraining-GiT": {minVersion: "3.2.9-compat-fixed-4", installs: 264}, - "@phextension": {minVersion: "6.0.2", installs: 262}, - "FunMediaTab-the-extension1@mozilla.com": {minVersion: "0.1.9", installs: 262}, - "{7f57cf46-4467-4c2d-adfa-0cba7c507e54}": {minVersion: "4.0.1", installs: 259}, - "safefacebook@bkav": {minVersion: "1.0.4", installs: 255}, - "content_blocker_6418E0D362104DADA084DC312DFA8ABC@kaspersky.com": {minVersion: "4.5.3.8", installs: 254}, - "virtual_keyboard_294FF26A1D5B455495946778FDE7CEDB@kaspersky.com": {minVersion: "4.5.3.8", installs: 254}, - "{B821BF60-5C2D-41EB-92DC-3E4CCD3A22E4}": {minVersion: "4.3.1.10", installs: 252}, - "@E9438230-A7DF-4D1F-8F2D-CA1D0F0F7924": {minVersion: "1.08.8.66", installs: 252}, - "jid1-6MGm94JnyY2VkA@jetpack": {minVersion: "2.1.8", installs: 250}, - "{20a82645-c095-46ed-80e3-08825760534b}": {minVersion: "1.3.1.1-signed", installs: 246}, - "{a192bf54-089f-4325-ac25-7eafcd17a342}": {minVersion: "3.2", installs: 246}, - "e389d8c2-5554-4ba2-a36e-ac7a57093130@gmail.com": {minVersion: "1.44.275", installs: 244}, - "yslow@yahoo-inc.com": {minVersion: "3.1.8.1-signed.1-signed", installs: 244}, - "avg@safeguard": {minVersion: "19.6.0.592", installs: 243}, - "@windscribeff": {minVersion: "0.1.43", installs: 242}, - "jid1-PBNne26X1Kn6hQ@jetpack": {minVersion: "3.3.3", installs: 240}, - "{53A03D43-5363-4669-8190-99061B2DEBA5}": {minVersion: "1.5.14", installs: 239}, - "@offersolymp": {minVersion: "0.0.2", installs: 238}, - "firefox@dotvpn.com": {minVersion: "1.0.2", installs: 238}, - "{62760FD6-B943-48C9-AB09-F99C6FE96088}": {minVersion: "4.2.9", installs: 236}, - "jid1-sNL73VCI4UB0Fw@jetpack": {minVersion: "2.1.4", installs: 236}, - "low_quality_flash@pie2k.com": {minVersion: "0.2.1-signed.1-signed", installs: 236}, - "jid1-l6VQSR2FeKnliQ@jetpack": {minVersion: "2.0.1-signed", installs: 235}, - "_5zMembers_@www.couponxplorer.com": {minVersion: "7.102.10.3738", installs: 234}, - "adonis.cuhk@gmail.com": {minVersion: "1.8.9.1-signed.1-signed", installs: 234}, - "_e1Members_@free.actionclassicgames.com": {minVersion: "7.38.8.45834", installs: 232}, - "{ea4637dc-e014-4c17-9c2c-879322d23268}": {minVersion: "2.1.1-signed.1-signed", installs: 229}, - "{4DC70064-89E2-4a55-8FC6-E8CDEAE3618C}": {minVersion: "0.7.7.1-signed.1-signed", installs: 228}, - "odyssey_crypto_control@odysseytec.com": {minVersion: "3.5", installs: 228}, - "seostatus@rubyweb": {minVersion: "1.5.9.1-signed.1-signed", installs: 228}, - "_apMembers_@free.puzzlegamesdaily.com": {minVersion: "7.102.10.4865", installs: 227}, - "@safesearchincognito": {minVersion: "0.1.8", installs: 226}, - "jid1-HfCj61J5q2gaGQ@jetpack": {minVersion: "1.0.3", installs: 224}, - "@stopads": {minVersion: "0.0.4", installs: 224}, - "dta3noaero@vano": {minVersion: "1.0.1", installs: 224}, - "rainbow@colors.org": {minVersion: "1.6.1-signed.1-signed", installs: 223}, - "{146f1820-2b0d-49ef-acbf-d85a6986e10c}": {minVersion: "0.1.9.3.1-signed.1-signed", installs: 222}, - "{b2bfe60c-eef8-4e20-8334-c53afdc1ffdd}": {minVersion: "3.2", installs: 222}, - "{b7870b41-bfb3-44cd-8cc2-e392e51b0874}": {minVersion: "3.8", installs: 222}, - "printPages2Pdf@reinhold.ripper": {minVersion: "0.1.9.3.1-signed", installs: 221}, - "YouTubetoALL@ALLPlayer.org": {minVersion: "0.8.5.1-signed.1-signed", installs: 221}, - "{7a526449-3a92-426f-8ca4-47439918f2b1}": {minVersion: "3.2", installs: 219}, - "jdwimqhayu@yahoo.com": {minVersion: "0.0.0.6", installs: 219}, - "{54FBE89E-C878-46bb-A064-AB327EE26EBC}": {minVersion: "3.8", installs: 214}, - "modernDownloadManager@teo.pl": {minVersion: "0.2.2", installs: 214}, - "{eb8fff7e-1dce-4f3f-a51d-d9513ed6bab4}": {minVersion: "3.8", installs: 211}, - "jid0-YQz0l1jthOIz179ehuitYAOdBEs@jetpack": {minVersion: "2.0.2", installs: 211}, - "{7e80e173-7e63-464e-8252-fe170b15c15a}": {minVersion: "2.3", installs: 210}, - "{35d6291e-1d4b-f9b4-c52f-77e6410d1326}": {minVersion: "4.11.1.0", installs: 209}, - "{3c59c791-aeec-44bb-af60-ff112eea18e3}": {minVersion: "3.2", installs: 209}, - "{90477448-b59c-48cd-98af-6a298cbc15d2}": {minVersion: "3.8", installs: 209}, - "{24d26487-6274-48b1-b500-22f24884f971}": {minVersion: "2.3", installs: 208}, - "{b7389dbc-6646-412f-bbd5-53168ee68a98}": {minVersion: "49", installs: 208}, - "{22181a4d-af90-4ca3-a569-faed9118d6bc}": {minVersion: "11.0.0.1181", installs: 207}, - "printpdf@pavlov.net": {minVersion: "0.76.1-signed.1-signed", installs: 207}, - "@com.virtualjame.disableads": {minVersion: "0.1.0", installs: 206}, - "{9AA46F4F-4DC7-4c06-97AF-6665170634FE}": {minVersion: "1.11.6.1-signed.1-signed", installs: 205}, - "tinyjsdebugger@enigmail.net": {minVersion: "1.1.5", installs: 204}, - "_foMembers_@free.flightsearchapp.com": {minVersion: "7.102.10.4176", installs: 202}, - "jid1-rs90nxQtPi3Asg@jetpack": {minVersion: "1.8.1-signed.1-signed", installs: 201}, - "vlcplaylist@helgatauscher.de": {minVersion: "0.8.1-signed.1-signed", installs: 201}, - "jid1-G80Ec8LLEbK5fQ@jetpack": {minVersion: "1.3.8", installs: 200}, - "_gpMembers_@free.mymapswizard.com": {minVersion: "7.102.10.4775", installs: 199}, - "BestMediaTab-the-extension1@mozilla.com": {minVersion: "0.1.9", installs: 199}, - "info@convert2mp3.net": {minVersion: "2.5.1-signed.1-signed", installs: 199}, - "partnerdefaults@mozilla.com": {minVersion: "1.0.1", installs: 199}, - "qwantcomforfirefox@jetpack": {minVersion: "3.0.28", installs: 199}, - "{65e41d20-f092-41b7-bb83-c6e8a9ab0f57}": {minVersion: "1.2.6", installs: 198}, - "amznUWL2@amazon.com": {minVersion: "1.11", installs: 197}, - "{1b80ae74-4912-44fc-9f27-30f9252a5ad7}": {minVersion: "2.3", installs: 197}, - "{c9b4cd26-6f0e-4972-a9e0-8b77e811aa8f}": {minVersion: "2.3", installs: 197}, - "shopcbtoolbar2@befrugal.com": {minVersion: "2013.3.23.1", installs: 197}, - "trafficlight@bitdefender.com": {minVersion: "0.2.23.1-signed.1-signed", installs: 197}, - "webrank-toolbar@probcomp.com": {minVersion: "4.4.1.1-signed.1-signed", installs: 197}, - "_4lMembers_@www.bibletriviatime.com": {minVersion: "7.102.10.4330", installs: 196}, - "xthunder@lshai.com": {minVersion: "1.3.4.1-signed.1-signed", installs: 196}, - "extension@hidemyass.com": {minVersion: "1.3.2", installs: 195}, - "jid1-MIAJd5BiK7V4Pw@jetpack": {minVersion: "0.9.1-signed.1-signed", installs: 195}, - "{51aa69f8-8825-4def-916a-a766c5e3c0fd}": {minVersion: "3.8", installs: 194}, - "{2bc72c53-9bde-4db2-8479-eda9a5e71f4e}": {minVersion: "3.2", installs: 193}, - "{a95d8332-e4b4-6e7f-98ac-20b733364387}": {minVersion: "1.0.5", installs: 191}, - "ocr@babylon.com": {minVersion: "1.1", installs: 191}, - "{d3b9472c-f8b1-4a10-935b-1087bac8417f}": {minVersion: "3.8", installs: 189}, - "windowpromo@dm73.net": {minVersion: "1.6", installs: 188}, - "alldownloader@link64": {minVersion: "1.00.17.1-signed.1-signed", installs: 187}, - "{3e0e7d2a-070f-4a47-b019-91fe5385ba79}": {minVersion: "3.6.5.2", installs: 185}, - "jid1-vFmnfCkyf5VeSA@jetpack": {minVersion: "0.4.0", installs: 185}, - "@greatdealz": {minVersion: "0.0.3", installs: 184}, - "superstart@enjoyfreeware.org": {minVersion: "7.4.0.1-signed", installs: 183}, - "{c2fc3c2b-a65a-453c-bf95-101fde56ed1d}": {minVersion: "2.3", installs: 182}, - "{53152e75-fd90-472f-9d30-5cba3679eab9}": {minVersion: "48.3", installs: 180}, - "jid0-raWjElI57dRa4jx9CCiYm5qZUQU@jetpack": {minVersion: "3.0.12.1.1-signed.1-signed", installs: 180}, - "_ivMembers_@free.simplepictureedit.com": {minVersion: "7.102.10.14166", installs: 179}, - "jid1-wKRSK9TpFpr9Hw@jetpack": {minVersion: "0.92", installs: 179}, - "emailExtractor@penzil.com": {minVersion: "1.3.1-signed.1-signed", installs: 178}, - "{60B7679C-BED9-11E5-998D-8526BB8E7F8B}": {minVersion: "6.3", installs: 177}, - "@pdfit": {minVersion: "0.1.9", installs: 177}, - "jid1-6AyZ1PQXsR9LgQ@jetpack": {minVersion: "0.2.1", installs: 177}, - "_6oMembers_@free.heroicplay.com": {minVersion: "7.38.8.46626", installs: 175}, - "{4BBDD651-70CF-4821-84F8-2B918CF89CA3}": {minVersion: "8.9.3.1", installs: 173}, - "jid1-GeRCnsiDhZiTvA@jetpack": {minVersion: "1.0.3", installs: 172}, - "jid0-zs24wecdcQo0Lp18D7QOV4WSZFo@jetpack": {minVersion: "0.2.1-signed.1-signed", installs: 171}, - "{c50ca3c4-5656-43c2-a061-13e717f73fc8}": {minVersion: "5.0.1.48.1-signed.1-signed", installs: 170}, - "selenium_ide_buttons@egarracingteam.com.ar": {minVersion: "1.2.0.1-signed.1-signed", installs: 170}, - "WSVCU@Wondershare.com": {minVersion: "7.1.0", installs: 169}, - "{4cc4a13b-94a6-7568-370d-5f9de54a9c7f}": {minVersion: "2.7.1-signed.1-signed", installs: 168}, - "{aa84ce40-4253-a00a-8cd6-0800200f9a67}": {minVersion: "3.12.0", installs: 168}, - "FasterFox_Lite@BigRedBrent": {minVersion: "3.9.9Lite.1-signed.1-signed", installs: 167}, - "{6cc0f0f7-a6e2-4834-9682-24de2229b51e}": {minVersion: "23.6", installs: 166}, - "{b749fc7c-e949-447f-926c-3f4eed6accfe}": {minVersion: "0.7.1.1.1-signed.1-signed", installs: 166}, - "@mendeleyimporter": {minVersion: "1.6.8", installs: 166}, - "ALone-live@ya.ru": {minVersion: "1.4.11", installs: 166}, - "{4093c4de-454a-4329-8aff-c6b0b123c386}": {minVersion: "0.8.14.1-signed.1-signed", installs: 165}, - "cookiemgr@jayapal.com": {minVersion: "5.12", installs: 164}, - "touchenex@raon.co.kr": {minVersion: "1.0.1.11", installs: 163}, - "{b0e1b4a6-2c6f-4e99-94f2-8e625d7ae255}": {minVersion: "3.5.0.1-signed.1-signed", installs: 162}, - "isreaditlater@ideashower.com": {minVersion: "3.0.6.1-signed", installs: 161}, - "safesearchplus@avira.com": {minVersion: "1.4.1.371", installs: 161}, - "_e0Members_@www.downshotfree.com": {minVersion: "7.102.10.3833", installs: 159}, - "LDSI_plashcor@gmail.com": {minVersion: "1.1.0.3", installs: 159}, - "jid1-9ETkKdBARv7Iww@jetpack": {minVersion: "0.20.1-signed.1-signed", installs: 157}, - "jid1-CGxMej0nDJTjwQ@jetpack": {minVersion: "1.0.1-signed.1-signed", installs: 157}, - "{00f7ab9f-62f4-4145-b2f9-38d579d639f6}": {minVersion: "49", installs: 156}, - "googledictionary@toptip.ca": {minVersion: "7.5", installs: 156}, - "shopearn@prodege.com": {minVersion: "219", installs: 156}, - "fvdmedia@gmail.com": {minVersion: "11.0.1", installs: 155}, - "magicplayer_unlisted@acestream.org": {minVersion: "1.1.42", installs: 155}, - "{0538E3E3-7E9B-4d49-8831-A227C80A7AD3}": {minVersion: "2.2.2.1-signed.1-let-fixed.1-signed", installs: 154}, - "{73007fef-a6e0-47d3-b4e7-dfc116ed6f65}": {minVersion: "1.15.1-signed.1-signed", installs: 153}, - "{cd617372-6743-4ee4-bac4-fbf60f35719e}": {minVersion: "2.0.1-signed.1-signed", installs: 152}, - "TopSecurityTab-the-extension1@mozilla.com": {minVersion: "0.1.9", installs: 152}, - "jid1-hDf2iQXGiUjzGQ@jetpack": {minVersion: "2.5.0", installs: 151}, - "_dnMembers_@www.free.webmailworld.com": {minVersion: "7.102.10.5052", installs: 149}, - "jid1-rrMTK7JqsxNOeQ@jetpack": {minVersion: "2.1.0", installs: 149}, - "jid1-XgC5trUcILmXBw@jetpack": {minVersion: "2.0.3", installs: 149}, - "online_banking_69A4E213815F42BD863D889007201D82@kaspersky.com": {minVersion: "4.5.3.8", installs: 148}, - "jid1-AXn9cXcB4fD1QQ@jetpack": {minVersion: "0.7.4", installs: 148}, - "feedly@devhd": {minVersion: "16.0.528.1-signed.1-signed", installs: 147}, - "{6E727987-C8EA-44DA-8749-310C0FBE3C3E}": {minVersion: "2.0.0.11", installs: 146}, - "{1082eb84-f0f2-11e5-8e18-9bb85ab7992e}": {minVersion: "1.07", installs: 146}, - "{c151d79e-e61b-4a90-a887-5a46d38fba99}": {minVersion: "2.8.8", installs: 146}, - "public.proartex@gmail.com": {minVersion: "1.1.3", installs: 145}, - "jid1-8J7ayxTha4KqKQ@jetpack": {minVersion: "1.1.1-signed.1-signed", installs: 144}, - "stealthyextension@gmail.com": {minVersion: "3.0.1.1-signed", installs: 144}, - "_beMembers_@free.dailylocalguide.com": {minVersion: "7.38.9.7920", installs: 143}, - "mytube@ashishmishra.in": {minVersion: "0.979.1-signed.1-signed", installs: 142}, - "@A3592ADB-854A-443A-854E-EB92130D470D": {minVersion: "1.08.8.88", installs: 139}, - "FunkyTVTabs-the-extension1@mozilla.com": {minVersion: "0.1.9", installs: 139}, - "jid1-QpHD8URtZWJC2A@jetpack": {minVersion: "4.3.0", installs: 138}, - "savedeo-video-downloader@fczbkk.com": {minVersion: "0.4.1.1-signed.1-signed", installs: 137}, - "toolbar@shopathome.com": {minVersion: "8.20.3.1", installs: 137}, - "_dyMembers_@www.dezipper.com": {minVersion: "7.102.10.3775", installs: 135}, - "jid0-zXo3XFGyiDalgkeEO4UYJTUwo2I@jetpack": {minVersion: "1.0.0", installs: 134}, - "{d57c9ff1-6389-48fc-b770-f78bd89b6e8a}": {minVersion: "1.46.1-signed.1-signed", installs: 133}, - "@searchlock-fx": {minVersion: "1.1.6", installs: 133}, - "dm@jetpack": {minVersion: "0.0.2", installs: 133}, - "proxyselector@mozilla.org": {minVersion: "1.31.1-signed.1-signed", installs: 133}, - "{065829BC-17B5-4C0B-9429-3173C361092E}": {minVersion: "1.0.8", installs: 132}, - "{ada4b710-8346-4b82-8199-5de2b400a6ae}": {minVersion: "2.1.5.5.3", installs: 132}, - "readable@evernote.com": {minVersion: "10.2.1.7.1-signed", installs: 131}, - "{d48a39ba-8f80-4fce-8ee1-bc710561c55d}": {minVersion: "3.1.0.1-signed.1-signed", installs: 131}, - "autorefresh@plugin": {minVersion: "1.0.2.1-signed.1-signed", installs: 130}, - "SafeBrowseSearch-the-extension1@mozilla.com": {minVersion: "0.1.2", installs: 130}, - "browsermodulecorp@browcorporation.org": {minVersion: "2.3", installs: 129}, - "wisestamp@wisestamp.com": {minVersion: "4.14.20", installs: 127}, - "_63Members_@www.aplusgamer.com": {minVersion: "7.38.8.45832", installs: 126}, - "bestproxyswitcher@bestproxyswitcher.com": {minVersion: "3.4.6.1-signed.1-signed", installs: 126}, - "jid1-AVgCeF1zoVzMjA@jetpack": {minVersion: "0.9.5.6", installs: 126}, - "{ce7e73df-6a44-4028-8079-5927a588c948}": {minVersion: "1.1.4", installs: 125}, - "{E71B541F-5E72-5555-A47C-E47863195841}": {minVersion: "3.0.3", installs: 125}, - "{F5DDF39C-9293-4d5e-9AA8-E04E6DD5E9B4}": {minVersion: "1.6.3.1-signed.1-signed", installs: 125}, - "@simplepopupblocker": {minVersion: "1.2.1", installs: 125}, - "commonfix@mozillaonline.com": {minVersion: "0.13", installs: 125}, - "searchme@mybrowserbar.com": {minVersion: "2.8", installs: 125}, - "_4wMembers_@www.retrogamer.com": {minVersion: "7.38.8.46604", installs: 124}, - "{71328583-3CA7-4809-B4BA-570A85818FBB}": {minVersion: "0.8.6.3.1-let-fixed", installs: 123}, - "dmremote@westbyte.com": {minVersion: "1.9.3", installs: 123}, - "@google-translate-menu": {minVersion: "1.0.1", installs: 122}, - "_aaMembers_@free.eliteunzip.com": {minVersion: "7.39.8.50909", installs: 121}, - "{8620c15f-30dc-4dba-a131-7c5d20cf4a29}": {minVersion: "3.9", installs: 121}, - "{eb4b28c8-7f2d-4327-a00c-40de4299ba44}": {minVersion: "1.7", installs: 121}, - "flashlight@stephennolan.com.au": {minVersion: "1.2.1-signed.1-signed", installs: 121}, - "useragentoverrider@qixinglu.com": {minVersion: "0.4.1", installs: 121}, - "{1B33E42F-EF14-4cd3-B6DC-174571C4349C}": {minVersion: "4.7", installs: 120}, - "_dxMembers_@www.download-freemaps.com": {minVersion: "7.38.8.46371", installs: 120}, - "{95ab36d4-fb6f-47b0-8b8d-e5f3bd547953}": {minVersion: "4.20.13.1-signed.1-signed", installs: 120}, - "FirefoxAddon@similarWeb.com": {minVersion: "4.0.6", installs: 120}, - "flashstopper@byo.co.il": {minVersion: "1.4.2", installs: 120}, - "{15e67a59-bd3d-49ae-90dd-b3d3fd14c2ed}": {minVersion: "1.0.3.1-signed.1-signed", installs: 119}, - "{c37bac34-849a-4d28-be41-549b2c76c64e}": {minVersion: "2.6", installs: 119}, - "{03B08592-E5B4-45ff-A0BE-C1D975458688}": {minVersion: "1.1.1-signed.1-signed", installs: 118}, - "newtabgoogle@graememcc.co.uk": {minVersion: "1.0.2.1-signed.1-signed", installs: 118}, - "SocialNewtabs-the-extension1@mozilla.com": {minVersion: "0.1.9", installs: 118}, - "@kikikokicicidada": {minVersion: "2.1.2", installs: 117}, - "{9D6218B8-03C7-4b91-AA43-680B305DD35C}": {minVersion: "4.0.5", installs: 116}, - "extension@one-tab.com": {minVersion: "1.17.0", installs: 116}, - "{22119944-ED35-4ab1-910B-E619EA06A115}": {minVersion: "7.9.21.5", installs: 115}, - "admin@hide-my-ip.org": {minVersion: "9.6.3", installs: 115}, - "bdwteffv19@bitdefender.com": {minVersion: "2.2.1", installs: 115}, - "exif_viewer@mozilla.doslash.org": {minVersion: "2.00.1-signed.1-signed", installs: 115}, - "MyStartab-the-extension1@mozilla.com": {minVersion: "0.1.9", installs: 115}, - "coralietab@mozdev.org": {minVersion: "2.04.20110724.1-signed.1-signed", installs: 113}, - "gaurangnshah@gmail.com": {minVersion: "1.3.2.1-signed.1-signed", installs: 113}, - "ImagePicker@topolog.org": {minVersion: "1.9.4", installs: 113}, - "{d49a148e-817e-4025-bee3-5d541376de3b}": {minVersion: "3.1.1-signed.1-signed", installs: 112}, - "firebug@tools.sitepoint.com": {minVersion: "1.6.1-signed.1-signed", installs: 111}, - "add-to-searchbox@maltekraus.de": {minVersion: "2.9", installs: 110}, - "captiondownloader@hiephm.com": {minVersion: "2.3.1-signed.1-signed", installs: 110}, - "jid1-LYopfl0r00ZV5k@jetpack": {minVersion: "1.0.1-signed.1-signed", installs: 110}, - "{7CA9CF31-1C73-46CD-8377-85AB71EA771F}": {minVersion: "5.0.12", installs: 109}, - "jid1-HdwPLukcGQeOSh@jetpack": {minVersion: "1.2.3", installs: 108}, - "{0AA9101C-D3C1-4129-A9B7-D778C6A17F82}": {minVersion: "2.09.1-signed", installs: 107}, - "CookiesIE@yahoo.com": {minVersion: "1.0.1-signed.1-signed", installs: 107}, - "selenium-expert_selenium-ide@Samit.Badle": {minVersion: "0.25.1-signed.1-signed", installs: 107}, - "{19EB90DC-A456-458b-8AAC-616D91AAFCE1}": {minVersion: "1.0.1-signed", installs: 105}, - "application@itineraire.info": {minVersion: "4.5.0", installs: 105}, - "rest-easy@quickmediasolutions.com": {minVersion: "0.3.1.1-signed", installs: 105}, - "TopSocialHub-the-extension1@mozilla.com": {minVersion: "0.1.9", installs: 105}, - "{7affbfae-c4e2-4915-8c0f-00fa3ec610a1}": {minVersion: "6.36.32", installs: 104}, - "azhang@cloudacl.com": {minVersion: "0.19.6.9.1-signed.1-signed", installs: 104}, - "FunCyberTab-the-extension1@mozilla.com": {minVersion: "0.1.9", installs: 104}, - "SkipScreen@SkipScreen": {minVersion: "0.7.2.1-signed.1-signed", installs: 104}, - "toolbar@seomoz.org": {minVersion: "3.1.18", installs: 104}, - "{8b86149f-01fb-4842-9dd8-4d7eb02fd055}": {minVersion: "0.26.1-signed.1-signed", installs: 103}, - "fbp@fbpurity.com": {minVersion: "9.3.2.1-signed", installs: 103}, - "jid1-V8ev2melBDV3qQ@jetpack": {minVersion: "1.0.12.1-signed.1-signed", installs: 103}, - "_fvMembers_@free.directionsace.com": {minVersion: "7.102.10.3790", installs: 102}, - "{b6b1a201-b252-484f-b9fe-68efbb273fbd}": {minVersion: "1.10.1-signed.1-signed", installs: 102}, - "flashfirebug@o-minds.com": {minVersion: "4.9.1", installs: 102}, - "_ebMembers_@download.metrohotspot.com": {minVersion: "7.102.10.4735", installs: 101}, - "{2e17e2b2-b8d4-4a67-8d7b-fafa6cc9d1d0}": {minVersion: "1.2.7.0.1-signed.1-signed", installs: 101}, - "{ea61041c-1e22-4400-99a0-aea461e69d04}": {minVersion: "0.2.4.1-signed.1-signed", installs: 101}, - "rapportive@rapportive.com": {minVersion: "1.4.0.1.1-signed.1-signed", installs: 101}, - "_dvMembers_@www.testinetspeed.com": {minVersion: "7.38.8.45918", installs: 100}, - "{9aad3da6-6c46-4ef0-9109-6df5eaaf597c}": {minVersion: "1.4.1.1-signed.1-signed", installs: 100}, - "{c2b1f3ae-5cd5-49b7-8a0c-2c3bcbbbb294}": {minVersion: "1.1.1-signed.1-signed", installs: 100}, - "jid0-w1UVmoLd6VGudaIERuRJCPQx1dQ@jetpack": {minVersion: "1.6.8.1-signed", installs: 100}, - "_cxMembers_@www.autopcbackup.com": {minVersion: "7.102.10.3597", installs: 99}, - "vpn@hide-my-ip.org": {minVersion: "10.6.2", installs: 99}, - "{1a5dabbd-0e74-41da-b532-a364bb552cab}": {minVersion: "1.0.9.1-signed", installs: 98}, - "FirePHPExtension-Build@firephp.org": {minVersion: "0.7.4.1-signed.1-signed", installs: 98}, - "jid1-UXDr6c69BeyPVw@jetpack": {minVersion: "0.8.2", installs: 98}, - "TopSafeTab-the-extension1@mozilla.com": {minVersion: "0.1.9", installs: 98}, - "{3b56bcc7-54e5-44a2-9b44-66c3ef58c13e}": {minVersion: "0.9.7.4", installs: 97}, - "autoreload@yz.com": {minVersion: "1.21", installs: 97}, - "manish.p05@gmail.com": {minVersion: "12.9", installs: 97}, - "videoresumer@jetpack": {minVersion: "1.1.4", installs: 97}, - "@Radio": {minVersion: "0.2.0", installs: 96}, - "_hfMembers_@free.everydaymanuals.com": {minVersion: "7.102.10.4142", installs: 96}, - "jid0-jJRRRBMgoShUhb07IvnxTBAl29w@jetpack": {minVersion: "2.0.4", installs: 96}, - "rikaichan-jpen@polarcloud.com": {minVersion: "2.01.160101", installs: 96}, - "{7c6cdf7c-8ea8-4be7-ae5a-0b3effe14d66}": {minVersion: "49.1", installs: 95}, - "{FDBAD97E-A258-4fe3-9CF6-60CF386C4422}": {minVersion: "2.0.1.6", installs: 95}, - "intgcal@egarracingteam.com.ar": {minVersion: "1.5.1", installs: 95}, - "MediaNewTab-the-extension1@mozilla.com": {minVersion: "0.1.6", installs: 95}, - "{9EB34849-81D3-4841-939D-666D522B889A}": {minVersion: "2.4.0.157", installs: 94}, - "{158d7cb3-7039-4a75-8e0b-3bd0a464edd2}": {minVersion: "2.7.1-signed.1-signed", installs: 94}, - "jid1-ach2kaGSshPJCg@jetpack": {minVersion: "0.1.1-signed.1-signed", installs: 94}, - "jid1-cwbvBTE216jjpg@jetpack": {minVersion: "2.1.0.1-signed.1-signed", installs: 94}, - "{f36c6cd1-da73-491d-b290-8fc9115bfa55}": {minVersion: "3.0.9.1-signed.1-let-fixed.1-signed", installs: 93}, - "dmpluginff@westbyte.com": {minVersion: "1.4.12", installs: 93}, - "firefox@serptrends.com": {minVersion: "0.8.14", installs: 93}, - "panel-plugin@effectivemeasure.com": {minVersion: "4.0.0", installs: 93}, - "_evMembers_@www.free.bestbackground.com": {minVersion: "7.102.10.3607", installs: 92}, - "canitbecheaper@trafficbroker.co.uk": {minVersion: "3.9.78", installs: 92}, - "favorites_selenium-ide@Samit.Badle": {minVersion: "2.0.1-signed.1-signed", installs: 92}, - "{5F590AA2-1221-4113-A6F4-A4BB62414FAC}": {minVersion: "0.45.8.20130519.3.1-signed.1-signed", installs: 90}, - "{3e9bb2a7-62ca-4efa-a4e6-f6f6168a652d}": {minVersion: "2.7.7.1-signed.1-signed", installs: 90}, - "{ab4b5718-3998-4a2c-91ae-18a7c2db513e}": {minVersion: "1.2.0.1-signed.1-signed", installs: 90}, - "2020Player_WEB@2020Technologies.com": {minVersion: "5.0.94.0", installs: 90}, - "translator@dontfollowme.net": {minVersion: "2.0.5", installs: 90}, - "YouTubeAutoReplay@arikv.com": {minVersion: "3.3.1-signed.1-signed", installs: 90}, - "{a949831f-d9c0-45ae-8c60-91c2a86fbfb6}": {minVersion: "0.2.1-signed.1-signed", installs: 89}, - "@vpn-unlimited-secure-proxy": {minVersion: "4.4", installs: 89}, - "jid1-JcGokIiQyjoBAQ@jetpack": {minVersion: "0.6.1-signed.1-signed", installs: 89}, - "_73Members_@www.easyhomedecorating.com": {minVersion: "7.102.10.4129", installs: 88}, - "{065ee92a-ad57-42a2-b6d5-466b6fd8e24d}": {minVersion: "0.11.6.1-signed.1-signed", installs: 88}, - "{455D905A-D37C-4643-A9E2-F6FEFAA0424A}": {minVersion: "0.8.17.1-signed.1-signed", installs: 88}, - "{7eb3f691-25b4-4a85-9038-9e57e2bcd537}": {minVersion: "0.4.4.1-signed.1-signed", installs: 88}, - "FunSocialTab-the-extension1@mozilla.com": {minVersion: "0.1.9", installs: 88}, - "Lucifox@lucidor.org": {minVersion: "0.9.13", installs: 88}, - "YourMediaTab-the-extension1@mozilla.com": {minVersion: "0.1.9", installs: 88}, - "youtube-video-player@lejenome.me": {minVersion: "0.2.38.1-signed.1-signed", installs: 88}, - "_hgMembers_@free.atozmanuals.com": {minVersion: "7.102.10.3604", installs: 87}, - "abb-acer@amazon.com": {minVersion: "10.161.13.1002", installs: 87}, - "gmail_panel@alejandrobrizuela.com.ar": {minVersion: "1.2.0", installs: 87}, - "izer@camelcamelcamel.com": {minVersion: "2.8.2", installs: 87}, - "tvnewtab-the-extension1@mozilla.com": {minVersion: "0.1.5", installs: 87}, - "vlc_shortcut@kosan.kosan": {minVersion: "0.8.3.0", installs: 87}, - "youtubeunblocker@unblocker.yt": {minVersion: "0.6.20", installs: 86}, - "email@jetpack": {minVersion: "0.0.16", installs: 86}, - "extensions@gismeteo.com": {minVersion: "5.1.0.2", installs: 86}, - "idaremote@westbyte.com": {minVersion: "1.6.3", installs: 86}, - "{725fc0a6-1f6b-4cf9-ae17-748d111dc16d}": {minVersion: "1.1.0", installs: 85}, - "jid1-461B0PwxL3oTt1@jetpack": {minVersion: "0.2.1-signed.1-signed", installs: 85}, - "webdavlauncher@benryan.com": {minVersion: "1.1.0", installs: 85}, - "jid1-ZM3BerwS6FsQAg@jetpack": {minVersion: "0.4.1-signed", installs: 84}, - "_fwMembers_@free.howtosuite.com": {minVersion: "7.102.10.4280", installs: 84}, - "{023e9ca0-63f3-47b1-bcb2-9badf9d9ef28}": {minVersion: "4.4.3.1-signed.1-signed", installs: 84}, - "{25A1388B-6B18-46c3-BEBA-A81915D0DE8F}": {minVersion: "1.7.8.5.1-signed.1-signed", installs: 84}, - "{75493B06-1504-4976-9A55-B6FE240FF0BF}": {minVersion: "3.4.0.0", installs: 84}, - "facepaste.firefox.addon@azabani.com": {minVersion: "2.91", installs: 84}, - "jid1-cplLTTY501TB2Q@jetpack": {minVersion: "0.5.1", installs: 84}, - "_d1Members_@free.mysocialshortcut.com": {minVersion: "7.102.10.4792", installs: 83}, - "{761a54f1-8ccf-4112-9e48-dbf72adf6244}": {minVersion: "2.3.1-signed.1-signed", installs: 83}, - "{BBB77B49-9FF4-4d5c-8FE2-92B1D6CD696C}": {minVersion: "2.0.0.1083", installs: 83}, - "{a3a5c777-f583-4fef-9380-ab4add1bc2a2}": {minVersion: "2.1.4", installs: 82}, - "{eb80b076-a444-444c-a590-5aee5d977d80}": {minVersion: "2.6.18", installs: 82}, - "KVAllmytube@KeepVid.com": {minVersion: "4.10.0", installs: 82}, - "lumerias-instagram@lumerias.com": {minVersion: "1.3", installs: 82}, - "omnibar@ajitk.com": {minVersion: "0.7.28.20141004.1-signed.1-signed", installs: 81}, - "@autofillanyforms-easytatkal": {minVersion: "7.51.0", installs: 81}, - "@youtuberightclick": {minVersion: "0.0.3", installs: 81}, - "autoproxy@autoproxy.org": {minVersion: "0.4b2.2013051811.1-signed.1-let-fixed.1-signed", installs: 80}, - "{e33788ea-0bb9-4502-9c77-bdc551afc8ad}": {minVersion: "1.0.4", installs: 80}, - "dmmm@westbyte.com": {minVersion: "1.3.4", installs: 80}, - "easycopy@smokyink.com": {minVersion: "2.7.0", installs: 80}, - "jid1-LelsJ0Oz0rt71A@jetpack": {minVersion: "2.0.0", installs: 80}, - "_f7Members_@download.smsfrombrowser.com": {minVersion: "7.38.8.45917", installs: 79}, - "{6614d11d-d21d-b211-ae23-815234e1ebb5}": {minVersion: "3.9.13", installs: 79}, - "FunTvTab-the-extension1@mozilla.com": {minVersion: "0.1.9", installs: 79}, - "{4204c864-50bf-467a-95b3-0912b7f15869}": {minVersion: "1.2.00.1-signed.1-signed", installs: 78}, - "{987311C6-B504-4aa2-90BF-60CC49808D42}": {minVersion: "3.1-signed.1-signed", installs: 78}, - "uploader@adblockfilters.mozdev.org": {minVersion: "2.1.1-signed.1-let-fixed.1-signed", installs: 77}, - "PageRank@addonfactory.in": {minVersion: "2.0.1-signed.1-signed", installs: 77}, - "restartbutton@strk.jp": {minVersion: "0.1.5.1-signed.1-signed", installs: 77}, - "text2voice@vik.josh": {minVersion: "1.15", installs: 77}, - "_dpMembers_@free.findyourmaps.com": {minVersion: "7.102.10.4185", installs: 76}, - "53ffxtbr@www.dailyfitnesscenter.com": {minVersion: "7.36.8.15623", installs: 76}, - "gary@builtwith.com": {minVersion: "1.9.6.1-signed.1-signed", installs: 76}, - "idamm@westbyte.com": {minVersion: "1.3.2", installs: 76}, - "jid1-3gu11JeYBiIuJA@jetpack": {minVersion: "3.1.1", installs: 76}, - "jid1-zV8eHYwTDNUtwQ@jetpack": {minVersion: "1.0.4", installs: 76}, - "nst@neiron.ru": {minVersion: "7.3.0.2", installs: 76}, - "service@touchpdf.com": {minVersion: "1.15.1-signed.1-signed", installs: 76}, - "{02450954-cdd9-410f-b1da-db804e18c671}": {minVersion: "0.96.3.1-signed.1-signed", installs: 75}, - "{4176DFF4-4698-11DE-BEEB-45DA55D89593}": {minVersion: "0.8.50.1-signed.1-signed", installs: 75}, - "{DAD0F81A-CF67-4eed-98D6-26F6E47274CA}": {minVersion: "1.8.1-signed.1-signed", installs: 75}, - "dealxplorermysites770@yahoo.com": {minVersion: "0.0.0.1", installs: 75}, - "firefox@online-convert.com": {minVersion: "1.4.1-signed.1-signed", installs: 75}, - "jid1-zmgYgiQPXJtjNA@jetpack": {minVersion: "1.23", installs: 75}, - "_evMembers_@www.bestbackground.com": {minVersion: "7.38.9.7654", installs: 74}, - "dmbarff@westbyte.com": {minVersion: "1.5.11", installs: 74}, - "inf@youtube-mp3.video": {minVersion: "0.1", installs: 74}, - "jid1-e7w0SHT82Gv9qA@jetpack": {minVersion: "1.2", installs: 74}, - "NewTabTVCool-the-extension1@mozilla.com": {minVersion: "0.1.9", installs: 74}, - "{E173B749-DB5B-4fd2-BA0E-94ECEA0CA55B}": {minVersion: "7.4.1-signed", installs: 73}, - "{9BAE5926-8513-417d-8E47-774955A7C60D}": {minVersion: "1.1.1d.1-signed.1-signed", installs: 73}, - "{3cc6c6ba-654c-417e-a8af-6997ac388ae1}": {minVersion: "49", installs: 72}, - "{daf44bf7-a45e-4450-979c-91cf07434c3d}": {minVersion: "2.0.5", installs: 72}, - "{dbac9680-d559-4cd4-9765-059879e8c467}": {minVersion: "5.0.5", installs: 72}, - "application@recettes.net": {minVersion: "4.5.0", installs: 72}, - "idapluginff@westbyte.com": {minVersion: "1.5.9", installs: 71}, - "imgflashblocker@shimon.chohen": {minVersion: "0.7.1-signed.1-signed", installs: 71}, - "inspector@mozilla.org": {minVersion: "2.0.16.1-signed", installs: 71}, - "jid1-ReWlW1efOwaQJQ@jetpack": {minVersion: "1.1.2", installs: 71}, - "youtubedownloader@trafficterminal.com": {minVersion: "1.0.1.1-signed.1-signed", installs: 71}, - "FavIconReloader@mozilla.org": {minVersion: "0.8.1-signed", installs: 70}, - "_2bMembers_@www.bettercareersearch.com": {minVersion: "7.38.8.45828", installs: 70}, - "{5e594888-3e8e-47da-b2c6-b0b545112f84}": {minVersion: "1.3.18", installs: 70}, - "@greatdealzu": {minVersion: "0.0.3", installs: 70}, - "86ffxtbr@download.yourvideochat.com": {minVersion: "7.36.8.15938", installs: 70}, - "google@hitachi.com": {minVersion: "0.3.1-signed.1-signed", installs: 70}, - "{6e84150a-d526-41f1-a480-a67d3fed910d}": {minVersion: "1.5.6.1-signed.1-signed", installs: 69}, - "firepicker@thedarkone": {minVersion: "1.4.3.1-signed.1-signed", installs: 69}, - "jid0-AocRXUCRsLTCYvn6bgJERnwfuqw@jetpack": {minVersion: "2.8.3.1-signed.1-signed", installs: 69}, - "nortonsecurity@symantec.com": {minVersion: "7.2.0f90", installs: 69}, - "{ef4e370e-d9f0-4e00-b93e-a4f274cfdd5a}": {minVersion: "1.4.10.1-signed", installs: 68}, - "{d4e0dc9c-c356-438e-afbe-dca439f4399d}": {minVersion: "49.1", installs: 68}, - "{E6C93316-271E-4b3d-8D7E-FE11B4350AEB}": {minVersion: "2.1.25.1-signed.1-signed", installs: 68}, - "{fa8476cf-a98c-4e08-99b4-65a69cb4b7d4}": {minVersion: "1.7.6.1", installs: 68}, - "simplesiteblocker@example.com": {minVersion: "1.1.1-signed.1-signed", installs: 68}, - "_fpMembers_@free.passwordlogic.com": {minVersion: "7.102.10.4853", installs: 67}, - "{6e764c17-863a-450f-bdd0-6772bd5aaa18}": {minVersion: "1.0.3.1-signed.1-signed", installs: 67}, - "adbeaver@adbeaver.org": {minVersion: "0.7.2.9", installs: 67}, - "application2@allo-pages.fr": {minVersion: "4.5.0", installs: 67}, - "arf3@getcartt.com": {minVersion: "1.2.3", installs: 67}, - "clearcache@michel.de.almeida": {minVersion: "2.0.1.1-signed.1-signed", installs: 67}, - "fbmessengerpanel@alejandrobrizuela.com.ar": {minVersion: "1.0.3.1-signed.1-signed", installs: 67}, - "tilt@mozilla.com": {minVersion: "1.0.1.1-signed.1-signed", installs: 67}, - "toolbar_AVIRA-V7@apn.ask.com": {minVersion: "127.25", installs: 67}, - "{524B8EF8-C312-11DB-8039-536F56D89593}": {minVersion: "4.91.0.0", installs: 66}, - "{9d1f059c-cada-4111-9696-41a62d64e3ba}": {minVersion: "0.17.0.1", installs: 66}, - "{B068AC18-0121-4e67-9A7E-6386F93F4F7A}": {minVersion: "2.4", installs: 66}, - "@lottadealsun": {minVersion: "0.0.1", installs: 66}, - "@thebestyoutubedownloader": {minVersion: "1.0.0.7", installs: 66}, - "TopSocialTab-the-extension1@mozilla.com": {minVersion: "0.1.9", installs: 66}, - "{11483926-db67-4190-91b1-ef20fcec5f33}": {minVersion: "0.4.9.1", installs: 65}, - "{8AA36F4F-6DC7-4c06-77AF-5035170634FE}": {minVersion: "2016.9.16", installs: 65}, - "dam@tensons.com": {minVersion: "5.0.7", installs: 65}, - "jid1-D7momAzRw417Ag@jetpack": {minVersion: "4.5.13", installs: 65}, - "support@videoadd.ru": {minVersion: "2.8.1.1-signed.1-signed", installs: 65}, - "{95322c08-05ff-4f3c-85fd-8ceb821988dd}": {minVersion: "49", installs: 64}, - "AllMyTube@Wondershare.com": {minVersion: "4.9.1", installs: 64}, - "azan-times@hamid.net": {minVersion: "1.2.3.1-signed.1-signed", installs: 64}, - "check-compatibility@dactyl.googlecode.com": {minVersion: "1.3.1-signed.1-signed", installs: 64}, - "ifamebook@stormvision.it": {minVersion: "4.03.1-signed", installs: 64}, - "jid1-vRJA7N8VwBoiXw@jetpack": {minVersion: "1.1.1.1-signed", installs: 64}, - "{04426594-bce6-4705-b811-bcdba2fd9c7b}": {minVersion: "1.7.1-signed.1-signed", installs: 63}, - "{f3f219f9-cbce-467e-b8fe-6e076d29665c}": {minVersion: "50", installs: 63}, - "fireforce@scrt.ch": {minVersion: "2.2.1-signed.1-signed", installs: 63}, - "FunkyMediaTab-the-extension1@mozilla.com": {minVersion: "0.1.9", installs: 63}, - "TopTabTV-the-extension1@mozilla.com": {minVersion: "0.1.9", installs: 63}, - "{018f3160-1a6f-4650-84fd-aad8c13609c8}": {minVersion: "0.1.1-signed.1-signed", installs: 62}, - "{2e710e6b-5e9d-44ba-8f4e-09a040978b49}": {minVersion: "1.7", installs: 62}, - "{c1970c0d-dbe6-4d91-804f-c9c0de643a57}": {minVersion: "1.3.2.13.1-signed.1-signed", installs: 62}, - "{c9b4529a-eeba-4e48-976e-f3d3f9026e04}": {minVersion: "1.1.1-signed.1-signed", installs: 62}, - "{df4e4df5-5cb7-46b0-9aef-6c784c3249f8}": {minVersion: "1.3.0.1-signed.1-signed", installs: 62}, - "@stremio": {minVersion: "1.0.2", installs: 62}, - "application@les-pages.com": {minVersion: "4.4.0", installs: 62}, - "ffvkontaktemusic@chupakabr.ru": {minVersion: "2.2.1-signed.1-signed", installs: 62}, - "firefinder@robertnyman.com": {minVersion: "1.4.1-signed.1-signed", installs: 62}, - "formhistory@yahoo.com": {minVersion: "1.4.0.6", installs: 62}, - "fxclickonce@rushyo.com": {minVersion: "0.1.1-signed.1-signed", installs: 62}, - "gmail@borsosfisoft.com": {minVersion: "1.0.1.1-signed.1-signed", installs: 62}, - "HighlightedTextToFile@bobbyrne01.org": {minVersion: "2.7.1", installs: 62}, - "jid1-n85lxPv1NAWVTQ@jetpack": {minVersion: "0.96.1.1-signed", installs: 62}, - "ramback@pavlov.net": {minVersion: "1.0.1-signed.1-signed", installs: 62}, - "VacuumPlacesImproved@lultimouomo-gmail.com": {minVersion: "1.2.1-signed.1-signed", installs: 62}, - "@News": {minVersion: "0.2.0", installs: 61}, - "{45d8ff86-d909-11db-9705-005056c00008}": {minVersion: "1.3.4.8", installs: 61}, - "{686fc9c5-c339-43db-b93a-5181a217f9a6}": {minVersion: "1.11", installs: 61}, - "{ea2b95c2-9be8-48ed-bdd1-5fcd2ad0ff99}": {minVersion: "0.3.8.1.1-signed.1-signed", installs: 61}, - "@chomikuj": {minVersion: "1.2.0", installs: 61}, - "avg@wtu3": {minVersion: "3.7.0.0", installs: 61}, - "jid1-f7dnBeTj8ElpWQ@jetpack": {minVersion: "1.34.1-signed.1-signed", installs: 61}, - "jid1-OY8Xu5BsKZQa6A@jetpack": {minVersion: "2.0.21", installs: 61}, - "jid1-u9RbFp9JcoEGGw@jetpack": {minVersion: "1.2.2.1-signed.1-signed", installs: 61}, - "plugin@okta.com": {minVersion: "5.8.0", installs: 61}, - "showpassword@pratikpoddar": {minVersion: "1.7.1-signed.1-signed", installs: 61}, - "IGF.F3@igufei.com": {minVersion: "3.2.11", installs: 60}, - "{12b6fdcd-4423-4276-82a3-73fdbff5f7e4}": {minVersion: "50", installs: 60}, - "{8F6A6FD9-0619-459f-B9D0-81DE065D4E21}": {minVersion: "1.13", installs: 60}, - "jid1-mW7iuA66Ny8Ziw@jetpack": {minVersion: "0.9.1-signed.1-signed", installs: 60}, - "nishan.naseer.googimagesearch@gmail.com": {minVersion: "0.5.1-signed.1-signed", installs: 60}, - "quicksearch@yandex.ru": {minVersion: "1.0.13", installs: 60}, - "{902D2C4A-457A-4EF9-AD43-7014562929FF}": {minVersion: "0.6.4", installs: 59}, - "@yset": {minVersion: "0.0.10", installs: 59}, - "csscoverage@spaghetticoder.org": {minVersion: "0.3.4.1-signed.1-signed", installs: 59}, - "dgnria2@nuance.com": {minVersion: "15.00.000.058", installs: 59}, - "firequery@binaryage.com": {minVersion: "2.0.4", installs: 59}, - "IBM-cck@firefox-extensions.ibm.com": {minVersion: "2.3.0", installs: 59}, - "trackmenot@mrl.nyu.edu": {minVersion: "0.9.2", installs: 59}, - "_chMembers_@free.discoverancestry.com": {minVersion: "7.102.10.3818", installs: 58}, - "{338e0b96-2285-4424-b4c8-e25560750fa3}": {minVersion: "3.1-signed.1-signed", installs: 58}, - "{8b5bea8c-6194-4c7c-a440-d5ca181480c3}": {minVersion: "1.500.000.11", installs: 58}, - "{e30e9060-21d5-11e3-8224-0800200c9a66}": {minVersion: "1.2.12", installs: 58}, - "LDshowpicture_plashcor@gmail.com": {minVersion: "3.2", installs: 58}, - "open.about.permissions@jasnapaka.com": {minVersion: "1.2.1-signed.1-signed", installs: 58}, - "sqlime@security.compass": {minVersion: "0.4.7.1-signed.1-signed", installs: 58}, - "@jetpack-easy-turism2": {minVersion: "7.1.0", installs: 57}, - "check4change-owner@mozdev.org": {minVersion: "1.9.8.1", installs: 57}, - "jid1-SDFC9fEAZRW7ab@jetpack": {minVersion: "0.1.3.1-signed.1-signed", installs: 57}, - "linkgopher@oooninja.com": {minVersion: "1.3.3.1-signed.1-signed", installs: 57}, - "pixelperfectplugin@openhouseconcepts.com": {minVersion: "2.0.14", installs: 57}, - "YoutubeDownloader@huangho.net76.net": {minVersion: "1.6.5.1-signed.1-signed", installs: 57}, - "lwthemes-manager@loucypher": {minVersion: "0.2.1-signed.1-let-fixed.1-signed", installs: 56}, - "_eiMembers_@www.100sofrecipes.com": {minVersion: "7.102.10.3580", installs: 56}, - "{068c594c-1a69-4f51-888d-1e231eac59a3}": {minVersion: "1", installs: 56}, - "{139C4B80-60ED-11E4-80EC-84041E5D46B0}": {minVersion: "1.3", installs: 56}, - "{4c7097f7-08f2-4ef2-9b9f-f95fa4cbb064}": {minVersion: "1.1", installs: 56}, - "{776f38cb-6255-4b92-b5cf-e5c71ff2b688}": {minVersion: "1.6", installs: 56}, - "{79c50f9a-2ffe-4ee0-8a37-fae4f5dacd4f}": {minVersion: "5.1.3", installs: 56}, - "{8BCA0E8A-E57B-425b-A05B-CD3868EB577E}": {minVersion: "1.4.1-signed.1-signed", installs: 56}, - "easycopypaste@everhelper.me": {minVersion: "1.1.0.1-signed.1-signed", installs: 56}, - "NoiaFoxoption@davidvincent.tld": {minVersion: "3.0.2.1-signed", installs: 56}, - "r2d2b2g@mozilla.org": {minVersion: "4.0.4.1-signed", installs: 56}, - "TFToolbarX@torrent-finder": {minVersion: "1.3.1.1-signed.1-signed", installs: 56}, - "{E4091D66-127C-11DB-903A-DE80D2EFDFE8}": {minVersion: "1.6.5.5.1-signed.1-signed", installs: 55}, - "downintab@max.max": {minVersion: "1.00.1-signed.1-signed", installs: 55}, - "flv2mp3@hotger.com": {minVersion: "2.3.2-signed", installs: 55}, - "ISVCU@iSkysoft.com": {minVersion: "5.1.0", installs: 55}, - "jid1-n5ARdBzHkUEdAA@jetpack": {minVersion: "3.8.7", installs: 55}, - "rpnetdownloadhelper@gmail.com": {minVersion: "3.0.1-signed.1-signed", installs: 55}, - "shpassword@shpassword.fr": {minVersion: "0.3.1-signed.1-signed", installs: 55}, - "snt@simplenewtab.com": {minVersion: "1.3", installs: 55}, - "admin@djamol.com": {minVersion: "4.31.1-signed.1-signed", installs: 54}, - "{22870005-adef-4c9d-ae36-d0e1f2f27e5a}": {minVersion: "0.4.0.9.1.1-signed.1-signed", installs: 54}, - "{DBBB3167-6E81-400f-BBFD-BD8921726F52}": {minVersion: "7125.2016.0115.2213", installs: 54}, - "{e4f94d1e-2f53-401e-8885-681602c0ddd8}": {minVersion: "1.0.1-signed.1-signed", installs: 54}, - "{FBF6D7FB-F305-4445-BB3D-FEF66579A033}": {minVersion: "6", installs: 54}, - "5aa55fd5-6e61-4896-b186-fdc6f298ec92@mozilla": {minVersion: "0.1.2.1-signed", installs: 54}, - "fireml@sirma.bg": {minVersion: "1.1.11.1-signed.1-signed", installs: 54}, - "info@priceblink.com": {minVersion: "4.8", installs: 54}, - "jid0-f82gosWvE8oeGQt6WDCGRF1Dy7Q@jetpack": {minVersion: "1.0.003", installs: 54}, - "jid0-hyjN250ZzTOOX3evFwwAQBxE4ik@jetpack": {minVersion: "6.0.1-signed.1-signed", installs: 54}, - "restart@restart.org": {minVersion: "0.5.1-signed.1-signed", installs: 54}, - "webmaster@keep-tube.com": {minVersion: "1.2.1-signed.1-signed", installs: 54}, - "eliteproxyswitcher@my-proxy.com": {minVersion: "1.2.0.2.1-signed.1-signed", installs: 53}, - "foxfilter@inspiredeffect.net": {minVersion: "7.7.1-signed.1-signed", installs: 53}, - "searchprivacy@searchprivacy.co": {minVersion: "1.15", installs: 53}, - "SignPlugin@pekao.pl": {minVersion: "1.4.0.73", installs: 53}, - "{15fe27f3-e5ab-2d59-4c5c-dadc7945bdbd}": {minVersion: "2.1.1.1-signed.1-signed", installs: 52}, - "ipfuck@p4ul.info": {minVersion: "1.2.1.1-signed.1-signed", installs: 52}, - "jyboy.yy@gmail.com": {minVersion: "1.0.4.1-signed.1-signed", installs: 52}, - "MySafeTabs-the-extension1@mozilla.com": {minVersion: "0.1.9", installs: 52}, - "saiful.neo@gmail.com": {minVersion: "3.0.1-signed.1-signed", installs: 52}, - "sendtokindle@amazon.com": {minVersion: "1.0.2.76", installs: 52}, - "smile1Button@amazon.com": {minVersion: "1.0.1-signed.1-signed", installs: 52}, - "whodeletedme@deleted.io": {minVersion: "0.3.3", installs: 52}, - "{C0CB8BA3-6C1B-47e8-A6AB-1FAB889562D9}": {minVersion: "0.7.6", installs: 51}, - "@irctctatkal": {minVersion: "2.0.0", installs: 51}, - "antgroup@antdownloadmanager.com": {minVersion: "0.1.7", installs: 51}, - "downloadplan@firefoxmania.uci.cu": {minVersion: "1.3.1-signed.1-signed", installs: 51}, - "jid1-AoXeeOB4j7kFdA@jetpack": {minVersion: "8.1", installs: 51}, - "memoryrestart@teamextension.com": {minVersion: "1.18.1-signed.1-signed", installs: 51}, - "multifox-toolbar-button@rbaldwin": {minVersion: "4.28.1-signed.1-signed", installs: 51}, - "soaclient@santoso": {minVersion: "0.2.1-signed.1-signed", installs: 51}, - "speeddns@gmail.com": {minVersion: "0.2.1-signed.1-signed", installs: 51}, - "windowandtablimiter@weintraut.net": {minVersion: "4.28.1-signed.1-signed", installs: 51}, - "@Recipes": {minVersion: "0.2.0", installs: 50}, - "{e6a9a96e-4a08-4719-b9bd-0e91c35aaabc}": {minVersion: "1.3.1.1-signed.1-signed", installs: 50}, - "autopager@mozilla.org": {minVersion: "0.8.0.10.1-signed.1-signed", installs: 50}, - "btpersonas@brandthunder.com": {minVersion: "2.0.4.7", installs: 50}, - "gdrivepanel@alejandrobrizuela.com.ar": {minVersion: "1.0.2.1-signed.1-signed", installs: 50}, - "jid1-m3kqTBs1zKXXaA@jetpack": {minVersion: "0.2.6.1-signed.1-signed", installs: 50}, - "qqmail_plugin_for_firefox@tencent.com": {minVersion: "1.0.0.22", installs: 50}, - "savefileto@mozdev.org": {minVersion: "2.5.5", installs: 50}, - "seodoctor@prelovac.com": {minVersion: "1.6.5.1-signed.1-signed", installs: 50}, - "support@todoist.com": {minVersion: "4.0.5", installs: 50}, - "toolbar_TeoMediaTB@apn.ask.com": {minVersion: "135.3", installs: 50}, - "txftn@tencent.com": {minVersion: "1.0.0.7", installs: 50}, -}; - -// ================== END OF LIST FOR 51 ====================== - -// We use these named policies to correlate the telemetry -// data with them, in order to understand how each set -// is behaving in the wild. -const RolloutPolicy = { - // Used during 48 Beta cycle - "2a": { addons: set2, webextensions: true }, - "2b": { addons: set2, webextensions: false }, - - // Set agreed for Release 49 - "49a": { addons: set49Release, webextensions: true }, - "49b": { addons: set49Release, webextensions: false }, - - // Smaller set that can be used for Release 49 - "49limiteda": { addons: set49PaneOnly, webextensions: true }, - "49limitedb": { addons: set49PaneOnly, webextensions: false }, - - // Beta testing on 50 - "50allmpc": { addons: [], webextensions: true, mpc: true }, - - // Beta testing on 51 - "51alladdons": { addons: [], webextensions: true, alladdons: true }, - - // 51 release - "51set1": { addonsv2: set51Release, installs: 50, webextensions: true, mpc: true }, - "51set2": { addonsv2: set51Release, installs: 100, webextensions: true, mpc: true }, - "51set3": { addonsv2: set51Release, installs: 300, webextensions: true, mpc: true }, - "51set4": { addonsv2: set51Release, installs: 1000, webextensions: true, mpc: true }, - - // ESR - "esrA": { addons: [], mpc: true, webextensions: true }, - "esrB": { addons: [], mpc: true, webextensions: false }, - "esrC": { addons: [], mpc: false, webextensions: true }, - - "xpcshell-test": { addons: [ADDONS.test1, ADDONS.test2], webextensions: false }, -}; - -Object.defineProperty(this, "isAddonPartOfE10SRollout", { - configurable: false, - enumerable: false, - writable: false, - value: function isAddonPartOfE10SRollout(aAddon) { - let blocklist = Preferences.get(PREF_E10S_ADDON_BLOCKLIST, ""); - let policyId = Preferences.get(PREF_E10S_ADDON_POLICY, ""); - - if (!policyId || !RolloutPolicy.hasOwnProperty(policyId)) { - return false; - } - - if (blocklist && blocklist.indexOf(aAddon.id) > -1) { - return false; - } - - let policy = RolloutPolicy[policyId]; - - if (aAddon.mpcOptedOut == true) { - return false; - } - - if (policy.alladdons) { - return true; - } - - if (policy.webextensions && aAddon.type == "webextension") { - return true; - } - - if (policy.mpc && aAddon.multiprocessCompatible) { - return true; - } - - if (policy.addonsv2) { - if (aAddon.id in policy.addonsv2) { - let rolloutAddon = policy.addonsv2[aAddon.id]; - - if (rolloutAddon.installs >= policy.installs && - Services.vc.compare(aAddon.version, rolloutAddon.minVersion) >= 0) { - return true; - } - } - return false; - } - - for (let rolloutAddon of policy.addons) { - if (aAddon.id == rolloutAddon.id && - Services.vc.compare(aAddon.version, rolloutAddon.minVersion) >= 0) { - return true; - } - } - - return false; - }, -}); diff --git a/toolkit/mozapps/extensions/internal/GMPProvider.jsm b/toolkit/mozapps/extensions/internal/GMPProvider.jsm index 9bb34a7af..52affa9ba 100644 --- a/toolkit/mozapps/extensions/internal/GMPProvider.jsm +++ b/toolkit/mozapps/extensions/internal/GMPProvider.jsm @@ -12,17 +12,12 @@ this.EXPORTED_SYMBOLS = []; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/AddonManager.jsm"); -/* globals AddonManagerPrivate*/ Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/Preferences.jsm"); Cu.import("resource://gre/modules/osfile.jsm"); -/* globals OS*/ Cu.import("resource://gre/modules/Log.jsm"); Cu.import("resource://gre/modules/Task.jsm"); Cu.import("resource://gre/modules/GMPUtils.jsm"); -/* globals EME_ADOBE_ID, GMP_PLUGIN_IDS, GMPPrefs, GMPUtils, OPEN_H264_ID, WIDEVINE_ID */ -Cu.import("resource://gre/modules/AppConstants.jsm"); -Cu.import("resource://gre/modules/UpdateUtils.jsm"); XPCOMUtils.defineLazyModuleGetter( this, "GMPInstallManager", "resource://gre/modules/GMPInstallManager.jsm"); @@ -41,8 +36,6 @@ const CLEARKEY_PLUGIN_ID = "gmp-clearkey"; const CLEARKEY_VERSION = "0.1"; const GMP_LICENSE_INFO = "gmp_license_info"; -const GMP_PRIVACY_INFO = "gmp_privacy_info"; -const GMP_LEARN_MORE = "learn_more_label"; const GMP_PLUGINS = [ { @@ -54,33 +47,17 @@ const GMP_PLUGINS = [ // localisation. licenseURL: "chrome://mozapps/content/extensions/OpenH264-license.txt", homepageURL: "http://www.openh264.org/", - optionsURL: "chrome://mozapps/content/extensions/gmpPrefs.xul", + optionsURL: "chrome://mozapps/content/extensions/gmpPrefs.xul" }, { id: EME_ADOBE_ID, name: "eme-adobe_name", description: "eme-adobe_description", - // The following learnMoreURL is another hack to be able to support a SUMO page for this - // feature. - get learnMoreURL() { - return Services.urlFormatter.formatURLPref("app.support.baseURL") + "drm-content"; - }, licenseURL: "http://help.adobe.com/en_US/primetime/drm/HTML5_CDM_EULA/index.html", homepageURL: "http://help.adobe.com/en_US/primetime/drm/HTML5_CDM", optionsURL: "chrome://mozapps/content/extensions/gmpPrefs.xul", - isEME: true, - }, - { - id: WIDEVINE_ID, - name: "widevine_description", - // Describe the purpose of both CDMs in the same way. - description: "eme-adobe_description", - licenseURL: "https://www.google.com/policies/privacy/", - homepageURL: "https://www.widevine.com/", - optionsURL: "chrome://mozapps/content/extensions/gmpPrefs.xul", isEME: true }]; -XPCOMUtils.defineConstant(this, "GMP_PLUGINS", GMP_PLUGINS); XPCOMUtils.defineLazyGetter(this, "pluginsBundle", () => Services.strings.createBundle("chrome://global/locale/plugins.properties")); @@ -170,17 +147,13 @@ GMPWrapper.prototype = { get version() { return GMPPrefs.get(GMPPrefs.KEY_PLUGIN_VERSION, null, this._plugin.id); }, - get isActive() { - return !this.appDisabled && - !this.userDisabled && - !GMPUtils.isPluginHidden(this._plugin); - }, + get isActive() { return !this.appDisabled && !this.userDisabled; }, get appDisabled() { if (this._plugin.isEME && !GMPPrefs.get(GMPPrefs.KEY_EME_ENABLED, true)) { // If "media.eme.enabled" is false, all EME plugins are disabled. return true; } - return false; + return false; }, get userDisabled() { @@ -210,7 +183,7 @@ GMPWrapper.prototype = { get updateDate() { let time = Number(GMPPrefs.get(GMPPrefs.KEY_PLUGIN_LAST_UPDATE, null, this._plugin.id)); - if (!isNaN(time) && this.isInstalled) { + if (time !== NaN && this.isInstalled) { return new Date(time * 1000) } return null; @@ -287,12 +260,14 @@ GMPWrapper.prototype = { return this._updateTask; } - this._updateTask = Task.spawn(function*() { + this._updateTask = Task.spawn(function* GMPProvider_updateTask() { this._log.trace("findUpdates() - updateTask"); try { let installManager = new GMPInstallManager(); - let res = yield installManager.checkForAddons(); - let update = res.gmpAddons.find(addon => addon.id === this._plugin.id); + let gmpAddons = yield installManager.checkForAddons(); + let update = gmpAddons.find(function(aAddon) { + return aAddon.id === this._plugin.id; + }, this); if (update && update.isValid && !update.isInstalled) { this._log.trace("findUpdates() - found update for " + this._plugin.id + ", installing"); @@ -338,9 +313,6 @@ GMPWrapper.prototype = { }, _handleEnabledChanged: function() { - this._log.info("_handleEnabledChanged() id=" + - this._plugin.id + " isActive=" + this.isActive); - AddonManagerPrivate.callAddonListeners(this.isActive ? "onEnabling" : "onDisabling", this, false); @@ -361,17 +333,11 @@ GMPWrapper.prototype = { }, onPrefEMEGlobalEnabledChanged: function() { - this._log.info("onPrefEMEGlobalEnabledChanged() id=" + this._plugin.id + - " appDisabled=" + this.appDisabled + " isActive=" + this.isActive + - " hidden=" + GMPUtils.isPluginHidden(this._plugin)); - AddonManagerPrivate.callAddonListeners("onPropertyChanged", this, ["appDisabled"]); - // If EME or the GMP itself are disabled, uninstall the GMP. - // Otherwise, check for updates, so we download and install the GMP. if (this.appDisabled) { this.uninstallPlugin(); - } else if (!GMPUtils.isPluginHidden(this._plugin)) { + } else { AddonManagerPrivate.callInstallListeners("onExternalInstall", null, this, null, false); AddonManagerPrivate.callAddonListeners("onInstalling", this, false); @@ -407,12 +373,12 @@ GMPWrapper.prototype = { let parsedData; try { parsedData = JSON.parse(data); - } catch (ex) { + } catch(ex) { this._log.error("Malformed EME video message with data: " + data); return; } let {status: status, keySystem: keySystem} = parsedData; - if (status == "cdm-not-installed") { + if (status == "cdm-not-installed" || status == "cdm-insufficient-version") { this.checkForUpdates(0); } }, @@ -458,8 +424,6 @@ GMPWrapper.prototype = { gmpService.removeAndDeletePluginDirectory(this.gmpPath); } GMPPrefs.reset(GMPPrefs.KEY_PLUGIN_VERSION, this.id); - GMPPrefs.reset(GMPPrefs.KEY_PLUGIN_ABI, this.id); - GMPPrefs.reset(GMPPrefs.KEY_PLUGIN_LAST_UPDATE, this.id); AddonManagerPrivate.callAddonListeners("onUninstalled", this); }, @@ -477,56 +441,6 @@ GMPWrapper.prototype = { } return this._updateTask; }, - - _arePluginFilesOnDisk: function() { - let fileExists = function(aGmpPath, aFileName) { - let f = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); - let path = OS.Path.join(aGmpPath, aFileName); - f.initWithPath(path); - return f.exists(); - }; - - let id = this._plugin.id.substring(4); - let libName = AppConstants.DLL_PREFIX + id + AppConstants.DLL_SUFFIX; - let infoName; - if (this._plugin.id == WIDEVINE_ID) { - infoName = "manifest.json"; - } else { - infoName = id + ".info"; - } - - return fileExists(this.gmpPath, libName) && - fileExists(this.gmpPath, infoName) && - (this._plugin.id != EME_ADOBE_ID || fileExists(this.gmpPath, id + ".voucher")); - }, - - validate: function() { - if (!this.isInstalled) { - // Not installed -> Valid. - return { - installed: false, - valid: true - }; - } - - let abi = GMPPrefs.get(GMPPrefs.KEY_PLUGIN_ABI, UpdateUtils.ABI, this._plugin.id); - if (abi != UpdateUtils.ABI) { - // ABI doesn't match. Possibly this is a profile migrated across platforms - // or from 32 -> 64 bit. - return { - installed: true, - mismatchedABI: true, - valid: false - }; - } - - // Installed -> Check if files are missing. - let filesOnDisk = this._arePluginFilesOnDisk(); - return { - installed: true, - valid: filesOnDisk - }; - }, }; var GMPProvider = { @@ -538,6 +452,7 @@ var GMPProvider = { configureLogging(); this._log = Log.repository.getLoggerWithMessagePrefix("Toolkit.GMP", "GMPProvider."); + let telemetry = {}; this.buildPluginList(); this.ensureProperCDMInstallState(); @@ -551,50 +466,47 @@ var GMPProvider = { gmpPath); if (gmpPath && isEnabled) { - let validation = wrapper.validate(); - if (validation.mismatchedABI) { - this._log.info("startup - gmp " + plugin.id + - " mismatched ABI, uninstalling"); - wrapper.uninstallPlugin(); - continue; - } - if (!validation.valid) { - this._log.info("startup - gmp " + plugin.id + - " invalid, uninstalling"); - wrapper.uninstallPlugin(); - continue; - } this._log.info("startup - adding gmp directory " + gmpPath); try { gmpService.addPluginDirectory(gmpPath); - } catch (e) { - if (e.name != 'NS_ERROR_NOT_AVAILABLE') - throw e; + } catch (e if e.name == 'NS_ERROR_NOT_AVAILABLE') { this._log.warn("startup - adding gmp directory failed with " + e.name + " - sandboxing not available?", e); } } + + if (this.isEnabled) { + telemetry[id] = { + userDisabled: wrapper.userDisabled, + version: wrapper.version, + applyBackgroundUpdates: wrapper.applyBackgroundUpdates, + }; + } } - try { - let greDir = Services.dirsvc.get(NS_GRE_DIR, - Ci.nsILocalFile); - let clearkeyPath = OS.Path.join(greDir.path, - CLEARKEY_PLUGIN_ID, - CLEARKEY_VERSION); - this._log.info("startup - adding clearkey CDM directory " + - clearkeyPath); - gmpService.addPluginDirectory(clearkeyPath); - } catch (e) { - this._log.warn("startup - adding clearkey CDM failed", e); + if (Preferences.get(GMPPrefs.KEY_EME_ENABLED, false)) { + try { + let greDir = Services.dirsvc.get(NS_GRE_DIR, + Ci.nsILocalFile); + let clearkeyPath = OS.Path.join(greDir.path, + CLEARKEY_PLUGIN_ID, + CLEARKEY_VERSION); + this._log.info("startup - adding clearkey CDM directory " + + clearkeyPath); + gmpService.addPluginDirectory(clearkeyPath); + } catch (e) { + this._log.warn("startup - adding clearkey CDM failed", e); + } } + + AddonManagerPrivate.setTelemetryDetails("GMP", telemetry); }, shutdown: function() { this._log.trace("shutdown"); Preferences.ignore(GMPPrefs.KEY_LOG_BASE, configureLogging); - let shutdownTask = Task.spawn(function*() { + let shutdownTask = Task.spawn(function* GMPProvider_shutdownTask() { this._log.trace("shutdown - shutdownTask"); let shutdownSucceeded = true; @@ -637,10 +549,16 @@ var GMPProvider = { return; } - let results = Array.from(this._plugins.values()) - .filter(p => !GMPUtils.isPluginHidden(p)) - .map(p => p.wrapper); - + // Tycho: + // let results = [p.wrapper for ([id, p] of this._plugins) + // if (!GMPUtils.isPluginHidden(p))]; + let results = []; + for (let [id, p] of this._plugins) { + if (!GMPUtils.isPluginHidden(p)) { + results.push(p.wrapper); + } + } + aCallback(results); }, @@ -648,20 +566,14 @@ var GMPProvider = { return GMPPrefs.get(GMPPrefs.KEY_PROVIDER_ENABLED, false); }, - generateFullDescription: function(aPlugin) { - let rv = []; - for (let [urlProp, labelId] of [["learnMoreURL", GMP_LEARN_MORE], - ["licenseURL", aPlugin.id == WIDEVINE_ID ? - GMP_PRIVACY_INFO : GMP_LICENSE_INFO]]) { - if (aPlugin[urlProp]) { - let label = pluginsBundle.GetStringFromName(labelId); - rv.push(`<xhtml:a href="${aPlugin[urlProp]}" target="_blank">${label}</xhtml:a>.`); - } - } - return rv.length ? rv.join("<xhtml:br /><xhtml:br />") : undefined; + generateFullDescription: function(aLicenseURL, aLicenseInfo) { + return "<xhtml:a href=\"" + aLicenseURL + "\" target=\"_blank\">" + + aLicenseInfo + "</xhtml:a>." }, buildPluginList: function() { + let licenseInfo = pluginsBundle.GetStringFromName(GMP_LICENSE_INFO); + this._plugins = new Map(); for (let aPlugin of GMP_PLUGINS) { let plugin = { @@ -673,7 +585,10 @@ var GMPProvider = { wrapper: null, isEME: aPlugin.isEME, }; - plugin.fullDescription = this.generateFullDescription(aPlugin); + if (aPlugin.licenseURL) { + plugin.fullDescription = + this.generateFullDescription(aPlugin.licenseURL, licenseInfo); + } plugin.wrapper = new GMPWrapper(plugin); this._plugins.set(plugin.id, plugin); } diff --git a/toolkit/mozapps/extensions/internal/LightweightThemeImageOptimizer.jsm b/toolkit/mozapps/extensions/internal/LightweightThemeImageOptimizer.jsm index 49dfa237f..1e7d6b0d8 100644 --- a/toolkit/mozapps/extensions/internal/LightweightThemeImageOptimizer.jsm +++ b/toolkit/mozapps/extensions/internal/LightweightThemeImageOptimizer.jsm @@ -21,8 +21,8 @@ const ORIGIN_TOP_RIGHT = 1; const ORIGIN_BOTTOM_LEFT = 2; this.LightweightThemeImageOptimizer = { - optimize: function(aThemeData, aScreen) { - let data = Object.assign({}, aThemeData); + optimize: function LWTIO_optimize(aThemeData, aScreen) { + let data = Utils.createCopy(aThemeData); if (!data.headerURL) { return data; } @@ -38,7 +38,7 @@ this.LightweightThemeImageOptimizer = { return data; }, - purge: function() { + purge: function LWTIO_purge() { let dir = FileUtils.getDir("ProfD", ["lwtheme"]); dir.followLinks = false; try { @@ -52,12 +52,18 @@ Object.freeze(LightweightThemeImageOptimizer); var ImageCropper = { _inProgress: {}, - getCroppedImageURL: function(aImageURL, aScreen, aOrigin) { + getCroppedImageURL: + function ImageCropper_getCroppedImageURL(aImageURL, aScreen, aOrigin) { // We can crop local files, only. if (!aImageURL.startsWith("file://")) { return aImageURL; } + if (Services.prefs.getBoolPref("lightweightThemes.animation.enabled")) { + //Don't crop if animated + return aImageURL; + } + // Generate the cropped image's file name using its // base name and the current screen size. let uri = Services.io.newURI(aImageURL, null, null); @@ -88,7 +94,7 @@ var ImageCropper = { return aImageURL; }, - _crop: function(aURI, aTargetFile, aScreen, aOrigin) { + _crop: function ImageCropper_crop(aURI, aTargetFile, aScreen, aOrigin) { let inProgress = this._inProgress; inProgress[aTargetFile.path] = true; @@ -96,7 +102,7 @@ var ImageCropper = { delete inProgress[aTargetFile.path]; } - ImageFile.read(aURI, function(aInputStream, aContentType) { + ImageFile.read(aURI, function crop_readImageFile(aInputStream, aContentType) { if (aInputStream && aContentType) { let image = ImageTools.decode(aInputStream, aContentType); if (image && image.width && image.height) { @@ -114,24 +120,27 @@ var ImageCropper = { }; var ImageFile = { - read: function(aURI, aCallback) { - this._netUtil.asyncFetch({ - uri: aURI, - loadUsingSystemPrincipal: true, - contentPolicyType: Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE - }, function(aInputStream, aStatus, aRequest) { + read: function ImageFile_read(aURI, aCallback) { + this._netUtil.asyncFetch2( + aURI, + function read_asyncFetch(aInputStream, aStatus, aRequest) { if (Components.isSuccessCode(aStatus) && aRequest instanceof Ci.nsIChannel) { let channel = aRequest.QueryInterface(Ci.nsIChannel); aCallback(aInputStream, channel.contentType); } else { aCallback(); } - }); + }, + null, // aLoadingNode + Services.scriptSecurityManager.getSystemPrincipal(), + null, // aTriggeringPrincipal + Ci.nsILoadInfo.SEC_NORMAL, + Ci.nsIContentPolicy.TYPE_IMAGE); }, - write: function(aFile, aInputStream, aCallback) { + write: function ImageFile_write(aFile, aInputStream, aCallback) { let fos = FileUtils.openSafeFileOutputStream(aFile); - this._netUtil.asyncCopy(aInputStream, fos, function(aResult) { + this._netUtil.asyncCopy(aInputStream, fos, function write_asyncCopy(aResult) { FileUtils.closeSafeFileOutputStream(fos); // Remove the file if writing was not successful. @@ -150,7 +159,7 @@ XPCOMUtils.defineLazyModuleGetter(ImageFile, "_netUtil", "resource://gre/modules/NetUtil.jsm", "NetUtil"); var ImageTools = { - decode: function(aInputStream, aContentType) { + decode: function ImageTools_decode(aInputStream, aContentType) { let outParam = {value: null}; try { @@ -160,7 +169,7 @@ var ImageTools = { return outParam.value; }, - encode: function(aImage, aScreen, aOrigin, aContentType) { + encode: function ImageTools_encode(aImage, aScreen, aOrigin, aContentType) { let stream; let width = Math.min(aImage.width, aScreen.width); let height = Math.min(aImage.height, aScreen.height); @@ -178,3 +187,12 @@ var ImageTools = { XPCOMUtils.defineLazyServiceGetter(ImageTools, "_imgTools", "@mozilla.org/image/tools;1", "imgITools"); +var Utils = { + createCopy: function Utils_createCopy(aData) { + let copy = {}; + for (let [k, v] in Iterator(aData)) { + copy[k] = v; + } + return copy; + } +}; diff --git a/toolkit/mozapps/extensions/internal/PluginProvider.jsm b/toolkit/mozapps/extensions/internal/PluginProvider.jsm index 075159a9a..cb07dcb12 100644 --- a/toolkit/mozapps/extensions/internal/PluginProvider.jsm +++ b/toolkit/mozapps/extensions/internal/PluginProvider.jsm @@ -11,7 +11,6 @@ const Cu = Components.utils; this.EXPORTED_SYMBOLS = []; Cu.import("resource://gre/modules/AddonManager.jsm"); -/* globals AddonManagerPrivate*/ Cu.import("resource://gre/modules/Services.jsm"); const URI_EXTENSION_STRINGS = "chrome://mozapps/locale/extensions/extensions.properties"; @@ -28,7 +27,8 @@ var logger = Log.repository.getLogger(LOGGER_ID); function getIDHashForString(aStr) { // return the two-digit hexadecimal code for a byte - let toHexString = charCode => ("0" + charCode.toString(16)).slice(-2); + function toHexString(charCode) + ("0" + charCode.toString(16)).slice(-2); let hasher = Cc["@mozilla.org/security/hash;1"]. createInstance(Ci.nsICryptoHash); @@ -40,8 +40,16 @@ function getIDHashForString(aStr) { // convert the binary hash data to a hex string. let binary = hasher.finish(false); - let hash = Array.from(binary, c => toHexString(c.charCodeAt(0))); + + // Tycho: let hash = [toHexString(binary.charCodeAt(i)) for (i in binary)].join("").toLowerCase(); + let hash = []; + + for (let i in binary) { + hash.push(toHexString(binary.charCodeAt(i))); + } + hash = hash.join("").toLowerCase(); + return "{" + hash.substr(0, 8) + "-" + hash.substr(8, 4) + "-" + hash.substr(12, 4) + "-" + @@ -50,14 +58,12 @@ function getIDHashForString(aStr) { } var PluginProvider = { - get name() { - return "PluginProvider"; - }, + get name() "PluginProvider", // A dictionary mapping IDs to names and descriptions plugins: null, - startup: function() { + startup: function PL_startup() { Services.obs.addObserver(this, LIST_UPDATED_TOPIC, false); Services.obs.addObserver(this, AddonManager.OPTIONS_NOTIFICATION_DISPLAYED, false); }, @@ -66,7 +72,7 @@ var PluginProvider = { * Called when the application is shutting down. Only necessary for tests * to be able to simulate a shutdown. */ - shutdown: function() { + shutdown: function PL_shutdown() { this.plugins = null; Services.obs.removeObserver(this, AddonManager.OPTIONS_NOTIFICATION_DISPLAYED); Services.obs.removeObserver(this, LIST_UPDATED_TOPIC); @@ -75,7 +81,7 @@ var PluginProvider = { observe: function(aSubject, aTopic, aData) { switch (aTopic) { case AddonManager.OPTIONS_NOTIFICATION_DISPLAYED: - this.getAddonByID(aData, function(plugin) { + this.getAddonByID(aData, function PL_displayPluginInfo(plugin) { if (!plugin) return; @@ -85,7 +91,7 @@ var PluginProvider = { let typeLabel = aSubject.getElementById("pluginMimeTypes"), types = []; for (let type of plugin.pluginMimeTypes) { let extras = [type.description.trim(), type.suffixes]. - filter(x => x).join(": "); + filter(function(x) x).join(": "); types.push(type.type + (extras ? " (" + extras + ")" : "")); } typeLabel.textContent = types.join(",\n"); @@ -104,7 +110,7 @@ var PluginProvider = { /** * Creates a PluginWrapper for a plugin object. */ - buildWrapper: function(aPlugin) { + buildWrapper: function PL_buildWrapper(aPlugin) { return new PluginWrapper(aPlugin.id, aPlugin.name, aPlugin.description, @@ -119,7 +125,7 @@ var PluginProvider = { * @param aCallback * A callback to pass the Addon to */ - getAddonByID: function(aId, aCallback) { + getAddonByID: function PL_getAddon(aId, aCallback) { if (!this.plugins) this.buildPluginList(); @@ -137,7 +143,7 @@ var PluginProvider = { * @param callback * A callback to pass an array of Addons to */ - getAddonsByTypes: function(aTypes, aCallback) { + getAddonsByTypes: function PL_getAddonsByTypes(aTypes, aCallback) { if (aTypes && aTypes.indexOf("plugin") < 0) { aCallback([]); return; @@ -148,8 +154,11 @@ var PluginProvider = { let results = []; - for (let id in this.plugins) - this.getAddonByID(id, (addon) => results.push(addon)); + for (let id in this.plugins) { + this.getAddonByID(id, function(aAddon) { + results.push(aAddon); + }); + } aCallback(results); }, @@ -162,7 +171,7 @@ var PluginProvider = { * @param aCallback * A callback to pass an array of Addons to */ - getAddonsWithOperationsByTypes: function(aTypes, aCallback) { + getAddonsWithOperationsByTypes: function PL_getAddonsWithOperationsByTypes(aTypes, aCallback) { aCallback([]); }, @@ -174,7 +183,7 @@ var PluginProvider = { * @param aCallback * A callback to pass the array of AddonInstalls to */ - getInstallsByTypes: function(aTypes, aCallback) { + getInstallsByTypes: function PL_getInstallsByTypes(aTypes, aCallback) { aCallback([]); }, @@ -183,7 +192,7 @@ var PluginProvider = { * * @return a dictionary of plugins indexed by our generated ID */ - getPluginList: function() { + getPluginList: function PL_getPluginList() { let tags = Cc["@mozilla.org/plugin/host;1"]. getService(Ci.nsIPluginHost). getPluginTags({}); @@ -196,7 +205,8 @@ var PluginProvider = { if (!(tag.description in seenPlugins[tag.name])) { let plugin = { id: getIDHashForString(tag.name + tag.description), - name: tag.name, + // XXX Flash name substitution like in browser-plugins.js, aboutPermissions.js, permissions.js + name: tag.name == "Shockwave Flash" ? "Adobe Flash" : tag.name, description: tag.description, tags: [tag] }; @@ -215,7 +225,7 @@ var PluginProvider = { /** * Builds the list of known plugins from the plugin host */ - buildPluginList: function() { + buildPluginList: function PL_buildPluginList() { this.plugins = this.getPluginList(); }, @@ -224,14 +234,40 @@ var PluginProvider = { * to the last known list sending out any necessary API notifications for * changes. */ - updatePluginList: function() { + updatePluginList: function PL_updatePluginList() { let newList = this.getPluginList(); - let lostPlugins = Object.keys(this.plugins).filter(id => !(id in newList)). - map(id => this.buildWrapper(this.plugins[id])); - let newPlugins = Object.keys(newList).filter(id => !(id in this.plugins)). - map(id => this.buildWrapper(newList[id])); - let matchedIDs = Object.keys(newList).filter(id => id in this.plugins); + // Tycho: + // let lostPlugins = [this.buildWrapper(this.plugins[id]) + // for each (id in Object.keys(this.plugins)) if (!(id in newList))]; + + // let newPlugins = [this.buildWrapper(newList[id]) + // for each (id in Object.keys(newList)) if (!(id in this.plugins))]; + + // let matchedIDs = [id for each (id in Object.keys(newList)) if (id in this.plugins)]; + + let lostPlugins = []; + let newPlugins = []; + let matchedIDs = []; + + // lostPlugins + for each(let id in Object.keys(this.plugins)) { + if (!(id in newList)) { + lostPlugins.push(this.buildWrapper(this.plugins[id])); + } + } + + // newPlugins and matchedIDs + for each(let id in Object.keys(newList)) { + if (!(id in this.plugins)) { + newPlugins.push(this.buildWrapper(newList[id])); + } + + if (id in this.plugins) { + matchedIDs.push(id); + } + } + // The plugin host generates new tags for every plugin after a scan and // if the plugin's filename has changed then the disabled state won't have @@ -293,99 +329,63 @@ function canDisableFlashProtectedMode(aPlugin) { return isFlashPlugin(aPlugin) && Services.appinfo.XPCOMABI == "x86-msvc"; } -const wrapperMap = new WeakMap(); -let pluginFor = wrapper => wrapperMap.get(wrapper); - /** * The PluginWrapper wraps a set of nsIPluginTags to provide the data visible to * public callers through the API. */ -function PluginWrapper(id, name, description, tags) { - wrapperMap.set(this, { id, name, description, tags }); -} - -PluginWrapper.prototype = { - get id() { - return pluginFor(this).id; - }, - - get type() { - return "plugin"; - }, - - get name() { - return pluginFor(this).name; - }, - - get creator() { - return null; - }, - - get description() { - return pluginFor(this).description.replace(/<\/?[a-z][^>]*>/gi, " "); - }, - - get version() { - let { tags: [tag] } = pluginFor(this); - return tag.version; - }, - - get homepageURL() { - let { description } = pluginFor(this); - if (/<A\s+HREF=[^>]*>/i.test(description)) - return /<A\s+HREF=["']?([^>"'\s]*)/i.exec(description)[1]; - return null; - }, - - get isActive() { - let { tags: [tag] } = pluginFor(this); - return !tag.blocklisted && !tag.disabled; - }, - - get appDisabled() { - let { tags: [tag] } = pluginFor(this); - return tag.blocklisted; - }, - - get userDisabled() { - let { tags: [tag] } = pluginFor(this); - if (tag.disabled) +function PluginWrapper(aId, aName, aDescription, aTags) { + let safedesc = aDescription.replace(/<\/?[a-z][^>]*>/gi, " "); + let homepageURL = null; + if (/<A\s+HREF=[^>]*>/i.test(aDescription)) + homepageURL = /<A\s+HREF=["']?([^>"'\s]*)/i.exec(aDescription)[1]; + + this.__defineGetter__("id", function() aId); + this.__defineGetter__("type", function() "plugin"); + this.__defineGetter__("name", function() aName); + this.__defineGetter__("creator", function() null); + this.__defineGetter__("description", function() safedesc); + this.__defineGetter__("version", function() aTags[0].version); + this.__defineGetter__("homepageURL", function() homepageURL); + + this.__defineGetter__("isActive", function() !aTags[0].blocklisted && !aTags[0].disabled); + this.__defineGetter__("appDisabled", function() aTags[0].blocklisted); + + this.__defineGetter__("userDisabled", function() { + if (aTags[0].disabled) return true; - if ((Services.prefs.getBoolPref("plugins.click_to_play") && tag.clicktoplay) || + if ((Services.prefs.getBoolPref("plugins.click_to_play") && aTags[0].clicktoplay) || this.blocklistState == Ci.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE || this.blocklistState == Ci.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE) return AddonManager.STATE_ASK_TO_ACTIVATE; return false; - }, + }); - set userDisabled(val) { + this.__defineSetter__("userDisabled", function(aVal) { let previousVal = this.userDisabled; - if (val === previousVal) - return val; + if (aVal === previousVal) + return aVal; - let { tags } = pluginFor(this); - - for (let tag of tags) { - if (val === true) + for (let tag of aTags) { + if (aVal === true) tag.enabledState = Ci.nsIPluginTag.STATE_DISABLED; - else if (val === false) + else if (aVal === false) tag.enabledState = Ci.nsIPluginTag.STATE_ENABLED; - else if (val == AddonManager.STATE_ASK_TO_ACTIVATE) + else if (aVal == AddonManager.STATE_ASK_TO_ACTIVATE) tag.enabledState = Ci.nsIPluginTag.STATE_CLICKTOPLAY; } // If 'userDisabled' was 'true' and we're going to a state that's not // that, we're enabling, so call those listeners. - if (previousVal === true && val !== true) { + if (previousVal === true && aVal !== true) { AddonManagerPrivate.callAddonListeners("onEnabling", this, false); AddonManagerPrivate.callAddonListeners("onEnabled", this); } // If 'userDisabled' was not 'true' and we're going to a state where // it is, we're disabling, so call those listeners. - if (previousVal !== true && val === true) { + if (previousVal !== true && aVal === true) { AddonManagerPrivate.callAddonListeners("onDisabling", this, false); AddonManagerPrivate.callAddonListeners("onDisabled", this); } @@ -393,28 +393,27 @@ PluginWrapper.prototype = { // If the 'userDisabled' value involved AddonManager.STATE_ASK_TO_ACTIVATE, // call the onPropertyChanged listeners. if (previousVal == AddonManager.STATE_ASK_TO_ACTIVATE || - val == AddonManager.STATE_ASK_TO_ACTIVATE) { + aVal == AddonManager.STATE_ASK_TO_ACTIVATE) { AddonManagerPrivate.callAddonListeners("onPropertyChanged", this, ["userDisabled"]); } - return val; - }, + return aVal; + }); - get blocklistState() { - let { tags: [tag] } = pluginFor(this); + + this.__defineGetter__("blocklistState", function() { let bs = Cc["@mozilla.org/extensions/blocklist;1"]. getService(Ci.nsIBlocklistService); - return bs.getPluginBlocklistState(tag); - }, + return bs.getPluginBlocklistState(aTags[0]); + }); - get blocklistURL() { - let { tags: [tag] } = pluginFor(this); + this.__defineGetter__("blocklistURL", function() { let bs = Cc["@mozilla.org/extensions/blocklist;1"]. getService(Ci.nsIBlocklistService); - return bs.getPluginBlocklistURL(tag); - }, + return bs.getPluginBlocklistURL(aTags[0]); + }); - get size() { + this.__defineGetter__("size", function() { function getDirectorySize(aFile) { let size = 0; let entries = aFile.directoryEntries.QueryInterface(Ci.nsIDirectoryEnumerator); @@ -431,7 +430,7 @@ PluginWrapper.prototype = { let size = 0; let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); - for (let tag of pluginFor(this).tags) { + for (let tag of aTags) { file.initWithPath(tag.fullpath); if (file.isDirectory()) size += getDirectorySize(file); @@ -439,25 +438,25 @@ PluginWrapper.prototype = { size += file.fileSize; } return size; - }, + }); - get pluginLibraries() { + this.__defineGetter__("pluginLibraries", function() { let libs = []; - for (let tag of pluginFor(this).tags) + for (let tag of aTags) libs.push(tag.filename); return libs; - }, + }); - get pluginFullpath() { + this.__defineGetter__("pluginFullpath", function() { let paths = []; - for (let tag of pluginFor(this).tags) + for (let tag of aTags) paths.push(tag.fullpath); return paths; - }, + }) - get pluginMimeTypes() { + this.__defineGetter__("pluginMimeTypes", function() { let types = []; - for (let tag of pluginFor(this).tags) { + for (let tag of aTags) { let mimeTypes = tag.getMimeTypes({}); let mimeDescriptions = tag.getMimeDescriptions({}); let extensions = tag.getExtensions({}); @@ -471,19 +470,18 @@ PluginWrapper.prototype = { } } return types; - }, + }); - get installDate() { + this.__defineGetter__("installDate", function() { let date = 0; - for (let tag of pluginFor(this).tags) { + for (let tag of aTags) { date = Math.max(date, tag.lastModifiedTime); } return new Date(date); - }, + }); - get scope() { - let { tags: [tag] } = pluginFor(this); - let path = tag.fullpath; + this.__defineGetter__("scope", function() { + let path = aTags[0].fullpath; // Plugins inside the application directory are in the application scope let dir = Services.dirsvc.get("APlugns", Ci.nsIFile); if (path.startsWith(dir.path)) @@ -500,28 +498,25 @@ PluginWrapper.prototype = { dir = Services.dirsvc.get("Home", Ci.nsIFile); if (path.startsWith(dir.path)) return AddonManager.SCOPE_USER; - } catch (e) { - if (!e.result || e.result != Components.results.NS_ERROR_FAILURE) - throw e; + } catch (e if (e.result && e.result == Components.results.NS_ERROR_FAILURE)) { // Do nothing: missing "Home". } // Any other locations are system scope return AddonManager.SCOPE_SYSTEM; - }, + }); - get pendingOperations() { + this.__defineGetter__("pendingOperations", function() { return AddonManager.PENDING_NONE; - }, + }); - get operationsRequiringRestart() { + this.__defineGetter__("operationsRequiringRestart", function() { return AddonManager.OP_NEEDS_RESTART_NONE; - }, + }); - get permissions() { - let { tags: [tag] } = pluginFor(this); + this.__defineGetter__("permissions", function() { let permissions = 0; - if (tag.isEnabledStateLocked) { + if (aTags[0].isEnabledStateLocked) { return permissions; } if (!this.appDisabled) { @@ -545,18 +540,18 @@ PluginWrapper.prototype = { } } return permissions; - }, + }); - get optionsType() { + this.__defineGetter__("optionsType", function() { if (canDisableFlashProtectedMode(this)) { return AddonManager.OPTIONS_TYPE_INLINE; } return AddonManager.OPTIONS_TYPE_INLINE_INFO; - }, + }); +} - get optionsURL() { - return "chrome://mozapps/content/extensions/pluginPrefs.xul"; - }, +PluginWrapper.prototype = { + optionsURL: "chrome://mozapps/content/extensions/pluginPrefs.xul", get updateDate() { return this.installDate; @@ -578,7 +573,7 @@ PluginWrapper.prototype = { return true; }, - isCompatibleWith: function(aAppVersion, aPlatformVersion) { + isCompatibleWith: function(aAppVerison, aPlatformVersion) { return true; }, diff --git a/toolkit/mozapps/extensions/internal/ProductAddonChecker.jsm b/toolkit/mozapps/extensions/internal/ProductAddonChecker.jsm deleted file mode 100644 index f98dd2a94..000000000 --- a/toolkit/mozapps/extensions/internal/ProductAddonChecker.jsm +++ /dev/null @@ -1,467 +0,0 @@ -/* 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/. */ - -"use strict"; - -const { classes: Cc, interfaces: Ci, utils: Cu } = Components; - -const LOCAL_EME_SOURCES = [{ - "id": "gmp-eme-adobe", - "src": "chrome://global/content/gmp-sources/eme-adobe.json" -}, { - "id": "gmp-gmpopenh264", - "src": "chrome://global/content/gmp-sources/openh264.json" -}, { - "id": "gmp-widevinecdm", - "src": "chrome://global/content/gmp-sources/widevinecdm.json" -}]; - -this.EXPORTED_SYMBOLS = [ "ProductAddonChecker" ]; - -Cu.importGlobalProperties(["XMLHttpRequest"]); - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/Task.jsm"); -Cu.import("resource://gre/modules/Log.jsm"); -Cu.import("resource://gre/modules/CertUtils.jsm"); -/* globals checkCert, BadCertHandler*/ -Cu.import("resource://gre/modules/FileUtils.jsm"); -Cu.import("resource://gre/modules/NetUtil.jsm"); -Cu.import("resource://gre/modules/osfile.jsm"); - -/* globals GMPPrefs */ -XPCOMUtils.defineLazyModuleGetter(this, "GMPPrefs", - "resource://gre/modules/GMPUtils.jsm"); - -/* globals OS */ - -XPCOMUtils.defineLazyModuleGetter(this, "UpdateUtils", - "resource://gre/modules/UpdateUtils.jsm"); - -XPCOMUtils.defineLazyModuleGetter(this, "ServiceRequest", - "resource://gre/modules/ServiceRequest.jsm"); - -// This exists so that tests can override the XHR behaviour for downloading -// the addon update XML file. -var CreateXHR = function() { - return Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]. - createInstance(Ci.nsISupports); -} - -var logger = Log.repository.getLogger("addons.productaddons"); - -/** - * Number of milliseconds after which we need to cancel `downloadXML`. - * - * Bug 1087674 suggests that the XHR we use in `downloadXML` may - * never terminate in presence of network nuisances (e.g. strange - * antivirus behavior). This timeout is a defensive measure to ensure - * that we fail cleanly in such case. - */ -const TIMEOUT_DELAY_MS = 20000; -// Chunk size for the incremental downloader -const DOWNLOAD_CHUNK_BYTES_SIZE = 300000; -// Incremental downloader interval -const DOWNLOAD_INTERVAL = 0; -// How much of a file to read into memory at a time for hashing -const HASH_CHUNK_SIZE = 8192; - -/** - * Gets the status of an XMLHttpRequest either directly or from its underlying - * channel. - * - * @param request - * The XMLHttpRequest. - * @return an integer status value. - */ -function getRequestStatus(request) { - let status = null; - try { - status = request.status; - } - catch (e) { - } - - if (status != null) { - return status; - } - - return request.channel.QueryInterface(Ci.nsIRequest).status; -} - -/** - * Downloads an XML document from a URL optionally testing the SSL certificate - * for certain attributes. - * - * @param url - * The url to download from. - * @param allowNonBuiltIn - * Whether to trust SSL certificates without a built-in CA issuer. - * @param allowedCerts - * The list of certificate attributes to match the SSL certificate - * against or null to skip checks. - * @return a promise that resolves to the DOM document downloaded or rejects - * with a JS exception in case of error. - */ -function downloadXML(url, allowNonBuiltIn = false, allowedCerts = null) { - return new Promise((resolve, reject) => { - let request = CreateXHR(); - // This is here to let unit test code override XHR - if (request.wrappedJSObject) { - request = request.wrappedJSObject; - } - request.open("GET", url, true); - request.channel.notificationCallbacks = new BadCertHandler(allowNonBuiltIn); - // Prevent the request from reading from the cache. - request.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE; - // Prevent the request from writing to the cache. - request.channel.loadFlags |= Ci.nsIRequest.INHIBIT_CACHING; - // Use conservative TLS settings. See bug 1325501. - // TODO move to ServiceRequest. - if (request.channel instanceof Ci.nsIHttpChannelInternal) { - request.channel.QueryInterface(Ci.nsIHttpChannelInternal).beConservative = true; - } - request.timeout = TIMEOUT_DELAY_MS; - - request.overrideMimeType("text/xml"); - // The Cache-Control header is only interpreted by proxies and the - // final destination. It does not help if a resource is already - // cached locally. - request.setRequestHeader("Cache-Control", "no-cache"); - // HTTP/1.0 servers might not implement Cache-Control and - // might only implement Pragma: no-cache - request.setRequestHeader("Pragma", "no-cache"); - - let fail = (event) => { - let request = event.target; - let status = getRequestStatus(request); - let message = "Failed downloading XML, status: " + status + ", reason: " + event.type; - logger.warn(message); - let ex = new Error(message); - ex.status = status; - reject(ex); - }; - - let success = (event) => { - logger.info("Completed downloading document"); - let request = event.target; - - try { - checkCert(request.channel, allowNonBuiltIn, allowedCerts); - } catch (ex) { - logger.error("Request failed certificate checks: " + ex); - ex.status = getRequestStatus(request); - reject(ex); - return; - } - - resolve(request.responseXML); - }; - - request.addEventListener("error", fail, false); - request.addEventListener("abort", fail, false); - request.addEventListener("timeout", fail, false); - request.addEventListener("load", success, false); - - logger.info("sending request to: " + url); - request.send(null); - }); -} - -function downloadJSON(uri) { - logger.info("fetching config from: " + uri); - return new Promise((resolve, reject) => { - let xmlHttp = new ServiceRequest({mozAnon: true}); - - xmlHttp.onload = function(aResponse) { - resolve(JSON.parse(this.responseText)); - }; - - xmlHttp.onerror = function(e) { - reject("Fetching " + uri + " results in error code: " + e.target.status); - }; - - xmlHttp.open("GET", uri); - xmlHttp.overrideMimeType("application/json"); - xmlHttp.send(); - }); -} - - -/** - * Parses a list of add-ons from a DOM document. - * - * @param document - * The DOM document to parse. - * @return null if there is no <addons> element otherwise an object containing - * an array of the addons listed and a field notifying whether the - * fallback was used. - */ -function parseXML(document) { - // Check that the root element is correct - if (document.documentElement.localName != "updates") { - throw new Error("got node name: " + document.documentElement.localName + - ", expected: updates"); - } - - // Check if there are any addons elements in the updates element - let addons = document.querySelector("updates:root > addons"); - if (!addons) { - return null; - } - - let results = []; - let addonList = document.querySelectorAll("updates:root > addons > addon"); - for (let addonElement of addonList) { - let addon = {}; - - for (let name of ["id", "URL", "hashFunction", "hashValue", "version", "size"]) { - if (addonElement.hasAttribute(name)) { - addon[name] = addonElement.getAttribute(name); - } - } - addon.size = Number(addon.size) || undefined; - - results.push(addon); - } - - return { - usedFallback: false, - gmpAddons: results - }; -} - -/** - * If downloading from the network fails (AUS server is down), - * load the sources from local build configuration. - */ -function downloadLocalConfig() { - - if (!GMPPrefs.get(GMPPrefs.KEY_UPDATE_ENABLED, true)) { - logger.info("Updates are disabled via media.gmp-manager.updateEnabled"); - return Promise.resolve({usedFallback: true, gmpAddons: []}); - } - - return Promise.all(LOCAL_EME_SOURCES.map(conf => { - return downloadJSON(conf.src).then(addons => { - - let platforms = addons.vendors[conf.id].platforms; - let target = Services.appinfo.OS + "_" + UpdateUtils.ABI; - let details = null; - - while (!details) { - if (!(target in platforms)) { - // There was no matching platform so return false, this addon - // will be filtered from the results below - logger.info("no details found for: " + target); - return false; - } - // Field either has the details of the binary or is an alias - // to another build target key that does - if (platforms[target].alias) { - target = platforms[target].alias; - } else { - details = platforms[target]; - } - } - - logger.info("found plugin: " + conf.id); - return { - "id": conf.id, - "URL": details.fileUrl, - "hashFunction": addons.hashFunction, - "hashValue": details.hashValue, - "version": addons.vendors[conf.id].version, - "size": details.filesize - }; - }); - })).then(addons => { - - // Some filters may not match this platform so - // filter those out - addons = addons.filter(x => x !== false); - - return { - usedFallback: true, - gmpAddons: addons - }; - }); -} - -/** - * Downloads file from a URL using XHR. - * - * @param url - * The url to download from. - * @return a promise that resolves to the path of a temporary file or rejects - * with a JS exception in case of error. - */ -function downloadFile(url) { - return new Promise((resolve, reject) => { - let xhr = new XMLHttpRequest(); - xhr.onload = function(response) { - logger.info("downloadXHR File download. status=" + xhr.status); - if (xhr.status != 200 && xhr.status != 206) { - reject(Components.Exception("File download failed", xhr.status)); - return; - } - Task.spawn(function* () { - let f = yield OS.File.openUnique(OS.Path.join(OS.Constants.Path.tmpDir, "tmpaddon")); - let path = f.path; - logger.info(`Downloaded file will be saved to ${path}`); - yield f.file.close(); - yield OS.File.writeAtomic(path, new Uint8Array(xhr.response)); - return path; - }).then(resolve, reject); - }; - - let fail = (event) => { - let request = event.target; - let status = getRequestStatus(request); - let message = "Failed downloading via XHR, status: " + status + ", reason: " + event.type; - logger.warn(message); - let ex = new Error(message); - ex.status = status; - reject(ex); - }; - xhr.addEventListener("error", fail); - xhr.addEventListener("abort", fail); - - xhr.responseType = "arraybuffer"; - try { - xhr.open("GET", url); - // Use conservative TLS settings. See bug 1325501. - // TODO move to ServiceRequest. - if (xhr.channel instanceof Ci.nsIHttpChannelInternal) { - xhr.channel.QueryInterface(Ci.nsIHttpChannelInternal).beConservative = true; - } - xhr.send(null); - } catch (ex) { - reject(ex); - } - }); -} - -/** - * Convert a string containing binary values to hex. - */ -function binaryToHex(input) { - let result = ""; - for (let i = 0; i < input.length; ++i) { - let hex = input.charCodeAt(i).toString(16); - if (hex.length == 1) { - hex = "0" + hex; - } - result += hex; - } - return result; -} - -/** - * Calculates the hash of a file. - * - * @param hashFunction - * The type of hash function to use, must be supported by nsICryptoHash. - * @param path - * The path of the file to hash. - * @return a promise that resolves to hash of the file or rejects with a JS - * exception in case of error. - */ -var computeHash = Task.async(function*(hashFunction, path) { - let file = yield OS.File.open(path, { existing: true, read: true }); - try { - let hasher = Cc["@mozilla.org/security/hash;1"]. - createInstance(Ci.nsICryptoHash); - hasher.initWithString(hashFunction); - - let bytes; - do { - bytes = yield file.read(HASH_CHUNK_SIZE); - hasher.update(bytes, bytes.length); - } while (bytes.length == HASH_CHUNK_SIZE); - - return binaryToHex(hasher.finish(false)); - } - finally { - yield file.close(); - } -}); - -/** - * Verifies that a downloaded file matches what was expected. - * - * @param properties - * The properties to check, `size` and `hashFunction` with `hashValue` - * are supported. Any properties missing won't be checked. - * @param path - * The path of the file to check. - * @return a promise that resolves if the file matched or rejects with a JS - * exception in case of error. - */ -var verifyFile = Task.async(function*(properties, path) { - if (properties.size !== undefined) { - let stat = yield OS.File.stat(path); - if (stat.size != properties.size) { - throw new Error("Downloaded file was " + stat.size + " bytes but expected " + properties.size + " bytes."); - } - } - - if (properties.hashFunction !== undefined) { - let expectedDigest = properties.hashValue.toLowerCase(); - let digest = yield computeHash(properties.hashFunction, path); - if (digest != expectedDigest) { - throw new Error("Hash was `" + digest + "` but expected `" + expectedDigest + "`."); - } - } -}); - -const ProductAddonChecker = { - /** - * Downloads a list of add-ons from a URL optionally testing the SSL - * certificate for certain attributes. - * - * @param url - * The url to download from. - * @param allowNonBuiltIn - * Whether to trust SSL certificates without a built-in CA issuer. - * @param allowedCerts - * The list of certificate attributes to match the SSL certificate - * against or null to skip checks. - * @return a promise that resolves to an object containing the list of add-ons - * and whether the local fallback was used, or rejects with a JS - * exception in case of error. - */ - getProductAddonList: function(url, allowNonBuiltIn = false, allowedCerts = null) { - if (!GMPPrefs.get(GMPPrefs.KEY_UPDATE_ENABLED, true)) { - logger.info("Updates are disabled via media.gmp-manager.updateEnabled"); - return Promise.resolve({usedFallback: true, gmpAddons: []}); - } - - return downloadXML(url, allowNonBuiltIn, allowedCerts) - .then(parseXML) - .catch(downloadLocalConfig); - }, - - /** - * Downloads an add-on to a local file and checks that it matches the expected - * file. The caller is responsible for deleting the temporary file returned. - * - * @param addon - * The addon to download. - * @return a promise that resolves to the temporary file downloaded or rejects - * with a JS exception in case of error. - */ - downloadAddon: Task.async(function*(addon) { - let path = yield downloadFile(addon.URL); - try { - yield verifyFile(addon, path); - return path; - } - catch (e) { - yield OS.File.remove(path); - throw e; - } - }) -} diff --git a/toolkit/mozapps/extensions/internal/WebExtensionBootstrap.js b/toolkit/mozapps/extensions/internal/WebExtensionBootstrap.js deleted file mode 100644 index a920c2eae..000000000 --- a/toolkit/mozapps/extensions/internal/WebExtensionBootstrap.js +++ /dev/null @@ -1,39 +0,0 @@ -/* 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/. */ - -"use strict"; - -Components.utils.import("resource://gre/modules/Extension.jsm"); - -var extension; - -const BOOTSTRAP_REASON_TO_STRING_MAP = { - 1: "APP_STARTUP", - 2: "APP_SHUTDOWN", - 3: "ADDON_ENABLE", - 4: "ADDON_DISABLE", - 5: "ADDON_INSTALL", - 6: "ADDON_UNINSTALL", - 7: "ADDON_UPGRADE", - 8: "ADDON_DOWNGRADE", -} - -function install(data, reason) -{ -} - -function startup(data, reason) -{ - extension = new Extension(data, BOOTSTRAP_REASON_TO_STRING_MAP[reason]); - extension.startup(); -} - -function shutdown(data, reason) -{ - extension.shutdown(); -} - -function uninstall(data, reason) -{ -} diff --git a/toolkit/mozapps/extensions/internal/XPIProvider.jsm b/toolkit/mozapps/extensions/internal/XPIProvider.jsm index 87e09cef1..8b49c6600 100644 --- a/toolkit/mozapps/extensions/internal/XPIProvider.jsm +++ b/toolkit/mozapps/extensions/internal/XPIProvider.jsm @@ -1,4 +1,4 @@ - /* This Source Code Form is subject to the terms of the Mozilla Public +/* 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/. */ @@ -11,14 +11,10 @@ const Cu = Components.utils; this.EXPORTED_SYMBOLS = ["XPIProvider"]; -const CONSTANTS = {}; -Cu.import("resource://gre/modules/addons/AddonConstants.jsm", CONSTANTS); -const { ADDON_SIGNING, REQUIRE_SIGNING } = CONSTANTS - -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/AddonManager.jsm"); -Cu.import("resource://gre/modules/Preferences.jsm"); +Components.utils.import("resource://gre/modules/Services.jsm"); +Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); +Components.utils.import("resource://gre/modules/AddonManager.jsm"); +Components.utils.import("resource://gre/modules/Preferences.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "AddonRepository", "resource://gre/modules/addons/AddonRepository.jsm"); @@ -26,12 +22,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "ChromeManifestParser", "resource://gre/modules/ChromeManifestParser.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "LightweightThemeManager", "resource://gre/modules/LightweightThemeManager.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "ExtensionData", - "resource://gre/modules/Extension.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "ExtensionManagement", - "resource://gre/modules/ExtensionManagement.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "Locale", - "resource://gre/modules/Locale.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "FileUtils", "resource://gre/modules/FileUtils.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "ZipUtils", @@ -50,16 +40,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "BrowserToolboxProcess", "resource://devtools/client/framework/ToolboxProcess.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "ConsoleAPI", "resource://gre/modules/Console.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "ProductAddonChecker", - "resource://gre/modules/addons/ProductAddonChecker.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "UpdateUtils", - "resource://gre/modules/UpdateUtils.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "AppConstants", - "resource://gre/modules/AppConstants.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "isAddonPartOfE10SRollout", - "resource://gre/modules/addons/E10SAddonsRollout.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "LegacyExtensionsUtils", - "resource://gre/modules/LegacyExtensionsUtils.jsm"); XPCOMUtils.defineLazyServiceGetter(this, "Blocklist", "@mozilla.org/extensions/blocklist;1", @@ -73,22 +53,10 @@ XPCOMUtils.defineLazyServiceGetter(this, "@mozilla.org/network/protocol;1?name=resource", "nsIResProtocolHandler"); XPCOMUtils.defineLazyServiceGetter(this, - "AddonPolicyService", - "@mozilla.org/addons/policy-service;1", - "nsIAddonPolicyService"); -XPCOMUtils.defineLazyServiceGetter(this, "AddonPathService", "@mozilla.org/addon-path-service;1", "amIAddonPathService"); -XPCOMUtils.defineLazyGetter(this, "CertUtils", function() { - let certUtils = {}; - Components.utils.import("resource://gre/modules/CertUtils.jsm", certUtils); - return certUtils; -}); - -Cu.importGlobalProperties(["URL"]); - const nsIFile = Components.Constructor("@mozilla.org/file/local;1", "nsIFile", "initWithPath"); @@ -97,6 +65,8 @@ const PREF_INSTALL_CACHE = "extensions.installCache"; const PREF_XPI_STATE = "extensions.xpiState"; const PREF_BOOTSTRAP_ADDONS = "extensions.bootstrappedAddons"; const PREF_PENDING_OPERATIONS = "extensions.pendingOperations"; +const PREF_MATCH_OS_LOCALE = "intl.locale.matchOS"; +const PREF_SELECTED_LOCALE = "general.useragent.locale"; const PREF_EM_DSS_ENABLED = "extensions.dss.enabled"; const PREF_DSS_SWITCHPENDING = "extensions.dss.switchPending"; const PREF_DSS_SKIN_TO_SELECT = "extensions.lastSelectedSkin"; @@ -106,67 +76,53 @@ const PREF_EM_UPDATE_BACKGROUND_URL = "extensions.update.background.url"; const PREF_EM_ENABLED_ADDONS = "extensions.enabledAddons"; const PREF_EM_EXTENSION_FORMAT = "extensions."; const PREF_EM_ENABLED_SCOPES = "extensions.enabledScopes"; +const PREF_EM_AUTO_DISABLED_SCOPES = "extensions.autoDisableScopes"; const PREF_EM_SHOW_MISMATCH_UI = "extensions.showMismatchUI"; const PREF_XPI_ENABLED = "xpinstall.enabled"; const PREF_XPI_WHITELIST_REQUIRED = "xpinstall.whitelist.required"; const PREF_XPI_DIRECT_WHITELISTED = "xpinstall.whitelist.directRequest"; const PREF_XPI_FILE_WHITELISTED = "xpinstall.whitelist.fileRequest"; -// xpinstall.signatures.required only supported in dev builds -const PREF_XPI_SIGNATURES_REQUIRED = "xpinstall.signatures.required"; -const PREF_XPI_SIGNATURES_DEV_ROOT = "xpinstall.signatures.dev-root"; const PREF_XPI_PERMISSIONS_BRANCH = "xpinstall."; const PREF_XPI_UNPACK = "extensions.alwaysUnpack"; const PREF_INSTALL_REQUIREBUILTINCERTS = "extensions.install.requireBuiltInCerts"; const PREF_INSTALL_REQUIRESECUREORIGIN = "extensions.install.requireSecureOrigin"; const PREF_INSTALL_DISTRO_ADDONS = "extensions.installDistroAddons"; const PREF_BRANCH_INSTALLED_ADDON = "extensions.installedDistroAddon."; +const PREF_SHOWN_SELECTION_UI = "extensions.shownSelectionUI"; const PREF_INTERPOSITION_ENABLED = "extensions.interposition.enabled"; -const PREF_SYSTEM_ADDON_SET = "extensions.systemAddonSet"; -const PREF_SYSTEM_ADDON_UPDATE_URL = "extensions.systemAddon.update.url"; -const PREF_E10S_BLOCK_ENABLE = "extensions.e10sBlocksEnabling"; -const PREF_E10S_ADDON_BLOCKLIST = "extensions.e10s.rollout.blocklist"; -const PREF_E10S_ADDON_POLICY = "extensions.e10s.rollout.policy"; -const PREF_E10S_HAS_NONEXEMPT_ADDON = "extensions.e10s.rollout.hasAddon"; const PREF_EM_MIN_COMPAT_APP_VERSION = "extensions.minCompatibleAppVersion"; const PREF_EM_MIN_COMPAT_PLATFORM_VERSION = "extensions.minCompatiblePlatformVersion"; const PREF_CHECKCOMAT_THEMEOVERRIDE = "extensions.checkCompatibility.temporaryThemeOverride_minAppVersion"; -const PREF_EM_HOTFIX_ID = "extensions.hotfix.id"; -const PREF_EM_CERT_CHECKATTRIBUTES = "extensions.hotfix.cert.checkAttributes"; -const PREF_EM_HOTFIX_CERTS = "extensions.hotfix.certs."; - +const URI_EXTENSION_SELECT_DIALOG = "chrome://mozapps/content/extensions/selectAddons.xul"; const URI_EXTENSION_UPDATE_DIALOG = "chrome://mozapps/content/extensions/update.xul"; const URI_EXTENSION_STRINGS = "chrome://mozapps/locale/extensions/extensions.properties"; const STRING_TYPE_NAME = "type.%ID%.name"; const DIR_EXTENSIONS = "extensions"; -const DIR_SYSTEM_ADDONS = "features"; const DIR_STAGE = "staged"; +const DIR_XPI_STAGE = "staged-xpis"; const DIR_TRASH = "trash"; const FILE_DATABASE = "extensions.json"; const FILE_OLD_CACHE = "extensions.cache"; -const FILE_RDF_MANIFEST = "install.rdf"; -const FILE_WEB_MANIFEST = "manifest.json"; +const FILE_INSTALL_MANIFEST = "install.rdf"; +const FILE_WEBEXT_MANIFEST = "manifest.json"; const FILE_XPI_ADDONS_LIST = "extensions.ini"; const KEY_PROFILEDIR = "ProfD"; -const KEY_ADDON_APP_DIR = "XREAddonAppDir"; +const KEY_APPDIR = "XCurProcD"; const KEY_TEMPDIR = "TmpD"; const KEY_APP_DISTRIBUTION = "XREAppDist"; -const KEY_APP_FEATURES = "XREAppFeat"; const KEY_APP_PROFILE = "app-profile"; -const KEY_APP_SYSTEM_ADDONS = "app-system-addons"; -const KEY_APP_SYSTEM_DEFAULTS = "app-system-defaults"; const KEY_APP_GLOBAL = "app-global"; const KEY_APP_SYSTEM_LOCAL = "app-system-local"; const KEY_APP_SYSTEM_SHARE = "app-system-share"; const KEY_APP_SYSTEM_USER = "app-system-user"; -const KEY_APP_TEMPORARY = "app-temporary"; const NOTIFICATION_FLUSH_PERMISSIONS = "flush-pending-permissions"; const XPI_PERMISSION = "install"; @@ -175,11 +131,13 @@ const RDFURI_INSTALL_MANIFEST_ROOT = "urn:mozilla:install-manifest"; const PREFIX_NS_EM = "http://www.mozilla.org/2004/em-rdf#"; const TOOLKIT_ID = "toolkit@mozilla.org"; +#ifdef MOZ_PHOENIX_EXTENSIONS +const FIREFOX_ID = "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}" +const FIREFOX_APPCOMPATVERSION = "56.9" +#endif -const XPI_SIGNATURE_CHECK_PERIOD = 24 * 60 * 60; - -XPCOMUtils.defineConstant(this, "DB_SCHEMA", 19); - +// The value for this is in Makefile.in +#expand const DB_SCHEMA = __MOZ_EXTENSIONS_DB_SCHEMA__; const NOTIFICATION_TOOLBOXPROCESS_LOADED = "ToolboxProcessLoaded"; // Properties that exist in the install manifest @@ -190,6 +148,12 @@ const PROP_LOCALE_SINGLE = ["name", "description", "creator", "homepageURL"]; const PROP_LOCALE_MULTI = ["developers", "translators", "contributors"]; const PROP_TARGETAPP = ["id", "minVersion", "maxVersion"]; +// Properties that should be migrated where possible from an old database. These +// shouldn't include properties that can be read directly from install.rdf files +// or calculated +const DB_MIGRATE_METADATA= ["installDate", "userDisabled", "softDisabled", + "sourceURI", "applyBackgroundUpdates", + "releaseNotesURI", "foreignInstall", "syncGUID"]; // Properties to cache and reload when an addon installation is pending const PENDING_INSTALL_METADATA = ["syncGUID", "targetApplications", "userDisabled", "softDisabled", @@ -229,51 +193,12 @@ const TYPES = { experiment: 128, }; -if (!AppConstants.RELEASE_OR_BETA) - TYPES.apiextension = 256; - -// Some add-on types that we track internally are presented as other types -// externally -const TYPE_ALIASES = { - "webextension": "extension", - "apiextension": "extension", -}; - -const CHROME_TYPES = new Set([ - "extension", - "locale", - "experiment", -]); - const RESTARTLESS_TYPES = new Set([ - "webextension", "dictionary", "experiment", "locale", - "apiextension", ]); -const SIGNED_TYPES = new Set([ - "webextension", - "extension", - "experiment", - "apiextension", -]); - -// This is a random number array that can be used as "salt" when generating -// an automatic ID based on the directory path of an add-on. It will prevent -// someone from creating an ID for a permanent add-on that could be replaced -// by a temporary add-on (because that would be confusing, I guess). -const TEMP_INSTALL_ID_GEN_SESSION = - new Uint8Array(Float64Array.of(Math.random()).buffer); - -// Whether add-on signing is required. -function mustSign(aType) { - if (!SIGNED_TYPES.has(aType)) - return false; - return REQUIRE_SIGNING || Preferences.get(PREF_XPI_SIGNATURES_REQUIRED, false); -} - // Keep track of where we are in startup for telemetry // event happened during XPIDatabase.startup() const XPI_STARTING = "XPIStarting"; @@ -288,7 +213,6 @@ const COMPATIBLE_BY_DEFAULT_TYPES = { }; const MSG_JAR_FLUSH = "AddonJarFlush"; -const MSG_MESSAGE_MANAGER_CACHES_FLUSH = "AddonMessageManagerCachesFlush"; var gGlobalScope = this; @@ -304,38 +228,17 @@ const LOGGER_ID = "addons.xpi"; // (Requires AddonManager.jsm) var logger = Log.repository.getLogger(LOGGER_ID); -const LAZY_OBJECTS = ["XPIDatabase", "XPIDatabaseReconcile"]; -/* globals XPIDatabase, XPIDatabaseReconcile*/ +const LAZY_OBJECTS = ["XPIDatabase"]; var gLazyObjectsLoaded = false; function loadLazyObjects() { - let uri = "resource://gre/modules/addons/XPIProviderUtils.js"; - let scope = Cu.Sandbox(Services.scriptSecurityManager.getSystemPrincipal(), { - sandboxName: uri, - wantGlobalProperties: ["TextDecoder"], - }); - - let shared = { - ADDON_SIGNING, - SIGNED_TYPES, - BOOTSTRAP_REASONS, - DB_SCHEMA, - AddonInternal, - XPIProvider, - XPIStates, - syncLoadManifestFromFile, - isUsableAddon, - recordAddonTelemetry, - applyBlocklistChanges, - flushChromeCaches, - canRunInSafeMode, - } - - for (let key of Object.keys(shared)) - scope[key] = shared[key]; - - Services.scriptloader.loadSubScript(uri, scope); + let scope = {}; + scope.AddonInternal = AddonInternal; + scope.XPIProvider = XPIProvider; + scope.XPIStates = XPIStates; + Services.scriptloader.loadSubScript("resource://gre/modules/addons/XPIProviderUtils.js", + scope); for (let name of LAZY_OBJECTS) { delete gGlobalScope[name]; @@ -345,35 +248,17 @@ function loadLazyObjects() { return scope; } -LAZY_OBJECTS.forEach(name => { +for (let name of LAZY_OBJECTS) { Object.defineProperty(gGlobalScope, name, { - get: function() { + get: function lazyObjectGetter() { let objs = loadLazyObjects(); return objs[name]; }, configurable: true }); -}); - - -// Behaves like Promise.all except waits for all promises to resolve/reject -// before resolving/rejecting itself -function waitForAllPromises(promises) { - return new Promise((resolve, reject) => { - let shouldReject = false; - let rejectValue = null; - - let newPromises = promises.map( - p => p.catch(value => { - shouldReject = true; - rejectValue = value; - }) - ); - Promise.all(newPromises) - .then((results) => shouldReject ? reject(rejectValue) : resolve(results)); - }); } + function findMatchingStaticBlocklistItem(aAddon) { for (let item of STATIC_BLOCKLIST_PATTERNS) { if ("creator" in item && typeof item.creator == "string") { @@ -386,12 +271,6 @@ function findMatchingStaticBlocklistItem(aAddon) { return null; } -/** - * Converts an iterable of addon objects into a map with the add-on's ID as key. - */ -function addonMap(addons) { - return new Map(addons.map(a => [a.id, a])); -} /** * Sets permissions on a file @@ -412,33 +291,6 @@ function setFilePermissions(aFile, aPermissions) { } /** - * Write a given string to a file - * - * @param file - * The nsIFile instance to write into - * @param string - * The string to write - */ -function writeStringToFile(file, string) { - let stream = Cc["@mozilla.org/network/file-output-stream;1"]. - createInstance(Ci.nsIFileOutputStream); - let converter = Cc["@mozilla.org/intl/converter-output-stream;1"]. - createInstance(Ci.nsIConverterOutputStream); - - try { - stream.init(file, FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE | - FileUtils.MODE_TRUNCATE, FileUtils.PERMS_FILE, - 0); - converter.init(stream, "UTF-8", 0, 0x0000); - converter.writeString(string); - } - finally { - converter.close(); - stream.close(); - } -} - -/** * A safe way to install a file or the contents of a directory to a new * directory. The file or directory is moved or copied recursively and if * anything fails an attempt is made to rollback the entire operation. The @@ -457,22 +309,14 @@ SafeInstallOperation.prototype = { _installedFiles: null, _createdDirs: null, - _installFile: function(aFile, aTargetDirectory, aCopy) { + _installFile: function SIO_installFile(aFile, aTargetDirectory, aCopy) { let oldFile = aCopy ? null : aFile.clone(); let newFile = aFile.clone(); try { - if (aCopy) { + if (aCopy) newFile.copyTo(aTargetDirectory, null); - // copyTo does not update the nsIFile with the new. - newFile = aTargetDirectory.clone(); - newFile.append(aFile.leafName); - // Windows roaming profiles won't properly sync directories if a new file - // has an older lastModifiedTime than a previous file, so update. - newFile.lastModifiedTime = Date.now(); - } - else { + else newFile.moveTo(aTargetDirectory, null); - } } catch (e) { logger.error("Failed to " + (aCopy ? "copy" : "move") + " file " + aFile.path + @@ -482,13 +326,7 @@ SafeInstallOperation.prototype = { this._installedFiles.push({ oldFile: oldFile, newFile: newFile }); }, - _installDirectory: function(aDirectory, aTargetDirectory, aCopy) { - if (aDirectory.contains(aTargetDirectory)) { - let err = new Error(`Not installing ${aDirectory} into its own descendent ${aTargetDirectory}`); - logger.error(err); - throw err; - } - + _installDirectory: function SIO_installDirectory(aDirectory, aTargetDirectory, aCopy) { let newDir = aTargetDirectory.clone(); newDir.append(aDirectory.leafName); try { @@ -505,16 +343,16 @@ SafeInstallOperation.prototype = { // embedded filesystem has this issue, see bug 772238), and to remove // normal files before their resource forks on OSX (see bug 733436). let entries = getDirectoryEntries(aDirectory, true); - for (let entry of entries) { + entries.forEach(function(aEntry) { try { - this._installDirEntry(entry, newDir, aCopy); + this._installDirEntry(aEntry, newDir, aCopy); } catch (e) { logger.error("Failed to " + (aCopy ? "copy" : "move") + " entry " + - entry.path, e); + aEntry.path, e); throw e; } - } + }, this); // If this is only a copy operation then there is nothing else to do if (aCopy) @@ -536,11 +374,11 @@ SafeInstallOperation.prototype = { this._installedFiles.push({ oldFile: aDirectory, newFile: newDir }); }, - _installDirEntry: function(aDirEntry, aTargetDirectory, aCopy) { + _installDirEntry: function SIO_installDirEntry(aDirEntry, aTargetDirectory, aCopy) { let isDir = null; try { - isDir = aDirEntry.isDirectory() && !aDirEntry.isSymlink(); + isDir = aDirEntry.isDirectory(); } catch (e) { // If the file has already gone away then don't worry about it, this can @@ -577,7 +415,7 @@ SafeInstallOperation.prototype = { * The directory to move into, this is expected to be an empty * directory. */ - moveUnder: function(aFile, aTargetDirectory) { + moveUnder: function SIO_move(aFile, aTargetDirectory) { try { this._installDirEntry(aFile, aTargetDirectory, false); } @@ -602,7 +440,7 @@ SafeInstallOperation.prototype = { oldFile.moveTo(newFile.parent, newFile.leafName); this._installedFiles.push({ oldFile: oldFile, newFile: newFile, isMoveTo: true}); } - catch (e) { + catch(e) { this.rollback(); throw e; } @@ -618,7 +456,7 @@ SafeInstallOperation.prototype = { * The directory to copy into, this is expected to be an empty * directory. */ - copy: function(aFile, aTargetDirectory) { + copy: function SIO_copy(aFile, aTargetDirectory) { try { this._installDirEntry(aFile, aTargetDirectory, true); } @@ -633,13 +471,13 @@ SafeInstallOperation.prototype = { * occurs here then both old and new directories are left in an indeterminate * state */ - rollback: function() { + rollback: function SIO_rollback() { while (this._installedFiles.length > 0) { let move = this._installedFiles.pop(); if (move.isMoveTo) { - move.newFile.moveTo(move.oldDir.parent, move.oldDir.leafName); + move.newFile.moveTo(oldDir.parent, oldDir.leafName); } - else if (move.newFile.isDirectory() && !move.newFile.isSymlink()) { + else if (move.newFile.isDirectory()) { let oldDir = move.oldFile.parent.clone(); oldDir.append(move.oldFile.leafName); oldDir.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY); @@ -659,6 +497,84 @@ SafeInstallOperation.prototype = { }; /** + * Gets the currently selected locale for display. + * @return the selected locale or "en-US" if none is selected + */ +function getLocale() { + if (Preferences.get(PREF_MATCH_OS_LOCALE, false)) + return Services.locale.getLocaleComponentForUserAgent(); + try { + let locale = Preferences.get(PREF_SELECTED_LOCALE, null, Ci.nsIPrefLocalizedString); + if (locale) + return locale; + } + catch (e) {} + return Preferences.get(PREF_SELECTED_LOCALE, "en-US"); +} + +/** + * Selects the closest matching locale from a list of locales. + * + * @param aLocales + * An array of locales + * @return the best match for the currently selected locale + */ +function findClosestLocale(aLocales) { + let appLocale = getLocale(); + + // Holds the best matching localized resource + var bestmatch = null; + // The number of locale parts it matched with + var bestmatchcount = 0; + // The number of locale parts in the match + var bestpartcount = 0; + + var matchLocales = [appLocale.toLowerCase()]; + /* If the current locale is English then it will find a match if there is + a valid match for en-US so no point searching that locale too. */ + if (matchLocales[0].substring(0, 3) != "en-") + matchLocales.push("en-us"); + + for each (var locale in matchLocales) { + var lparts = locale.split("-"); + for each (var localized in aLocales) { + for each (let found in localized.locales) { + found = found.toLowerCase(); + // Exact match is returned immediately + if (locale == found) + return localized; + + var fparts = found.split("-"); + /* If we have found a possible match and this one isn't any longer + then we dont need to check further. */ + if (bestmatch && fparts.length < bestmatchcount) + continue; + + // Count the number of parts that match + var maxmatchcount = Math.min(fparts.length, lparts.length); + var matchcount = 0; + while (matchcount < maxmatchcount && + fparts[matchcount] == lparts[matchcount]) + matchcount++; + + /* If we matched more than the last best match or matched the same and + this locale is less specific than the last best match. */ + if (matchcount > bestmatchcount || + (matchcount == bestmatchcount && fparts.length < bestpartcount)) { + bestmatch = localized; + bestmatchcount = matchcount; + bestpartcount = fparts.length; + } + } + } + // If we found a valid match for this locale return it + if (bestmatch) + return bestmatch; + } + return null; +} + +/** * Sets the userDisabled and softDisabled properties of an add-on based on what * values those properties had for a previous instance of the add-on. The * previous instance may be a previous install or in the case of an application @@ -684,10 +600,10 @@ function applyBlocklistChanges(aOldAddon, aNewAddon, aOldAppVersion, aNewAddon.userDisabled = aOldAddon.userDisabled; aNewAddon.softDisabled = aOldAddon.softDisabled; - let oldBlocklistState = Blocklist.getAddonBlocklistState(aOldAddon.wrapper, + let oldBlocklistState = Blocklist.getAddonBlocklistState(createWrapper(aOldAddon), aOldAppVersion, aOldPlatformVersion); - let newBlocklistState = Blocklist.getAddonBlocklistState(aNewAddon.wrapper); + let newBlocklistState = Blocklist.getAddonBlocklistState(createWrapper(aNewAddon)); // If the blocklist state hasn't changed then the properties don't need to // change @@ -712,27 +628,6 @@ function applyBlocklistChanges(aOldAddon, aNewAddon, aOldAppVersion, } /** - * Evaluates whether an add-on is allowed to run in safe mode. - * - * @param aAddon - * The add-on to check - * @return true if the add-on should run in safe mode - */ -function canRunInSafeMode(aAddon) { - // Even though the updated system add-ons aren't generally run in safe mode we - // include them here so their uninstall functions get called when switching - // back to the default set. - - // TODO product should make the call about temporary add-ons running - // in safe mode. assuming for now that they are. - if (aAddon._installLocation.name == KEY_APP_TEMPORARY) - return true; - - return aAddon._installLocation.name == KEY_APP_SYSTEM_DEFAULTS || - aAddon._installLocation.name == KEY_APP_SYSTEM_ADDONS; -} - -/** * Calculates whether an add-on should be appDisabled or not. * * @param aAddon @@ -744,59 +639,23 @@ function isUsableAddon(aAddon) { if (aAddon.type == "theme" && aAddon.internalName == XPIProvider.defaultSkin) return true; - if (mustSign(aAddon.type) && !aAddon.isCorrectlySigned) { - logger.warn(`Add-on ${aAddon.id} is not correctly signed.`); + if (aAddon.blocklistState == Blocklist.STATE_BLOCKED) return false; - } - if (aAddon.blocklistState == Blocklist.STATE_BLOCKED) { - logger.warn(`Add-on ${aAddon.id} is blocklisted.`); + if (AddonManager.checkUpdateSecurity && !aAddon.providesUpdatesSecurely) return false; - } - - // Experiments are installed through an external mechanism that - // limits target audience to compatible clients. We trust it knows what - // it's doing and skip compatibility checks. - // - // This decision does forfeit defense in depth. If the experiments system - // is ever wrong about targeting an add-on to a specific application - // or platform, the client will likely see errors. - if (aAddon.type == "experiment") - return true; - if (AddonManager.checkUpdateSecurity && !aAddon.providesUpdatesSecurely) { - logger.warn(`Updates for add-on ${aAddon.id} must be provided over HTTPS.`); + if (!aAddon.isPlatformCompatible) return false; - } - - - if (!aAddon.isPlatformCompatible) { - logger.warn(`Add-on ${aAddon.id} is not compatible with platform.`); - return false; - } - - if (aAddon.dependencies.length) { - let isActive = id => { - let active = XPIProvider.activeAddons.get(id); - return active && !active.disable; - }; - - if (aAddon.dependencies.some(id => !isActive(id))) - return false; - } if (AddonManager.checkCompatibility) { - if (!aAddon.isCompatible) { - logger.warn(`Add-on ${aAddon.id} is not compatible with application version.`); + if (!aAddon.isCompatible) return false; - } } else { let app = aAddon.matchingTargetApplication; - if (!app) { - logger.warn(`Add-on ${aAddon.id} is not compatible with target application.`); + if (!app) return false; - } // XXX Temporary solution to let applications opt-in to make themes safer // following significant UI changes even if checkCompatibility=false has @@ -806,7 +665,6 @@ function isUsableAddon(aAddon) { let minCompatVersion = Services.prefs.getCharPref(PREF_CHECKCOMAT_THEMEOVERRIDE); if (minCompatVersion && Services.vc.compare(minCompatVersion, app.maxVersion) > 0) { - logger.warn(`Theme ${aAddon.id} is not compatible with application version.`); return false; } } catch (e) {} @@ -827,75 +685,11 @@ function createAddonDetails(id, aAddon) { return { id: id || aAddon.id, type: aAddon.type, - version: aAddon.version, - multiprocessCompatible: aAddon.multiprocessCompatible, - mpcOptedOut: aAddon.mpcOptedOut, - runInSafeMode: aAddon.runInSafeMode, - dependencies: aAddon.dependencies, - hasEmbeddedWebExtension: aAddon.hasEmbeddedWebExtension, + version: aAddon.version }; } /** - * Converts an internal add-on type to the type presented through the API. - * - * @param aType - * The internal add-on type - * @return an external add-on type - */ -function getExternalType(aType) { - if (aType in TYPE_ALIASES) - return TYPE_ALIASES[aType]; - return aType; -} - -function getManifestFileForDir(aDir) { - let file = aDir.clone(); - file.append(FILE_RDF_MANIFEST); - if (file.exists() && file.isFile()) - return file; - file.leafName = FILE_WEB_MANIFEST; - if (file.exists() && file.isFile()) - return file; - return null; -} - -function getManifestEntryForZipReader(aZipReader) { - if (aZipReader.hasEntry(FILE_RDF_MANIFEST)) - return FILE_RDF_MANIFEST; - if (aZipReader.hasEntry(FILE_WEB_MANIFEST)) - return FILE_WEB_MANIFEST; - return null; -} - -/** - * Converts a list of API types to a list of API types and any aliases for those - * types. - * - * @param aTypes - * An array of types or null for all types - * @return an array of types or null for all types - */ -function getAllAliasesForTypes(aTypes) { - if (!aTypes) - return null; - - // Build a set of all requested types and their aliases - let typeset = new Set(aTypes); - - for (let alias of Object.keys(TYPE_ALIASES)) { - // Ignore any requested internal types - typeset.delete(alias); - - // Add any alias for the internal type - if (typeset.has(TYPE_ALIASES[alias])) - typeset.add(alias); - } - - return [...typeset]; -} - -/** * Converts an RDF literal, resource or integer into a string. * * @param aLiteral @@ -928,128 +722,6 @@ function getRDFProperty(aDs, aResource, aProperty) { } /** - * Reads an AddonInternal object from a manifest stream. - * - * @param aUri - * A |file:| or |jar:| URL for the manifest - * @return an AddonInternal object - * @throws if the install manifest in the stream is corrupt or could not - * be read - */ -var loadManifestFromWebManifest = Task.async(function*(aUri) { - // We're passed the URI for the manifest file. Get the URI for its - // parent directory. - let uri = NetUtil.newURI("./", null, aUri); - - let extension = new ExtensionData(uri); - - let manifest = yield extension.readManifest(); - - // Read the list of available locales, and pre-load messages for - // all locales. - let locales = yield extension.initAllLocales(); - - // If there were any errors loading the extension, bail out now. - if (extension.errors.length) - throw new Error("Extension is invalid"); - - let bss = (manifest.browser_specific_settings && manifest.browser_specific_settings.gecko) - || (manifest.applications && manifest.applications.gecko) || {}; - if (manifest.browser_specific_settings && manifest.applications) { - logger.warn("Ignoring applications property in manifest"); - } - - // A * is illegal in strict_min_version - if (bss.strict_min_version && bss.strict_min_version.split(".").some(part => part == "*")) { - throw new Error("The use of '*' in strict_min_version is invalid"); - } - - let addon = new AddonInternal(); - addon.id = bss.id; - addon.version = manifest.version; - addon.type = "webextension"; - addon.unpack = false; - addon.strictCompatibility = true; - addon.bootstrap = true; - addon.hasBinaryComponents = false; - addon.multiprocessCompatible = true; - addon.internalName = null; - addon.updateURL = bss.update_url; - addon.updateKey = null; - addon.optionsURL = null; - addon.optionsType = null; - addon.aboutURL = null; - addon.dependencies = Object.freeze(Array.from(extension.dependencies)); - - if (manifest.options_ui) { - // Store just the relative path here, the AddonWrapper getURL - // wrapper maps this to a full URL. - addon.optionsURL = manifest.options_ui.page; - if (manifest.options_ui.open_in_tab) - addon.optionsType = AddonManager.OPTIONS_TYPE_TAB; - else - addon.optionsType = AddonManager.OPTIONS_TYPE_INLINE_BROWSER; - } - - // WebExtensions don't use iconURLs - addon.iconURL = null; - addon.icon64URL = null; - addon.icons = manifest.icons || {}; - - addon.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DEFAULT; - - function getLocale(aLocale) { - // Use the raw manifest, here, since we need values with their - // localization placeholders still in place. - let rawManifest = extension.rawManifest; - - // As a convenience, allow author to be set if its a string bug 1313567. - let creator = typeof(rawManifest.author) === 'string' ? rawManifest.author : null; - let homepageURL = rawManifest.homepage_url; - - // Allow developer to override creator and homepage_url. - if (rawManifest.developer) { - if (rawManifest.developer.name) { - creator = rawManifest.developer.name; - } - if (rawManifest.developer.url) { - homepageURL = rawManifest.developer.url; - } - } - - let result = { - name: extension.localize(rawManifest.name, aLocale), - description: extension.localize(rawManifest.description, aLocale), - creator: extension.localize(creator, aLocale), - homepageURL: extension.localize(homepageURL, aLocale), - - developers: null, - translators: null, - contributors: null, - locales: [aLocale], - }; - return result; - } - - addon.defaultLocale = getLocale(extension.defaultLocale); - addon.locales = Array.from(locales.keys(), getLocale); - - delete addon.defaultLocale.locales; - - addon.targetApplications = [{ - id: TOOLKIT_ID, - minVersion: bss.strict_min_version, - maxVersion: bss.strict_max_version, - }]; - - addon.targetPlatforms = []; - addon.userDisabled = false; - addon.softDisabled = addon.blocklistState == Blocklist.STATE_SOFTBLOCKED; - - return addon; -}); - -/** * Reads an AddonInternal object from an RDF stream. * * @param aUri @@ -1060,7 +732,7 @@ var loadManifestFromWebManifest = Task.async(function*(aUri) { * @throws if the install manifest in the RDF stream is corrupt or could not * be read */ -let loadManifestFromRDF = Task.async(function*(aUri, aStream) { +function loadManifestFromRDF(aUri, aStream) { function getPropertyArray(aDs, aSource, aProperty) { let values = []; let targets = aDs.GetTargets(aSource, EM_R(aProperty), true); @@ -1112,17 +784,17 @@ let loadManifestFromRDF = Task.async(function*(aUri, aStream) { } } - for (let prop of PROP_LOCALE_SINGLE) { - locale[prop] = getRDFProperty(aDs, aSource, prop); - } + PROP_LOCALE_SINGLE.forEach(function(aProp) { + locale[aProp] = getRDFProperty(aDs, aSource, aProp); + }); - for (let prop of PROP_LOCALE_MULTI) { + PROP_LOCALE_MULTI.forEach(function(aProp) { // Don't store empty arrays let props = getPropertyArray(aDs, aSource, - prop.substring(0, prop.length - 1)); + aProp.substring(0, aProp.length - 1)); if (props.length > 0) - locale[prop] = props; - } + locale[aProp] = props; + }); return locale; } @@ -1158,9 +830,9 @@ let loadManifestFromRDF = Task.async(function*(aUri, aStream) { let root = gRDF.GetResource(RDFURI_INSTALL_MANIFEST_ROOT); let addon = new AddonInternal(); - for (let prop of PROP_METADATA) { - addon[prop] = getRDFProperty(ds, root, prop); - } + PROP_METADATA.forEach(function(aProp) { + addon[aProp] = getRDFProperty(ds, root, aProp); + }); addon.unpack = getRDFProperty(ds, root, "unpack") == "true"; if (!addon.type) { @@ -1195,13 +867,7 @@ let loadManifestFromRDF = Task.async(function*(aUri, aStream) { // Only read these properties for extensions. if (addon.type == "extension") { addon.bootstrap = getRDFProperty(ds, root, "bootstrap") == "true"; - - let mpcValue = getRDFProperty(ds, root, "multiprocessCompatible"); - addon.multiprocessCompatible = mpcValue == "true"; - addon.mpcOptedOut = mpcValue == "false"; - - addon.hasEmbeddedWebExtension = getRDFProperty(ds, root, "hasEmbeddedWebExtension") == "true"; - + addon.multiprocessCompatible = getRDFProperty(ds, root, "multiprocessCompatible") == "true"; if (addon.optionsType && addon.optionsType != AddonManager.OPTIONS_TYPE_DIALOG && addon.optionsType != AddonManager.OPTIONS_TYPE_INLINE && @@ -1209,19 +875,6 @@ let loadManifestFromRDF = Task.async(function*(aUri, aStream) { addon.optionsType != AddonManager.OPTIONS_TYPE_INLINE_INFO) { throw new Error("Install manifest specifies unknown type: " + addon.optionsType); } - - if (addon.hasEmbeddedWebExtension) { - let uri = NetUtil.newURI("webextension/manifest.json", null, aUri); - let embeddedAddon = yield loadManifestFromWebManifest(uri); - if (embeddedAddon.optionsURL) { - if (addon.optionsType || addon.optionsURL) - logger.warn(`Addon ${addon.id} specifies optionsType or optionsURL ` + - `in both install.rdf and manifest.json`); - - addon.optionsURL = embeddedAddon.optionsURL; - addon.optionsType = embeddedAddon.optionsType; - } - } } else { // Some add-on types are always restartless. @@ -1254,24 +907,15 @@ let loadManifestFromRDF = Task.async(function*(aUri, aStream) { addon.locales.push(locale); } - let dependencies = new Set(); - targets = ds.GetTargets(root, EM_R("dependency"), true); - while (targets.hasMoreElements()) { - let target = targets.getNext().QueryInterface(Ci.nsIRDFResource); - let id = getRDFProperty(ds, target, "id"); - dependencies.add(id); - } - addon.dependencies = Object.freeze(Array.from(dependencies)); - let seenApplications = []; addon.targetApplications = []; targets = ds.GetTargets(root, EM_R("targetApplication"), true); while (targets.hasMoreElements()) { let target = targets.getNext().QueryInterface(Ci.nsIRDFResource); let targetAppInfo = {}; - for (let prop of PROP_TARGETAPP) { - targetAppInfo[prop] = getRDFProperty(ds, target, prop); - } + PROP_TARGETAPP.forEach(function(aProp) { + targetAppInfo[aProp] = getRDFProperty(ds, target, aProp); + }); if (!targetAppInfo.id || !targetAppInfo.minVersion || !targetAppInfo.maxVersion) { logger.warn("Ignoring invalid targetApplication entry in install manifest"); @@ -1290,23 +934,23 @@ let loadManifestFromRDF = Task.async(function*(aUri, aStream) { // the RDF service coalesces them for us. let targetPlatforms = getPropertyArray(ds, root, "targetPlatform"); addon.targetPlatforms = []; - for (let targetPlatform of targetPlatforms) { + targetPlatforms.forEach(function(aPlatform) { let platform = { os: null, abi: null }; - let pos = targetPlatform.indexOf("_"); + let pos = aPlatform.indexOf("_"); if (pos != -1) { - platform.os = targetPlatform.substring(0, pos); - platform.abi = targetPlatform.substring(pos + 1); + platform.os = aPlatform.substring(0, pos); + platform.abi = aPlatform.substring(pos + 1); } else { - platform.os = targetPlatform; + platform.os = aPlatform; } addon.targetPlatforms.push(platform); - } + }); // A theme's userDisabled value is true if the theme is not the selected skin // or if there is an active lightweight theme. We ignore whether softblocking @@ -1315,16 +959,16 @@ let loadManifestFromRDF = Task.async(function*(aUri, aStream) { addon.userDisabled = !!LightweightThemeManager.currentTheme || addon.internalName != XPIProvider.selectedSkin; } + // Experiments are disabled by default. It is up to the Experiments Manager + // to enable them (it drives installation). else if (addon.type == "experiment") { - // Experiments are disabled by default. It is up to the Experiments Manager - // to enable them (it drives installation). addon.userDisabled = true; } else { addon.userDisabled = false; + addon.softDisabled = addon.blocklistState == Blocklist.STATE_SOFTBLOCKED; } - addon.softDisabled = addon.blocklistState == Blocklist.STATE_SOFTBLOCKED; addon.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DEFAULT; // Experiments are managed and updated through an external "experiments @@ -1333,49 +977,23 @@ let loadManifestFromRDF = Task.async(function*(aUri, aStream) { addon.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DISABLE; addon.updateURL = null; addon.updateKey = null; + + addon.targetApplications = []; + addon.targetPlatforms = []; } - // icons will be filled by the calling function - addon.icons = {}; + // Load the storage service before NSS (nsIRandomGenerator), + // to avoid a SQLite initialization error (bug 717904). + let storage = Services.storage; - return addon; -}); - -function defineSyncGUID(aAddon) { - // Define .syncGUID as a lazy property which is also settable - Object.defineProperty(aAddon, "syncGUID", { - get: () => { - // Generate random GUID used for Sync. - let guid = Cc["@mozilla.org/uuid-generator;1"] - .getService(Ci.nsIUUIDGenerator) - .generateUUID().toString(); - - delete aAddon.syncGUID; - aAddon.syncGUID = guid; - return guid; - }, - set: (val) => { - delete aAddon.syncGUID; - aAddon.syncGUID = val; - }, - configurable: true, - enumerable: true, - }); -} + // Generate random GUID used for Sync. + // This was lifted from util.js:makeGUID() from services-sync. + let guid = Cc["@mozilla.org/uuid-generator;1"] + .getService(Ci.nsIUUIDGenerator) + .generateUUID().toString(); + addon.syncGUID = guid; -// Generate a unique ID based on the path to this temporary add-on location. -function generateTemporaryInstallID(aFile) { - const hasher = Cc["@mozilla.org/security/hash;1"] - .createInstance(Ci.nsICryptoHash); - hasher.init(hasher.SHA1); - const data = new TextEncoder().encode(aFile.path); - // Make it so this ID cannot be guessed. - const sess = TEMP_INSTALL_ID_GEN_SESSION; - hasher.update(sess, sess.length); - hasher.update(data, data.length); - let id = `${getHashStringForCrypto(hasher)}@temporary-addon`; - logger.info(`Generated temp id ${id} (${sess.join("")}) for ${aFile.path}`); - return id; + return addon; } /** @@ -1386,7 +1004,7 @@ function generateTemporaryInstallID(aFile) { * @return an AddonInternal object * @throws if the directory does not contain a valid install manifest */ -var loadManifestFromDir = Task.async(function*(aDir, aInstallLocation) { +function loadManifestFromDir(aDir) { function getFileSize(aFile) { if (aFile.isSymlink()) return 0; @@ -1403,76 +1021,38 @@ var loadManifestFromDir = Task.async(function*(aDir, aInstallLocation) { return size; } - function* loadFromRDF(aUri) { - let fis = Cc["@mozilla.org/network/file-input-stream;1"]. - createInstance(Ci.nsIFileInputStream); - fis.init(aUri.file, -1, -1, false); - let bis = Cc["@mozilla.org/network/buffered-input-stream;1"]. - createInstance(Ci.nsIBufferedInputStream); - bis.init(fis, 4096); - try { - var addon = yield loadManifestFromRDF(aUri, bis); - } finally { - bis.close(); - fis.close(); - } - - let iconFile = aDir.clone(); - iconFile.append("icon.png"); - - if (iconFile.exists()) { - addon.icons[32] = "icon.png"; - addon.icons[48] = "icon.png"; - } + let file = aDir.clone(); + file.append(FILE_INSTALL_MANIFEST); + if (!file.exists() || !file.isFile()) + throw new Error("Directory " + aDir.path + " does not contain a valid " + + "install manifest"); - let icon64File = aDir.clone(); - icon64File.append("icon64.png"); + let fis = Cc["@mozilla.org/network/file-input-stream;1"]. + createInstance(Ci.nsIFileInputStream); + fis.init(file, -1, -1, false); + let bis = Cc["@mozilla.org/network/buffered-input-stream;1"]. + createInstance(Ci.nsIBufferedInputStream); + bis.init(fis, 4096); - if (icon64File.exists()) { - addon.icons[64] = "icon64.png"; - } + try { + let addon = loadManifestFromRDF(Services.io.newFileURI(file), bis); + addon._sourceBundle = aDir.clone(); + addon.size = getFileSize(aDir); - let file = aDir.clone(); + file = aDir.clone(); file.append("chrome.manifest"); let chromeManifest = ChromeManifestParser.parseSync(Services.io.newFileURI(file)); addon.hasBinaryComponents = ChromeManifestParser.hasType(chromeManifest, "binary-component"); - return addon; - } - let file = getManifestFileForDir(aDir); - if (!file) { - throw new Error("Directory " + aDir.path + " does not contain a valid " + - "install manifest"); + addon.appDisabled = !isUsableAddon(addon); + return addon; } - - let uri = Services.io.newFileURI(file).QueryInterface(Ci.nsIFileURL); - - let addon; - if (file.leafName == FILE_WEB_MANIFEST) { - addon = yield loadManifestFromWebManifest(uri); - if (!addon.id) { - if (aInstallLocation == TemporaryInstallLocation) { - addon.id = generateTemporaryInstallID(aDir); - } else { - addon.id = aDir.leafName; - } - } - } else { - addon = yield loadFromRDF(uri); + finally { + bis.close(); + fis.close(); } - - addon._sourceBundle = aDir.clone(); - addon._installLocation = aInstallLocation; - addon.size = getFileSize(aDir); - addon.signedState = yield verifyDirSignedState(aDir, addon) - .then(({signedState}) => signedState); - addon.appDisabled = !isUsableAddon(addon); - - defineSyncGUID(addon); - - return addon; -}); +} /** * Loads an AddonInternal object from an nsIZipReader for an add-on. @@ -1480,84 +1060,72 @@ var loadManifestFromDir = Task.async(function*(aDir, aInstallLocation) { * @param aZipReader * An open nsIZipReader for the add-on's files * @return an AddonInternal object - * @throws if the XPI file does not contain a valid install manifest + * @throws if the XPI file does not contain a valid install manifest. + * Throws with |webext:true| if a WebExtension manifest was found + * to distinguish between WebExtensions and corrupt files. */ -var loadManifestFromZipReader = Task.async(function*(aZipReader, aInstallLocation) { - function* loadFromRDF(aUri) { - let zis = aZipReader.getInputStream(entry); - let bis = Cc["@mozilla.org/network/buffered-input-stream;1"]. - createInstance(Ci.nsIBufferedInputStream); - bis.init(zis, 4096); +function loadManifestFromZipReader(aZipReader) { + let zis; + try { + zis = aZipReader.getInputStream(FILE_INSTALL_MANIFEST); + } catch (e) { + // We're going to throw here, but depending on whether we have a + // WebExtension manifest in the XPI, we'll throw with the webext flag. try { - var addon = yield loadManifestFromRDF(aUri, bis); - } finally { - bis.close(); - zis.close(); + let zws = aZipReader.getInputStream(FILE_WEBEXT_MANIFEST); + zws.close(); + } catch(e2) { + // We have neither an install manifest nor a WebExtension manifest; + // this means the extension file has a structural problem. + // Just pass the original error up the chain in that case. + throw { + name: e.name, + message: e.message + }; } + // If we get here, we have a WebExtension manifest but no install + // manifest. Pass the error up the chain with the webext flag. + throw { + name: e.name, + message: e.message, + webext: true + }; + } + + // We found an install manifest, so it's either a regular or hybrid + // extension. Continue processing. + let bis = Cc["@mozilla.org/network/buffered-input-stream;1"]. + createInstance(Ci.nsIBufferedInputStream); + bis.init(zis, 4096); - if (aZipReader.hasEntry("icon.png")) { - addon.icons[32] = "icon.png"; - addon.icons[48] = "icon.png"; - } + try { + let uri = buildJarURI(aZipReader.file, FILE_INSTALL_MANIFEST); + let addon = loadManifestFromRDF(uri, bis); + addon._sourceBundle = aZipReader.file; - if (aZipReader.hasEntry("icon64.png")) { - addon.icons[64] = "icon64.png"; - } + addon.size = 0; + let entries = aZipReader.findEntries(null); + while (entries.hasMore()) + addon.size += aZipReader.getEntry(entries.getNext()).realSize; // Binary components can only be loaded from unpacked addons. if (addon.unpack) { - let uri = buildJarURI(aZipReader.file, "chrome.manifest"); + uri = buildJarURI(aZipReader.file, "chrome.manifest"); let chromeManifest = ChromeManifestParser.parseSync(uri); addon.hasBinaryComponents = ChromeManifestParser.hasType(chromeManifest, "binary-component"); } else { addon.hasBinaryComponents = false; } - + + addon.appDisabled = !isUsableAddon(addon); return addon; } - - let entry = getManifestEntryForZipReader(aZipReader); - if (!entry) { - throw new Error("File " + aZipReader.file.path + " does not contain a valid " + - "install manifest"); - } - - let uri = buildJarURI(aZipReader.file, entry); - - let isWebExtension = (entry == FILE_WEB_MANIFEST); - - let addon = isWebExtension ? - yield loadManifestFromWebManifest(uri) : - yield loadFromRDF(uri); - - addon._sourceBundle = aZipReader.file; - addon._installLocation = aInstallLocation; - - addon.size = 0; - let entries = aZipReader.findEntries(null); - while (entries.hasMore()) - addon.size += aZipReader.getEntry(entries.getNext()).realSize; - - let {signedState, cert} = yield verifyZipSignedState(aZipReader.file, addon); - addon.signedState = signedState; - if (isWebExtension && !addon.id) { - if (cert) { - addon.id = cert.commonName; - if (!gIDTest.test(addon.id)) { - throw new Error(`Webextension is signed with an invalid id (${addon.id})`); - } - } - if (!addon.id && aInstallLocation == TemporaryInstallLocation) { - addon.id = generateTemporaryInstallID(aZipReader.file); - } + finally { + bis.close(); + zis.close(); } - addon.appDisabled = !isUsableAddon(addon); - - defineSyncGUID(addon); - - return addon; -}); +} /** * Loads an AddonInternal object from an add-on in an XPI file. @@ -1567,53 +1135,24 @@ var loadManifestFromZipReader = Task.async(function*(aZipReader, aInstallLocatio * @return an AddonInternal object * @throws if the XPI file does not contain a valid install manifest */ -var loadManifestFromZipFile = Task.async(function*(aXPIFile, aInstallLocation) { +function loadManifestFromZipFile(aXPIFile) { let zipReader = Cc["@mozilla.org/libjar/zip-reader;1"]. createInstance(Ci.nsIZipReader); try { zipReader.open(aXPIFile); - // Can't return this promise because that will make us close the zip reader - // before it has finished loading the manifest. Wait for the result and then - // return. - let manifest = yield loadManifestFromZipReader(zipReader, aInstallLocation); - return manifest; + return loadManifestFromZipReader(zipReader); } finally { zipReader.close(); } -}); - -function loadManifestFromFile(aFile, aInstallLocation) { - if (aFile.isFile()) - return loadManifestFromZipFile(aFile, aInstallLocation); - return loadManifestFromDir(aFile, aInstallLocation); } -/** - * A synchronous method for loading an add-on's manifest. This should only ever - * be used during startup or a sync load of the add-ons DB - */ -function syncLoadManifestFromFile(aFile, aInstallLocation) { - let success = undefined; - let result = null; - - loadManifestFromFile(aFile, aInstallLocation).then(val => { - success = true; - result = val; - }, val => { - success = false; - result = val - }); - - let thread = Services.tm.currentThread; - - while (success === undefined) - thread.processNextEvent(true); - - if (!success) - throw result; - return result; +function loadManifestFromFile(aFile) { + if (aFile.isFile()) + return loadManifestFromZipFile(aFile); + else + return loadManifestFromDir(aFile); } /** @@ -1632,9 +1171,11 @@ function syncLoadManifestFromFile(aFile, aInstallLocation) { function getURIForResourceInFile(aFile, aPath) { if (aFile.isDirectory()) { let resource = aFile.clone(); - if (aPath) - aPath.split("/").forEach(part => resource.append(part)); - + if (aPath) { + aPath.split("/").forEach(function(aPart) { + resource.append(aPart); + }); + } return NetUtil.newURI(resource); } @@ -1664,16 +1205,13 @@ function buildJarURI(aJarfile, aPath) { */ function flushJarCache(aJarFile) { Services.obs.notifyObservers(aJarFile, "flush-cache-entry", null); - Services.mm.broadcastAsyncMessage(MSG_JAR_FLUSH, aJarFile.path); + Cc["@mozilla.org/globalmessagemanager;1"].getService(Ci.nsIMessageBroadcaster) + .broadcastAsyncMessage(MSG_JAR_FLUSH, aJarFile.path); } -function flushChromeCaches() { +function flushStartupCache() { // Init this, so it will get the notification. Services.obs.notifyObservers(null, "startupcache-invalidate", null); - // Flush message manager cached scripts - Services.obs.notifyObservers(null, "message-manager-flush-caches", null); - // Also dispatch this event to child processes - Services.mm.broadcastAsyncMessage(MSG_MESSAGE_MANAGER_CACHES_FLUSH, null); } /** @@ -1724,186 +1262,6 @@ function verifyZipSigning(aZip, aCertificate) { } /** - * Returns the signedState for a given return code and certificate by verifying - * it against the expected ID. - */ -function getSignedStatus(aRv, aCert, aAddonID) { - let expectedCommonName = aAddonID; - if (aAddonID && aAddonID.length > 64) { - let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]. - createInstance(Ci.nsIScriptableUnicodeConverter); - converter.charset = "UTF-8"; - let data = converter.convertToByteArray(aAddonID, {}); - - let crypto = Cc["@mozilla.org/security/hash;1"]. - createInstance(Ci.nsICryptoHash); - crypto.init(Ci.nsICryptoHash.SHA256); - crypto.update(data, data.length); - expectedCommonName = getHashStringForCrypto(crypto); - } - - switch (aRv) { - case Cr.NS_OK: - if (expectedCommonName && expectedCommonName != aCert.commonName) - return AddonManager.SIGNEDSTATE_BROKEN; - - let hotfixID = Preferences.get(PREF_EM_HOTFIX_ID, undefined); - if (hotfixID && hotfixID == aAddonID && Preferences.get(PREF_EM_CERT_CHECKATTRIBUTES, false)) { - // The hotfix add-on has some more rigorous certificate checks - try { - CertUtils.validateCert(aCert, - CertUtils.readCertPrefs(PREF_EM_HOTFIX_CERTS)); - } - catch (e) { - logger.warn("The hotfix add-on was not signed by the expected " + - "certificate and so will not be installed.", e); - return AddonManager.SIGNEDSTATE_BROKEN; - } - } - - if (aCert.organizationalUnit == "Mozilla Components") - return AddonManager.SIGNEDSTATE_SYSTEM; - - return /preliminary/i.test(aCert.organizationalUnit) - ? AddonManager.SIGNEDSTATE_PRELIMINARY - : AddonManager.SIGNEDSTATE_SIGNED; - case Cr.NS_ERROR_SIGNED_JAR_NOT_SIGNED: - return AddonManager.SIGNEDSTATE_MISSING; - case Cr.NS_ERROR_SIGNED_JAR_MANIFEST_INVALID: - case Cr.NS_ERROR_SIGNED_JAR_ENTRY_INVALID: - case Cr.NS_ERROR_SIGNED_JAR_ENTRY_MISSING: - case Cr.NS_ERROR_SIGNED_JAR_ENTRY_TOO_LARGE: - case Cr.NS_ERROR_SIGNED_JAR_UNSIGNED_ENTRY: - case Cr.NS_ERROR_SIGNED_JAR_MODIFIED_ENTRY: - return AddonManager.SIGNEDSTATE_BROKEN; - default: - // Any other error indicates that either the add-on isn't signed or it - // is signed by a signature that doesn't chain to the trusted root. - return AddonManager.SIGNEDSTATE_UNKNOWN; - } -} - -function shouldVerifySignedState(aAddon) { - // Updated system add-ons should always have their signature checked - if (aAddon._installLocation.name == KEY_APP_SYSTEM_ADDONS) - return true; - - // We don't care about signatures for default system add-ons - if (aAddon._installLocation.name == KEY_APP_SYSTEM_DEFAULTS) - return false; - - // Hotfixes should always have their signature checked - let hotfixID = Preferences.get(PREF_EM_HOTFIX_ID, undefined); - if (hotfixID && aAddon.id == hotfixID) - return true; - - // Otherwise only check signatures if signing is enabled and the add-on is one - // of the signed types. - return ADDON_SIGNING && SIGNED_TYPES.has(aAddon.type); -} - -let gCertDB = Cc["@mozilla.org/security/x509certdb;1"] - .getService(Ci.nsIX509CertDB); - -/** - * Verifies that a zip file's contents are all correctly signed by an - * AMO-issued certificate - * - * @param aFile - * the xpi file to check - * @param aAddon - * the add-on object to verify - * @return a Promise that resolves to an object with properties: - * signedState: an AddonManager.SIGNEDSTATE_* constant - * cert: an nsIX509Cert - */ -function verifyZipSignedState(aFile, aAddon) { - if (!shouldVerifySignedState(aAddon)) - return Promise.resolve({ - signedState: AddonManager.SIGNEDSTATE_NOT_REQUIRED, - cert: null - }); - - let root = Ci.nsIX509CertDB.AddonsPublicRoot; - if (!REQUIRE_SIGNING && Preferences.get(PREF_XPI_SIGNATURES_DEV_ROOT, false)) - root = Ci.nsIX509CertDB.AddonsStageRoot; - - return new Promise(resolve => { - let callback = { - openSignedAppFileFinished: function(aRv, aZipReader, aCert) { - if (aZipReader) - aZipReader.close(); - resolve({ - signedState: getSignedStatus(aRv, aCert, aAddon.id), - cert: aCert - }); - } - }; - // This allows the certificate DB to get the raw JS callback object so the - // test code can pass through objects that XPConnect would reject. - callback.wrappedJSObject = callback; - - gCertDB.openSignedAppFileAsync(root, aFile, callback); - }); -} - -/** - * Verifies that a directory's contents are all correctly signed by an - * AMO-issued certificate - * - * @param aDir - * the directory to check - * @param aAddon - * the add-on object to verify - * @return a Promise that resolves to an object with properties: - * signedState: an AddonManager.SIGNEDSTATE_* constant - * cert: an nsIX509Cert - */ -function verifyDirSignedState(aDir, aAddon) { - if (!shouldVerifySignedState(aAddon)) - return Promise.resolve({ - signedState: AddonManager.SIGNEDSTATE_NOT_REQUIRED, - cert: null, - }); - - let root = Ci.nsIX509CertDB.AddonsPublicRoot; - if (!REQUIRE_SIGNING && Preferences.get(PREF_XPI_SIGNATURES_DEV_ROOT, false)) - root = Ci.nsIX509CertDB.AddonsStageRoot; - - return new Promise(resolve => { - let callback = { - verifySignedDirectoryFinished: function(aRv, aCert) { - resolve({ - signedState: getSignedStatus(aRv, aCert, aAddon.id), - cert: null, - }); - } - }; - // This allows the certificate DB to get the raw JS callback object so the - // test code can pass through objects that XPConnect would reject. - callback.wrappedJSObject = callback; - - gCertDB.verifySignedDirectoryAsync(root, aDir, callback); - }); -} - -/** - * Verifies that a bundle's contents are all correctly signed by an - * AMO-issued certificate - * - * @param aBundle - * the nsIFile for the bundle to check, either a directory or zip file - * @param aAddon - * the add-on object to verify - * @return a Promise that resolves to an AddonManager.SIGNEDSTATE_* constant. - */ -function verifyBundleSignedState(aBundle, aAddon) { - let promise = aBundle.isFile() ? verifyZipSignedState(aBundle, aAddon) - : verifyDirSignedState(aBundle, aAddon); - return promise.then(({signedState}) => signedState); -} - -/** * Replaces %...% strings in an addon url (update and updateInfo) with * appropriate values. * @@ -1947,7 +1305,7 @@ function escapeAddonURI(aAddon, aUri, aUpdateType, aAppVersion) } function removeAsync(aFile) { - return Task.spawn(function*() { + return Task.spawn(function () { let info = null; try { info = yield OS.File.stat(aFile.path); @@ -1956,9 +1314,7 @@ function removeAsync(aFile) { else yield OS.File.remove(aFile.path); } - catch (e) { - if (!(e instanceof OS.File.Error) || ! e.becauseNoSuchFile) - throw e; + catch (e if e instanceof OS.File.Error && e.becauseNoSuchFile) { // The file has already gone away return; } @@ -1997,7 +1353,7 @@ function recursiveRemove(aFile) { return; } catch (e) { - if (!aFile.isDirectory() || aFile.isSymlink()) { + if (!aFile.isDirectory()) { logger.error("Failed to remove file " + aFile.path, e); throw e; } @@ -2078,7 +1434,7 @@ function getDirectoryEntries(aDir, aSortEntries) { entries.push(dirEnum.nextFile); if (aSortEntries) { - entries.sort(function(a, b) { + entries.sort(function sortDirEntries(a, b) { return a.path > b.path ? -1 : 1; }); } @@ -2097,16 +1453,21 @@ function getDirectoryEntries(aDir, aSortEntries) { } /** - * Record a bit of per-addon telemetry - * @param aAddon the addon to record + * Wraps a function in an exception handler to protect against exceptions inside callbacks + * @param aFunction function(args...) + * @return function(args...), a function that takes the same arguments as aFunction + * and returns the same result unless aFunction throws, in which case it logs + * a warning and returns undefined. */ -function recordAddonTelemetry(aAddon) { - let locale = aAddon.defaultLocale; - if (locale) { - if (locale.name) - XPIProvider.setTelemetry(aAddon.id, "name", locale.name); - if (locale.creator) - XPIProvider.setTelemetry(aAddon.id, "creator", locale.creator); +function makeSafe(aFunction) { + return function(...aArgs) { + try { + return aFunction(...aArgs); + } + catch(ex) { + logger.warn("XPIProvider callback failed", ex); + } + return undefined; } } @@ -2162,18 +1523,20 @@ XPIState.prototype = { logger.debug('getModTime: Recursive scan of ' + aId); let [modFile, modTime, items] = recursiveLastModifiedTime(aFile); XPIProvider._mostRecentlyModifiedFile[aId] = modFile; - XPIProvider.setTelemetry(aId, "scan_items", items); if (modTime != this.scanTime) { this.scanTime = modTime; changed = true; } } - // if the add-on is disabled, modified time is the install manifest time, if - // any. If no manifest exists, we assume this is a packed .xpi and use + // if the add-on is disabled, modified time is the install.rdf time, if any. + // If {path}/install.rdf doesn't exist, we assume this is a packed .xpi and use // the time stamp of {path} try { - // Get the install manifest update time, if any. - let maniFile = getManifestFileForDir(aFile); + // Get the install.rdf update time, if any. + // XXX This will eventually also need to check for package.json or whatever + // the new manifest is named. + let maniFile = aFile.clone(); + maniFile.append(FILE_INSTALL_MANIFEST); if (!(aId in XPIProvider._mostRecentlyModifiedFile)) { XPIProvider._mostRecentlyModifiedFile[aId] = maniFile.leafName; } @@ -2197,9 +1560,6 @@ XPIState.prototype = { this.scanTime = 0; } } - // Record duration of file-modified check - XPIProvider.setTelemetry(aId, "scan_MS", Math.round(Cu.now() - scanStarted)); - return changed; }, @@ -2295,7 +1655,7 @@ this.XPIStates = { for (let location of XPIProvider.installLocations) { // The list of add-on like file/directory names in the install location. - let addons = location.getAddonLocations(); + let addons = location.addonLocations; // The results of scanning this location. let foundAddons = new SerializableMap(); @@ -2307,7 +1667,9 @@ this.XPIStates = { delete oldState[location.name]; } - for (let [id, file] of addons) { + for (let file of addons) { + let id = location.getIDForLocation(file); + if (!(id in locState)) { logger.debug("New add-on ${id} in ${location}", {id: id, location: location.name}); let xpiState = new XPIState({d: file.persistentDescriptor}); @@ -2327,12 +1689,8 @@ this.XPIStates = { if (changed) { logger.debug("Changed add-on ${id} in ${location}", {id: id, location: location.name}); } - else { - logger.debug("Existing add-on ${id} in ${location}", {id: id, location: location.name}); - } foundAddons.set(id, xpiState); } - XPIProvider.setTelemetry(id, "location", location.name); } // Anything left behind in oldState was removed from the file system. @@ -2415,7 +1773,6 @@ this.XPIStates = { let xpiState = new XPIState({d: aAddon.descriptor}); location.set(aAddon.id, xpiState); xpiState.syncWithDB(aAddon, true); - XPIProvider.setTelemetry(aAddon.id, "location", aAddon.location); }, /** @@ -2447,9 +1804,7 @@ this.XPIStates = { }; this.XPIProvider = { - get name() { - return "XPIProvider"; - }, + get name() "XPIProvider", // An array of known install locations installLocations: null, @@ -2471,8 +1826,8 @@ this.XPIProvider = { minCompatiblePlatformVersion: null, // A dictionary of the file descriptors for bootstrappable add-ons by ID bootstrappedAddons: {}, - // A Map of active addons to their bootstrapScope by ID - activeAddons: new Map(), + // A dictionary of JS scopes of loaded bootstrappable add-ons by ID + bootstrapScopes: {}, // True if the platform could have activated extensions extensionsActive: false, // True if all of the add-ons found during startup were installed in the @@ -2487,6 +1842,8 @@ this.XPIProvider = { _mostRecentlyModifiedFile: {}, // Per-addon telemetry information _telemetryDetails: {}, + // Experiments are disabled by default. Track ones that are locally enabled. + _enabledExperiments: null, // A Map from an add-on install to its ID _addonFileMap: new Map(), // Flag to know if ToolboxProcess.jsm has already been loaded by someone or not @@ -2494,62 +1851,14 @@ this.XPIProvider = { // Have we started shutting down bootstrap add-ons? _closing: false, - /** - * Returns an array of the add-on values in `bootstrappedAddons`, - * sorted so that all of an add-on's dependencies appear in the array - * before itself. - * - * @returns {Array<object>} - * A sorted array of add-on objects. Each value is a copy of the - * corresponding value in the `bootstrappedAddons` object, with an - * additional `id` property, which corresponds to the key in that - * object, which is the same as the add-ons ID. - */ - sortBootstrappedAddons: function() { - let addons = {}; - - // Sort the list of IDs so that the ordering is deterministic. - for (let id of Object.keys(this.bootstrappedAddons).sort()) { - addons[id] = Object.assign({id}, this.bootstrappedAddons[id]); - } - - let res = new Set(); - let seen = new Set(); - - let add = addon => { - seen.add(addon.id); - - for (let id of addon.dependencies || []) { - if (id in addons && !seen.has(id)) { - add(addons[id]); - } - } - - res.add(addon.id); - } - - Object.values(addons).forEach(add); - - return Array.from(res, id => addons[id]); - }, - - /* - * Set a value in the telemetry hash for a given ID - */ - setTelemetry: function(aId, aName, aValue) { - if (!this._telemetryDetails[aId]) - this._telemetryDetails[aId] = {}; - this._telemetryDetails[aId][aName] = aValue; - }, - // Keep track of in-progress operations that support cancel() _inProgress: [], - doing: function(aCancellable) { + doing: function XPI_doing(aCancellable) { this._inProgress.push(aCancellable); }, - done: function(aCancellable) { + done: function XPI_done(aCancellable) { let i = this._inProgress.indexOf(aCancellable); if (i != -1) { this._inProgress.splice(i, 1); @@ -2558,7 +1867,7 @@ this.XPIProvider = { return false; }, - cancelAll: function() { + cancelAll: function XPI_cancelAll() { // Cancelling one may alter _inProgress, so don't use a simple iterator while (this._inProgress.length > 0) { let c = this._inProgress.shift(); @@ -2578,7 +1887,7 @@ this.XPIProvider = { * will be still valid after an add-on gets disabled or uninstalled, as * consumers may still have URIs of (leaked) resources they want to map. */ - _addURIMapping: function(aID, aFile) { + _addURIMapping: function XPI__addURIMapping(aID, aFile) { logger.info("Mapping " + aID + " to " + aFile.path); this._addonFileMap.set(aID, aFile.path); @@ -2595,7 +1904,7 @@ this.XPIProvider = { * @return * resolved nsIFileURL */ - _resolveURIToFile: function(aURI) { + _resolveURIToFile: function XPI__resolveURIToFile(aURI) { switch (aURI.scheme) { case "jar": case "file": @@ -2663,7 +1972,7 @@ this.XPIProvider = { * The version of the platform last run with this profile or null * if it is a new profile or the version is unknown */ - startup: function(aAppChanged, aOldAppVersion, aOldPlatformVersion) { + startup: function XPI_startup(aAppChanged, aOldAppVersion, aOldPlatformVersion) { function addDirectoryInstallLocation(aName, aKey, aPaths, aScope, aLocked) { try { var dir = FileUtils.getDir(aKey, aPaths); @@ -2675,8 +1984,7 @@ this.XPIProvider = { } try { - var location = aLocked ? new DirectoryInstallLocation(aName, dir, aScope) - : new MutableDirectoryInstallLocation(aName, dir, aScope); + var location = new DirectoryInstallLocation(aName, dir, aScope, aLocked); } catch (e) { logger.warn("Failed to add directory install location " + aName, e); @@ -2687,28 +1995,6 @@ this.XPIProvider = { XPIProvider.installLocationsByName[location.name] = location; } - function addSystemAddonInstallLocation(aName, aKey, aPaths, aScope) { - try { - var dir = FileUtils.getDir(aKey, aPaths); - } - catch (e) { - // Some directories aren't defined on some platforms, ignore them - logger.debug("Skipping unavailable install location " + aName); - return; - } - - try { - var location = new SystemAddonInstallLocation(aName, dir, aScope, aAppChanged !== false); - } - catch (e) { - logger.warn("Failed to add system add-on install location " + aName, e); - return; - } - - XPIProvider.installLocations.push(location); - XPIProvider.installLocationsByName[location.name] = location; - } - function addRegistryInstallLocation(aName, aRootkey, aScope) { try { var location = new WinRegInstallLocation(aName, aRootkey, aScope); @@ -2727,15 +2013,15 @@ this.XPIProvider = { logger.debug("startup"); this.runPhase = XPI_STARTING; - this.installs = new Set(); + this.installs = []; this.installLocations = []; this.installLocationsByName = {}; // Hook for tests to detect when saving database at shutdown time fails this._shutdownError = null; // Clear this at startup for xpcshell test restarts this._telemetryDetails = {}; - // Register our details structure with AddonManager - AddonManagerPrivate.setTelemetryDetails("XPI", this._telemetryDetails); + // Clear the set of enabled experiments (experiments disabled by default). + this._enabledExperiments = new Set(); let hasRegistry = ("nsIWindowsRegKey" in Ci); @@ -2744,23 +2030,11 @@ this.XPIProvider = { // These must be in order of priority, highest to lowest, // for processFileChanges etc. to work - - XPIProvider.installLocations.push(TemporaryInstallLocation); - XPIProvider.installLocationsByName[TemporaryInstallLocation.name] = - TemporaryInstallLocation; - // The profile location is always enabled addDirectoryInstallLocation(KEY_APP_PROFILE, KEY_PROFILEDIR, [DIR_EXTENSIONS], AddonManager.SCOPE_PROFILE, false); - addSystemAddonInstallLocation(KEY_APP_SYSTEM_ADDONS, KEY_PROFILEDIR, - [DIR_SYSTEM_ADDONS], - AddonManager.SCOPE_PROFILE); - - addDirectoryInstallLocation(KEY_APP_SYSTEM_DEFAULTS, KEY_APP_FEATURES, - [], AddonManager.SCOPE_PROFILE, true); - if (enabledScopes & AddonManager.SCOPE_USER) { addDirectoryInstallLocation(KEY_APP_SYSTEM_USER, "XREUSysExt", [Services.appinfo.ID], @@ -2772,9 +2046,11 @@ this.XPIProvider = { } } - addDirectoryInstallLocation(KEY_APP_GLOBAL, KEY_ADDON_APP_DIR, - [DIR_EXTENSIONS], - AddonManager.SCOPE_APPLICATION, true); + if (enabledScopes & AddonManager.SCOPE_APPLICATION) { + addDirectoryInstallLocation(KEY_APP_GLOBAL, KEY_APPDIR, + [DIR_EXTENSIONS], + AddonManager.SCOPE_APPLICATION, true); + } if (enabledScopes & AddonManager.SCOPE_SYSTEM) { addDirectoryInstallLocation(KEY_APP_SYSTEM_SHARE, "XRESysSExtPD", @@ -2806,25 +2082,17 @@ this.XPIProvider = { Services.prefs.addObserver(PREF_EM_MIN_COMPAT_APP_VERSION, this, false); Services.prefs.addObserver(PREF_EM_MIN_COMPAT_PLATFORM_VERSION, this, false); - Services.prefs.addObserver(PREF_E10S_ADDON_BLOCKLIST, this, false); - Services.prefs.addObserver(PREF_E10S_ADDON_POLICY, this, false); - if (!REQUIRE_SIGNING) - Services.prefs.addObserver(PREF_XPI_SIGNATURES_REQUIRED, this, false); Services.obs.addObserver(this, NOTIFICATION_FLUSH_PERMISSIONS, false); - - // Cu.isModuleLoaded can fail here for external XUL apps where there is - // no chrome.manifest that defines resource://devtools. - if (ResProtocolHandler.hasSubstitution("devtools")) { - if (Cu.isModuleLoaded("resource://devtools/client/framework/ToolboxProcess.jsm")) { - // If BrowserToolboxProcess is already loaded, set the boolean to true - // and do whatever is needed - this._toolboxProcessLoaded = true; - BrowserToolboxProcess.on("connectionchange", - this.onDebugConnectionChange.bind(this)); - } else { - // Else, wait for it to load - Services.obs.addObserver(this, NOTIFICATION_TOOLBOXPROCESS_LOADED, false); - } + if (Cu.isModuleLoaded("resource://devtools/client/framework/ToolboxProcess.jsm")) { + // If BrowserToolboxProcess is already loaded, set the boolean to true + // and do whatever is needed + this._toolboxProcessLoaded = true; + BrowserToolboxProcess.on("connectionchange", + this.onDebugConnectionChange.bind(this)); + } + else { + // Else, wait for it to load + Services.obs.addObserver(this, NOTIFICATION_TOOLBOXPROCESS_LOADED, false); } let flushCaches = this.checkForChanges(aAppChanged, aOldAppVersion, @@ -2835,17 +2103,34 @@ this.XPIProvider = { AddonManagerPrivate.markProviderSafe(this); - if (aAppChanged && !this.allAppGlobal && - Preferences.get(PREF_EM_SHOW_MISMATCH_UI, true)) { - let addonsToUpdate = this.shouldForceUpdateCheck(aAppChanged); - if (addonsToUpdate) { - this.showUpgradeUI(addonsToUpdate); - flushCaches = true; + if (aAppChanged === undefined) { + // For new profiles we will never need to show the add-on selection UI + Services.prefs.setBoolPref(PREF_SHOWN_SELECTION_UI, true); + } + else if (aAppChanged && !this.allAppGlobal && + Preferences.get(PREF_EM_SHOW_MISMATCH_UI, true)) { + if (!Preferences.get(PREF_SHOWN_SELECTION_UI, false)) { + // Flip a flag to indicate that we interrupted startup with an interactive prompt + Services.startup.interrupted = true; + // This *must* be modal as it has to block startup. + var features = "chrome,centerscreen,dialog,titlebar,modal"; + Services.ww.openWindow(null, URI_EXTENSION_SELECT_DIALOG, "", features, null); + Services.prefs.setBoolPref(PREF_SHOWN_SELECTION_UI, true); + // Ensure any changes to the add-ons list are flushed to disk + Services.prefs.setBoolPref(PREF_PENDING_OPERATIONS, + !XPIDatabase.writeAddonsList()); + } + else { + let addonsToUpdate = this.shouldForceUpdateCheck(aAppChanged); + if (addonsToUpdate) { + this.showUpgradeUI(addonsToUpdate); + flushCaches = true; + } } } if (flushCaches) { - Services.obs.notifyObservers(null, "startupcache-invalidate", null); + flushStartupCache(); // UI displayed early in startup (like the compatibility UI) may have // caused us to cache parts of the skin or locale in memory. These must // be flushed to allow extension provided skins and locales to take full @@ -2871,23 +2156,22 @@ this.XPIProvider = { try { AddonManagerPrivate.recordTimestamp("XPI_bootstrap_addons_begin"); - - for (let addon of this.sortBootstrappedAddons()) { + for (let id in this.bootstrappedAddons) { try { let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); - file.persistentDescriptor = addon.descriptor; + file.persistentDescriptor = this.bootstrappedAddons[id].descriptor; let reason = BOOTSTRAP_REASONS.APP_STARTUP; // Eventually set INSTALLED reason when a bootstrap addon // is dropped in profile folder and automatically installed if (AddonManager.getStartupChanges(AddonManager.STARTUP_CHANGE_INSTALLED) - .indexOf(addon.id) !== -1) + .indexOf(id) !== -1) reason = BOOTSTRAP_REASONS.ADDON_INSTALL; - this.callBootstrapMethod(createAddonDetails(addon.id, addon), + this.callBootstrapMethod(createAddonDetails(id, this.bootstrappedAddons[id]), file, "startup", reason); } catch (e) { - logger.error("Failed to load bootstrap addon " + addon.id + " from " + - addon.descriptor, e); + logger.error("Failed to load bootstrap addon " + id + " from " + + this.bootstrappedAddons[id].descriptor, e); } } AddonManagerPrivate.recordTimestamp("XPI_bootstrap_addons_end"); @@ -2900,30 +2184,14 @@ this.XPIProvider = { // Let these shutdown a little earlier when they still have access to most // of XPCOM Services.obs.addObserver({ - observe: function(aSubject, aTopic, aData) { + observe: function shutdownObserver(aSubject, aTopic, aData) { XPIProvider._closing = true; - for (let addon of XPIProvider.sortBootstrappedAddons().reverse()) { - // If no scope has been loaded for this add-on then there is no need - // to shut it down (should only happen when a bootstrapped add-on is - // pending enable) - if (!XPIProvider.activeAddons.has(addon.id)) - continue; - + for (let id in XPIProvider.bootstrappedAddons) { let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); - file.persistentDescriptor = addon.descriptor; - let addonDetails = createAddonDetails(addon.id, addon); - - // If the add-on was pending disable then shut it down and remove it - // from the persisted data. - if (addon.disable) { - XPIProvider.callBootstrapMethod(addonDetails, file, "shutdown", - BOOTSTRAP_REASONS.ADDON_DISABLE); - delete XPIProvider.bootstrappedAddons[addon.id]; - } - else { - XPIProvider.callBootstrapMethod(addonDetails, file, "shutdown", - BOOTSTRAP_REASONS.APP_SHUTDOWN); - } + file.persistentDescriptor = XPIProvider.bootstrappedAddons[id].descriptor; + let addon = createAddonDetails(id, XPIProvider.bootstrappedAddons[id]); + XPIProvider.callBootstrapMethod(addon, file, "shutdown", + BOOTSTRAP_REASONS.APP_SHUTDOWN); } Services.obs.removeObserver(this, "quit-application-granted"); } @@ -2931,7 +2199,7 @@ this.XPIProvider = { // Detect final-ui-startup for telemetry reporting Services.obs.addObserver({ - observe: function(aSubject, aTopic, aData) { + observe: function uiStartupObserver(aSubject, aTopic, aData) { AddonManagerPrivate.recordTimestamp("XPI_finalUIStartup"); XPIProvider.runPhase = XPI_AFTER_UI_STARTUP; Services.obs.removeObserver(this, "final-ui-startup"); @@ -2942,12 +2210,6 @@ this.XPIProvider = { this.extensionsActive = true; this.runPhase = XPI_BEFORE_UI_STARTUP; - - let timerManager = Cc["@mozilla.org/updates/timer-manager;1"]. - getService(Ci.nsIUpdateTimerManager); - timerManager.registerTimer("xpi-signature-verification", () => { - this.verifySignatures(); - }, XPI_SIGNATURE_CHECK_PERIOD); } catch (e) { logger.error("startup failed", e); @@ -2961,14 +2223,14 @@ this.XPIProvider = { * flushing the XPI Database if it was loaded, * 0 otherwise. */ - shutdown: function() { + shutdown: function XPI_shutdown() { logger.debug("shutdown"); // Stop anything we were doing asynchronously this.cancelAll(); this.bootstrappedAddons = {}; - this.activeAddons.clear(); + this.bootstrapScopes = {}; this.enabledAddons = null; this.allAppGlobal = true; @@ -3004,15 +2266,16 @@ this.XPIProvider = { ); return done; } - logger.debug("Notifying XPI shutdown observers"); - Services.obs.notifyObservers(null, "xpi-provider-shutdown", null); - return undefined; + else { + logger.debug("Notifying XPI shutdown observers"); + Services.obs.notifyObservers(null, "xpi-provider-shutdown", null); + } }, /** * Applies any pending theme change to the preferences. */ - applyThemeChange: function() { + applyThemeChange: function XPI_applyThemeChange() { if (!Preferences.get(PREF_DSS_SWITCHPENDING, false)) return; @@ -3040,7 +2303,7 @@ this.XPIProvider = { * IDs to check for updates. Array may be empty if no add-ons can be/need * to be updated, but the metadata check needs to be performed. */ - shouldForceUpdateCheck: function(aAppChanged) { + shouldForceUpdateCheck: function XPI_shouldForceUpdateCheck(aAppChanged) { AddonManagerPrivate.recordSimpleMeasure("XPIDB_metadata_age", AddonRepository.metadataAge()); let startupChanges = AddonManager.getStartupChanges(AddonManager.STARTUP_CHANGE_DISABLED); @@ -3052,8 +2315,7 @@ this.XPIProvider = { let addons = XPIDatabase.getAddons(); for (let addon of addons) { if ((startupChanges.indexOf(addon.id) != -1) && - (addon.permissions() & AddonManager.PERM_CAN_UPGRADE) && - !addon.isCompatible) { + (addon.permissions() & AddonManager.PERM_CAN_UPGRADE)) { logger.debug("shouldForceUpdateCheck: can upgrade disabled add-on " + addon.id); forceUpdate.push(addon.id); } @@ -3078,10 +2340,8 @@ this.XPIProvider = { * Array opf addon IDs that were disabled by the application update, and * should therefore be checked for updates. */ - showUpgradeUI: function(aAddonIDs) { + showUpgradeUI: function XPI_showUpgradeUI(aAddonIDs) { logger.debug("XPI_showUpgradeUI: " + aAddonIDs.toSource()); - Services.telemetry.getHistogramById("ADDON_MANAGER_UPGRADE_UI_SHOWN").add(1); - // Flip a flag to indicate that we interrupted startup with an interactive prompt Services.startup.interrupted = true; @@ -3100,184 +2360,10 @@ this.XPIProvider = { !XPIDatabase.writeAddonsList()); }, - updateSystemAddons: Task.async(function*() { - let systemAddonLocation = XPIProvider.installLocationsByName[KEY_APP_SYSTEM_ADDONS]; - if (!systemAddonLocation) - return; - - // Don't do anything in safe mode - if (Services.appinfo.inSafeMode) - return; - - // Download the list of system add-ons - let url = Preferences.get(PREF_SYSTEM_ADDON_UPDATE_URL, null); - if (!url) { - yield systemAddonLocation.cleanDirectories(); - return; - } - - url = UpdateUtils.formatUpdateURL(url); - - logger.info(`Starting system add-on update check from ${url}.`); - let res = yield ProductAddonChecker.getProductAddonList(url); - - // If there was no list then do nothing. - if (!res || !res.gmpAddons) { - logger.info("No system add-ons list was returned."); - yield systemAddonLocation.cleanDirectories(); - return; - } - - let addonList = new Map( - res.gmpAddons.map(spec => [spec.id, { spec, path: null, addon: null }])); - - let getAddonsInLocation = (location) => { - return new Promise(resolve => { - XPIDatabase.getAddonsInLocation(location, resolve); - }); - }; - - let setMatches = (wanted, existing) => { - if (wanted.size != existing.size) - return false; - - for (let [id, addon] of existing) { - let wantedInfo = wanted.get(id); - - if (!wantedInfo) - return false; - if (wantedInfo.spec.version != addon.version) - return false; - } - - return true; - }; - - // If this matches the current set in the profile location then do nothing. - let updatedAddons = addonMap(yield getAddonsInLocation(KEY_APP_SYSTEM_ADDONS)); - if (setMatches(addonList, updatedAddons)) { - logger.info("Retaining existing updated system add-ons."); - yield systemAddonLocation.cleanDirectories(); - return; - } - - // If this matches the current set in the default location then reset the - // updated set. - let defaultAddons = addonMap(yield getAddonsInLocation(KEY_APP_SYSTEM_DEFAULTS)); - if (setMatches(addonList, defaultAddons)) { - logger.info("Resetting system add-ons."); - systemAddonLocation.resetAddonSet(); - yield systemAddonLocation.cleanDirectories(); - return; - } - - // Download all the add-ons - let downloadAddon = Task.async(function*(item) { - try { - let sourceAddon = updatedAddons.get(item.spec.id); - if (sourceAddon && sourceAddon.version == item.spec.version) { - // Copying the file to a temporary location has some benefits. If the - // file is locked and cannot be read then we'll fall back to - // downloading a fresh copy. It also means we don't have to remember - // whether to delete the temporary copy later. - try { - let path = OS.Path.join(OS.Constants.Path.tmpDir, "tmpaddon"); - let unique = yield OS.File.openUnique(path); - unique.file.close(); - yield OS.File.copy(sourceAddon._sourceBundle.path, unique.path); - // Make sure to update file modification times so this is detected - // as a new add-on. - yield OS.File.setDates(unique.path); - item.path = unique.path; - } - catch (e) { - logger.warn(`Failed make temporary copy of ${sourceAddon._sourceBundle.path}.`, e); - } - } - if (!item.path) { - item.path = yield ProductAddonChecker.downloadAddon(item.spec); - } - item.addon = yield loadManifestFromFile(nsIFile(item.path), systemAddonLocation); - } - catch (e) { - logger.error(`Failed to download system add-on ${item.spec.id}`, e); - } - }); - yield Promise.all(Array.from(addonList.values()).map(downloadAddon)); - - // The download promises all resolve regardless, now check if they all - // succeeded - let validateAddon = (item) => { - if (item.spec.id != item.addon.id) { - logger.warn(`Downloaded system add-on expected to be ${item.spec.id} but was ${item.addon.id}.`); - return false; - } - - if (item.spec.version != item.addon.version) { - logger.warn(`Expected system add-on ${item.spec.id} to be version ${item.spec.version} but was ${item.addon.version}.`); - return false; - } - - if (!systemAddonLocation.isValidAddon(item.addon)) - return false; - - return true; - } - - if (!Array.from(addonList.values()).every(item => item.path && item.addon && validateAddon(item))) { - throw new Error("Rejecting updated system add-on set that either could not " + - "be downloaded or contained unusable add-ons."); - } - - // Install into the install location - logger.info("Installing new system add-on set"); - yield systemAddonLocation.installAddonSet(Array.from(addonList.values()) - .map(a => a.addon)); - }), - - /** - * Verifies that all installed add-ons are still correctly signed. - */ - verifySignatures: function() { - XPIDatabase.getAddonList(a => true, (addons) => { - Task.spawn(function*() { - let changes = { - enabled: [], - disabled: [] - }; - - for (let addon of addons) { - // The add-on might have vanished, we'll catch that on the next startup - if (!addon._sourceBundle.exists()) - continue; - - let signedState = yield verifyBundleSignedState(addon._sourceBundle, addon); - - if (signedState != addon.signedState) { - addon.signedState = signedState; - AddonManagerPrivate.callAddonListeners("onPropertyChanged", - addon.wrapper, - ["signedState"]); - } - - let disabled = XPIProvider.updateAddonDisabledState(addon); - if (disabled !== undefined) - changes[disabled ? "disabled" : "enabled"].push(addon.id); - } - - XPIDatabase.saveChanges(); - - Services.obs.notifyObservers(null, "xpi-signature-changed", JSON.stringify(changes)); - }).then(null, err => { - logger.error("XPI_verifySignature: " + err); - }) - }); - }, - /** * Persists changes to XPIProvider.bootstrappedAddons to its store (a pref). */ - persistBootstrappedAddons: function() { + persistBootstrappedAddons: function XPI_persistBootstrappedAddons() { // Experiments are disabled upon app load, so don't persist references. let filtered = {}; for (let id in this.bootstrappedAddons) { @@ -3296,7 +2382,7 @@ this.XPIProvider = { /** * Adds a list of currently active add-ons to the next crash report. */ - addAddonsToCrashReporter: function() { + addAddonsToCrashReporter: function XPI_addAddonsToCrashReporter() { if (!("nsICrashReporter" in Ci) || !(Services.appinfo instanceof Ci.nsICrashReporter)) return; @@ -3331,24 +2417,110 @@ this.XPIProvider = { * of passing through updated compatibility information * @return true if an add-on was installed or uninstalled */ - processPendingFileChanges: function(aManifests) { + processPendingFileChanges: function XPI_processPendingFileChanges(aManifests) { let changed = false; - for (let location of this.installLocations) { - aManifests[location.name] = {}; + this.installLocations.forEach(function(aLocation) { + aManifests[aLocation.name] = {}; // We can't install or uninstall anything in locked locations - if (location.locked) { - continue; + if (aLocation.locked) + return; + + let stagedXPIDir = aLocation.getXPIStagingDir(); + let stagingDir = aLocation.getStagingDir(); + + if (stagedXPIDir.exists() && stagedXPIDir.isDirectory()) { + let entries = stagedXPIDir.directoryEntries + .QueryInterface(Ci.nsIDirectoryEnumerator); + while (entries.hasMoreElements()) { + let stageDirEntry = entries.nextFile; + + if (!stageDirEntry.isDirectory()) { + logger.warn("Ignoring file in XPI staging directory: " + stageDirEntry.path); + continue; + } + + // Find the last added XPI file in the directory + let stagedXPI = null; + var xpiEntries = stageDirEntry.directoryEntries + .QueryInterface(Ci.nsIDirectoryEnumerator); + while (xpiEntries.hasMoreElements()) { + let file = xpiEntries.nextFile; + if (file.isDirectory()) + continue; + + let extension = file.leafName; + extension = extension.substring(extension.length - 4); + + if (extension != ".xpi" && extension != ".jar") + continue; + + stagedXPI = file; + } + xpiEntries.close(); + + if (!stagedXPI) + continue; + + let addon = null; + try { + addon = loadManifestFromZipFile(stagedXPI); + } + catch (e) { + logger.error("Unable to read add-on manifest from " + stagedXPI.path, e); + continue; + } + + logger.debug("Migrating staged install of " + addon.id + " in " + aLocation.name); + + if (addon.unpack || Preferences.get(PREF_XPI_UNPACK, false)) { + let targetDir = stagingDir.clone(); + targetDir.append(addon.id); + try { + targetDir.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY); + } + catch (e) { + logger.error("Failed to create staging directory for add-on " + addon.id, e); + continue; + } + + try { + ZipUtils.extractFiles(stagedXPI, targetDir); + } + catch (e) { + logger.error("Failed to extract staged XPI for add-on " + addon.id + " in " + + aLocation.name, e); + } + } + else { + try { + stagedXPI.moveTo(stagingDir, addon.id + ".xpi"); + } + catch (e) { + logger.error("Failed to move staged XPI for add-on " + addon.id + " in " + + aLocation.name, e); + } + } + } + entries.close(); } - let stagingDir = location.getStagingDir(); + if (stagedXPIDir.exists()) { + try { + recursiveRemove(stagedXPIDir); + } + catch (e) { + // Non-critical, just saves some perf on startup if we clean this up. + logger.debug("Error removing XPI staging dir " + stagedXPIDir.path, e); + } + } try { if (!stagingDir || !stagingDir.exists() || !stagingDir.isDirectory()) - continue; + return; } catch (e) { logger.warn("Failed to find staging directory", e); - continue; + return; } let seenFiles = []; @@ -3364,9 +2536,7 @@ this.XPIProvider = { try { isDir = stageDirEntry.isDirectory(); } - catch (e) { - if (e.result != Cr.NS_ERROR_FILE_TARGET_DOES_NOT_EXIST) - throw e; + catch (e if e.result == Cr.NS_ERROR_FILE_TARGET_DOES_NOT_EXIST) { // If the file has already gone away then don't worry about it, this // can happen on OSX where the resource fork is automatically moved // with the data fork for the file. See bug 733436. @@ -3398,16 +2568,17 @@ this.XPIProvider = { if (isDir) { // Check if the directory contains an install manifest. - let manifest = getManifestFileForDir(stageDirEntry); + let manifest = stageDirEntry.clone(); + manifest.append(FILE_INSTALL_MANIFEST); // If the install manifest doesn't exist uninstall this add-on in this // install location. - if (!manifest) { - logger.debug("Processing uninstall of " + id + " in " + location.name); + if (!manifest.exists()) { + logger.debug("Processing uninstall of " + id + " in " + aLocation.name); try { - let addonFile = location.getLocationForID(id); - let addonToUninstall = syncLoadManifestFromFile(addonFile, location); + let addonFile = aLocation.getLocationForID(id); + let addonToUninstall = loadManifestFromFile(addonFile, aLocation); if (addonToUninstall.bootstrap) { this.callBootstrapMethod(addonToUninstall, addonToUninstall._sourceBundle, "uninstall", BOOTSTRAP_REASONS.ADDON_UNINSTALL); @@ -3418,28 +2589,25 @@ this.XPIProvider = { } try { - location.uninstallAddon(id); + aLocation.uninstallAddon(id); seenFiles.push(stageDirEntry.leafName); } catch (e) { - logger.error("Failed to uninstall add-on " + id + " in " + location.name, e); + logger.error("Failed to uninstall add-on " + id + " in " + aLocation.name, e); } // The file check later will spot the removal and cleanup the database continue; } } - aManifests[location.name][id] = null; + aManifests[aLocation.name][id] = null; let existingAddonID = id; let jsonfile = stagingDir.clone(); jsonfile.append(id + ".json"); - // Assume this was a foreign install if there is no cached metadata file - let foreignInstall = !jsonfile.exists(); - let addon; try { - addon = syncLoadManifestFromFile(stageDirEntry, location); + aManifests[aLocation.name][id] = loadManifestFromFile(stageDirEntry); } catch (e) { logger.error("Unable to read add-on manifest from " + stageDirEntry.path, e); @@ -3449,18 +2617,10 @@ this.XPIProvider = { continue; } - if (mustSign(addon.type) && - addon.signedState <= AddonManager.SIGNEDSTATE_MISSING) { - logger.warn("Refusing to install staged add-on " + id + " with signed state " + addon.signedState); - seenFiles.push(stageDirEntry.leafName); - seenFiles.push(jsonfile.leafName); - continue; - } - // Check for a cached metadata for this add-on, it may contain updated // compatibility information - if (!foreignInstall) { - logger.debug("Found updated metadata for " + id + " in " + location.name); + if (jsonfile.exists()) { + logger.debug("Found updated metadata for " + id + " in " + aLocation.name); let fis = Cc["@mozilla.org/network/file-input-stream;1"]. createInstance(Ci.nsIFileInputStream); let json = Cc["@mozilla.org/dom/json;1"]. @@ -3469,16 +2629,12 @@ this.XPIProvider = { try { fis.init(jsonfile, -1, 0, 0); let metadata = json.decodeFromStream(fis, jsonfile.fileSize); - addon.importMetadata(metadata); - - // Pass this through to addMetadata so it knows this add-on was - // likely installed through the UI - aManifests[location.name][id] = addon; + aManifests[aLocation.name][id].importMetadata(metadata); } catch (e) { // If some data can't be recovered from the cached metadata then it // is unlikely to be a problem big enough to justify throwing away - // the install, just log an error and continue + // the install, just log and error and continue logger.error("Unable to read metadata from " + jsonfile.path, e); } finally { @@ -3487,20 +2643,20 @@ this.XPIProvider = { } seenFiles.push(jsonfile.leafName); - existingAddonID = addon.existingAddonID || id; + existingAddonID = aManifests[aLocation.name][id].existingAddonID || id; var oldBootstrap = null; - logger.debug("Processing install of " + id + " in " + location.name); + logger.debug("Processing install of " + id + " in " + aLocation.name); if (existingAddonID in this.bootstrappedAddons) { try { - var existingAddon = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); - existingAddon.persistentDescriptor = this.bootstrappedAddons[existingAddonID].descriptor; - if (existingAddon.exists()) { + var existingAddon = aLocation.getLocationForID(existingAddonID); + if (this.bootstrappedAddons[existingAddonID].descriptor == + existingAddon.persistentDescriptor) { oldBootstrap = this.bootstrappedAddons[existingAddonID]; // We'll be replacing a currently active bootstrapped add-on so // call its uninstall method - let newVersion = addon.version; + let newVersion = aManifests[aLocation.name][id].version; let oldVersion = oldBootstrap.version; let uninstallReason = Services.vc.compare(oldVersion, newVersion) < 0 ? BOOTSTRAP_REASONS.ADDON_UPGRADE : @@ -3510,7 +2666,7 @@ this.XPIProvider = { existingAddon, "uninstall", uninstallReason, { newVersion: newVersion }); this.unloadBootstrapScope(existingAddonID); - flushChromeCaches(); + flushStartupCache(); } } catch (e) { @@ -3518,21 +2674,21 @@ this.XPIProvider = { } try { - addon._sourceBundle = location.installAddon({ - id, - source: stageDirEntry, - existingAddonID - }); + var addonInstallLocation = aLocation.installAddon(id, stageDirEntry, + existingAddonID); + if (aManifests[aLocation.name][id]) + aManifests[aLocation.name][id]._sourceBundle = addonInstallLocation; } catch (e) { - logger.error("Failed to install staged add-on " + id + " in " + location.name, + logger.error("Failed to install staged add-on " + id + " in " + aLocation.name, e); // Re-create the staged install - new StagedAddonInstall(location, stageDirEntry, addon); + AddonInstall.createStagedInstall(aLocation, stageDirEntry, + aManifests[aLocation.name][id]); // Make sure not to delete the cached manifest json file seenFiles.pop(); - delete aManifests[location.name][id]; + delete aManifests[aLocation.name][id]; if (oldBootstrap) { // Re-install the old add-on @@ -3545,13 +2701,13 @@ this.XPIProvider = { } try { - location.cleanStagingDir(seenFiles); + aLocation.cleanStagingDir(seenFiles); } catch (e) { // Non-critical, just saves some perf on startup if we clean this up. logger.debug("Error cleaning staging dir " + stagingDir.path, e); } - } + }, this); return changed; }, @@ -3564,11 +2720,9 @@ this.XPIProvider = { * @param aManifests * A dictionary to add new install manifests to to save having to * reload them later - * @param aAppChanged - * See checkForChanges * @return true if any new add-ons were installed */ - installDistributionAddons: function(aManifests, aAppChanged) { + installDistributionAddons: function XPI_installDistributionAddons(aManifests) { let distroDir; try { distroDir = FileUtils.getDir(KEY_APP_DISTRIBUTION, [DIR_EXTENSIONS]); @@ -3614,15 +2768,9 @@ this.XPIProvider = { continue; } - /* If this is not an upgrade and we've already handled this extension - * just continue */ - if (!aAppChanged && Preferences.isSet(PREF_BRANCH_INSTALLED_ADDON + id)) { - continue; - } - let addon; try { - addon = syncLoadManifestFromFile(entry, profileLocation); + addon = loadManifestFromFile(entry); } catch (e) { logger.warn("File entry " + entry.path + " contains an invalid add-on", e); @@ -3645,7 +2793,7 @@ this.XPIProvider = { if (existingEntry) { let existingAddon; try { - existingAddon = syncLoadManifestFromFile(existingEntry, profileLocation); + existingAddon = loadManifestFromFile(existingEntry); if (Services.vc.compare(addon.version, existingAddon.version) <= 0) continue; @@ -3662,7 +2810,7 @@ this.XPIProvider = { // Install the add-on try { - addon._sourceBundle = profileLocation.installAddon({ id, source: entry, action: "copy" }); + profileLocation.installAddon(id, entry, null, true); logger.debug("Installed distribution add-on " + id); Services.prefs.setBoolPref(PREF_BRANCH_INSTALLED_ADDON + id, true) @@ -3686,19 +2834,657 @@ this.XPIProvider = { }, /** + * Compares the add-ons that are currently installed to those that were + * known to be installed when the application last ran and applies any + * changes found to the database. Also sends "startupcache-invalidate" signal to + * observerservice if it detects that data may have changed. + * Always called after XPIProviderUtils.js and extensions.json have been loaded. + * + * @param aManifests + * A dictionary of cached AddonInstalls for add-ons that have been + * installed + * @param aUpdateCompatibility + * true to update add-ons appDisabled property when the application + * version has changed + * @param aOldAppVersion + * The version of the application last run with this profile or null + * if it is a new profile or the version is unknown + * @param aOldPlatformVersion + * The version of the platform last run with this profile or null + * if it is a new profile or the version is unknown + * @return a boolean indicating if a change requiring flushing the caches was + * detected + */ + processFileChanges: function XPI_processFileChanges(aManifests, + aUpdateCompatibility, + aOldAppVersion, + aOldPlatformVersion) { + let visibleAddons = {}; + let oldBootstrappedAddons = this.bootstrappedAddons; + this.bootstrappedAddons = {}; + + /** + * Updates an add-on's metadata and determines if a restart of the + * application is necessary. This is called when either the add-on's + * install directory path or last modified time has changed. + * + * @param aInstallLocation + * The install location containing the add-on + * @param aOldAddon + * The AddonInternal as it appeared the last time the application + * ran + * @param aAddonState + * The new state of the add-on + * @return a boolean indicating if flushing caches is required to complete + * changing this add-on + */ + function updateMetadata(aInstallLocation, aOldAddon, aAddonState) { + logger.debug("Add-on " + aOldAddon.id + " modified in " + aInstallLocation.name); + + // Check if there is an updated install manifest for this add-on + let newAddon = aManifests[aInstallLocation.name][aOldAddon.id]; + + try { + // If not load it + if (!newAddon) { + let file = aInstallLocation.getLocationForID(aOldAddon.id); + newAddon = loadManifestFromFile(file); + applyBlocklistChanges(aOldAddon, newAddon); + + // Carry over any pendingUninstall state to add-ons modified directly + // in the profile. This is important when the attempt to remove the + // add-on in processPendingFileChanges failed and caused an mtime + // change to the add-ons files. + newAddon.pendingUninstall = aOldAddon.pendingUninstall; + } + + // The ID in the manifest that was loaded must match the ID of the old + // add-on. + if (newAddon.id != aOldAddon.id) + throw new Error("Incorrect id in install manifest for existing add-on " + aOldAddon.id); + } + catch (e) { + logger.warn("updateMetadata: Add-on " + aOldAddon.id + " is invalid", e); + XPIDatabase.removeAddonMetadata(aOldAddon); + XPIStates.removeAddon(aOldAddon.location, aOldAddon.id); + if (!aInstallLocation.locked) + aInstallLocation.uninstallAddon(aOldAddon.id); + else + logger.warn("Could not uninstall invalid item from locked install location"); + // If this was an active add-on then we must force a restart + if (aOldAddon.active) + return true; + + return false; + } + + // Set the additional properties on the new AddonInternal + newAddon._installLocation = aInstallLocation; + newAddon.updateDate = aAddonState.mtime; + newAddon.visible = !(newAddon.id in visibleAddons); + + // Update the database + let newDBAddon = XPIDatabase.updateAddonMetadata(aOldAddon, newAddon, + aAddonState.descriptor); + if (newDBAddon.visible) { + visibleAddons[newDBAddon.id] = newDBAddon; + // Remember add-ons that were changed during startup + AddonManagerPrivate.addStartupChange(AddonManager.STARTUP_CHANGE_CHANGED, + newDBAddon.id); + + // If this was the active theme and it is now disabled then enable the + // default theme + if (aOldAddon.active && newDBAddon.disabled) + XPIProvider.enableDefaultTheme(); + + // If the new add-on is bootstrapped and active then call its install method + if (newDBAddon.active && newDBAddon.bootstrap) { + // Startup cache must be flushed before calling the bootstrap script + flushStartupCache(); + + let installReason = Services.vc.compare(aOldAddon.version, newDBAddon.version) < 0 ? + BOOTSTRAP_REASONS.ADDON_UPGRADE : + BOOTSTRAP_REASONS.ADDON_DOWNGRADE; + + let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); + file.persistentDescriptor = aAddonState.descriptor; + XPIProvider.callBootstrapMethod(newDBAddon, file, "install", + installReason, { oldVersion: aOldAddon.version }); + return false; + } + + return true; + } + + return false; + } + + /** + * Updates an add-on's descriptor for when the add-on has moved in the + * filesystem but hasn't changed in any other way. + * + * @param aInstallLocation + * The install location containing the add-on + * @param aOldAddon + * The AddonInternal as it appeared the last time the application + * ran + * @param aAddonState + * The new state of the add-on + * @return a boolean indicating if flushing caches is required to complete + * changing this add-on + */ + function updateDescriptor(aInstallLocation, aOldAddon, aAddonState) { + logger.debug("Add-on " + aOldAddon.id + " moved to " + aAddonState.descriptor); + + aOldAddon.descriptor = aAddonState.descriptor; + aOldAddon.visible = !(aOldAddon.id in visibleAddons); + XPIDatabase.saveChanges(); + + if (aOldAddon.visible) { + visibleAddons[aOldAddon.id] = aOldAddon; + + if (aOldAddon.bootstrap && aOldAddon.active) { + let bootstrap = oldBootstrappedAddons[aOldAddon.id]; + bootstrap.descriptor = aAddonState.descriptor; + XPIProvider.bootstrappedAddons[aOldAddon.id] = bootstrap; + } + + return true; + } + + return false; + } + + /** + * Called when no change has been detected for an add-on's metadata. The + * add-on may have become visible due to other add-ons being removed or + * the add-on may need to be updated when the application version has + * changed. + * + * @param aInstallLocation + * The install location containing the add-on + * @param aOldAddon + * The AddonInternal as it appeared the last time the application + * ran + * @param aAddonState + * The new state of the add-on + * @return a boolean indicating if flushing caches is required to complete + * changing this add-on + */ + function updateVisibilityAndCompatibility(aInstallLocation, aOldAddon, + aAddonState) { + let changed = false; + + // This add-ons metadata has not changed but it may have become visible + if (!(aOldAddon.id in visibleAddons)) { + visibleAddons[aOldAddon.id] = aOldAddon; + + if (!aOldAddon.visible) { + // Remember add-ons that were changed during startup. + AddonManagerPrivate.addStartupChange(AddonManager.STARTUP_CHANGE_CHANGED, + aOldAddon.id); + XPIDatabase.makeAddonVisible(aOldAddon); + + if (aOldAddon.bootstrap) { + // The add-on is bootstrappable so call its install script + let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); + file.persistentDescriptor = aAddonState.descriptor; + XPIProvider.callBootstrapMethod(aOldAddon, file, + "install", + BOOTSTRAP_REASONS.ADDON_INSTALL); + + // If it should be active then mark it as active otherwise unload + // its scope + if (!aOldAddon.disabled) { + XPIDatabase.updateAddonActive(aOldAddon, true); + } + else { + XPIProvider.unloadBootstrapScope(newAddon.id); + } + } + else { + // Otherwise a restart is necessary + changed = true; + } + } + } + + // App version changed, we may need to update the appDisabled property. + if (aUpdateCompatibility) { + let wasDisabled = aOldAddon.disabled; + let wasAppDisabled = aOldAddon.appDisabled; + let wasUserDisabled = aOldAddon.userDisabled; + let wasSoftDisabled = aOldAddon.softDisabled; + + // This updates the addon's JSON cached data in place + applyBlocklistChanges(aOldAddon, aOldAddon, aOldAppVersion, + aOldPlatformVersion); + aOldAddon.appDisabled = !isUsableAddon(aOldAddon); + + let isDisabled = aOldAddon.disabled; + + // If either property has changed update the database. + if (wasAppDisabled != aOldAddon.appDisabled || + wasUserDisabled != aOldAddon.userDisabled || + wasSoftDisabled != aOldAddon.softDisabled) { + logger.debug("Add-on " + aOldAddon.id + " changed appDisabled state to " + + aOldAddon.appDisabled + ", userDisabled state to " + + aOldAddon.userDisabled + " and softDisabled state to " + + aOldAddon.softDisabled); + XPIDatabase.saveChanges(); + } + + // If this is a visible add-on and it has changed disabled state then we + // may need a restart or to update the bootstrap list. + if (aOldAddon.visible && wasDisabled != isDisabled) { + // Remember add-ons that became disabled or enabled by the application + // change + let change = isDisabled ? AddonManager.STARTUP_CHANGE_DISABLED + : AddonManager.STARTUP_CHANGE_ENABLED; + AddonManagerPrivate.addStartupChange(change, aOldAddon.id); + if (aOldAddon.bootstrap) { + // Update the add-ons active state + XPIDatabase.updateAddonActive(aOldAddon, !isDisabled); + } + else { + changed = true; + } + } + } + + if (aOldAddon.visible && aOldAddon.active && aOldAddon.bootstrap) { + XPIProvider.bootstrappedAddons[aOldAddon.id] = { + version: aOldAddon.version, + type: aOldAddon.type, + descriptor: aAddonState.descriptor, + multiprocessCompatible: aOldAddon.multiprocessCompatible + }; + } + + return changed; + } + + /** + * Called when an add-on has been removed. + * + * @param aOldAddon + * The AddonInternal as it appeared the last time the application + * ran + * @return a boolean indicating if flushing caches is required to complete + * changing this add-on + */ + function removeMetadata(aOldAddon) { + // This add-on has disappeared + logger.debug("Add-on " + aOldAddon.id + " removed from " + aOldAddon.location); + XPIDatabase.removeAddonMetadata(aOldAddon); + + // Remember add-ons that were uninstalled during startup + if (aOldAddon.visible) { + AddonManagerPrivate.addStartupChange(AddonManager.STARTUP_CHANGE_UNINSTALLED, + aOldAddon.id); + } + else if (AddonManager.getStartupChanges(AddonManager.STARTUP_CHANGE_INSTALLED) + .indexOf(aOldAddon.id) != -1) { + AddonManagerPrivate.addStartupChange(AddonManager.STARTUP_CHANGE_CHANGED, + aOldAddon.id); + } + + if (aOldAddon.active) { + // Enable the default theme if the previously active theme has been + // removed + if (aOldAddon.type == "theme") + XPIProvider.enableDefaultTheme(); + + return true; + } + + return false; + } + + /** + * Called to add the metadata for an add-on in one of the install locations + * to the database. This can be called in three different cases. Either an + * add-on has been dropped into the location from outside of Firefox, or + * an add-on has been installed through the application, or the database + * has been upgraded or become corrupt and add-on data has to be reloaded + * into it. + * + * @param aInstallLocation + * The install location containing the add-on + * @param aId + * The ID of the add-on + * @param aAddonState + * The new state of the add-on + * @param aMigrateData + * If during startup the database had to be upgraded this will + * contain data that used to be held about this add-on + * @return a boolean indicating if flushing caches is required to complete + * changing this add-on + */ + function addMetadata(aInstallLocation, aId, aAddonState, aMigrateData) { + logger.debug("New add-on " + aId + " installed in " + aInstallLocation.name); + + let newAddon = null; + let sameVersion = false; + // Check the updated manifests lists for the install location, If there + // is no manifest for the add-on ID then newAddon will be undefined + if (aInstallLocation.name in aManifests) + newAddon = aManifests[aInstallLocation.name][aId]; + + // If we had staged data for this add-on or we aren't recovering from a + // corrupt database and we don't have migration data for this add-on then + // this must be a new install. + let isNewInstall = (!!newAddon) || (!XPIDatabase.activeBundles && !aMigrateData); + + // If it's a new install and we haven't yet loaded the manifest then it + // must be something dropped directly into the install location + let isDetectedInstall = isNewInstall && !newAddon; + + // Load the manifest if necessary and sanity check the add-on ID + try { + if (!newAddon) { + // Load the manifest from the add-on. + let file = aInstallLocation.getLocationForID(aId); + newAddon = loadManifestFromFile(file); + } + // The add-on in the manifest should match the add-on ID. + if (newAddon.id != aId) { + throw new Error("Invalid addon ID: expected addon ID " + aId + + ", found " + newAddon.id + " in manifest"); + } + } + catch (e) { + logger.warn("addMetadata: Add-on " + aId + " is invalid", e); + + // Remove the invalid add-on from the install location if the install + // location isn't locked, no restart will be necessary + if (!aInstallLocation.locked) + aInstallLocation.uninstallAddon(aId); + else + logger.warn("Could not uninstall invalid item from locked install location"); + return false; + } + + // Update the AddonInternal properties. + newAddon._installLocation = aInstallLocation; + newAddon.visible = !(newAddon.id in visibleAddons); + newAddon.installDate = aAddonState.mtime; + newAddon.updateDate = aAddonState.mtime; + newAddon.foreignInstall = isDetectedInstall; + + if (aMigrateData) { + // If there is migration data then apply it. + logger.debug("Migrating data from old database"); + + DB_MIGRATE_METADATA.forEach(function(aProp) { + // A theme's disabled state is determined by the selected theme + // preference which is read in loadManifestFromRDF + if (aProp == "userDisabled" && newAddon.type == "theme") + return; + + if (aProp in aMigrateData) + newAddon[aProp] = aMigrateData[aProp]; + }); + + // Force all non-profile add-ons to be foreignInstalls since they can't + // have been installed through the API + newAddon.foreignInstall |= aInstallLocation.name != KEY_APP_PROFILE; + + // Some properties should only be migrated if the add-on hasn't changed. + // The version property isn't a perfect check for this but covers the + // vast majority of cases. + if (aMigrateData.version == newAddon.version) { + logger.debug("Migrating compatibility info"); + sameVersion = true; + if ("targetApplications" in aMigrateData) + newAddon.applyCompatibilityUpdate(aMigrateData, true); + } + + // Since the DB schema has changed make sure softDisabled is correct + applyBlocklistChanges(newAddon, newAddon, aOldAppVersion, + aOldPlatformVersion); + } + + // The default theme is never a foreign install + if (newAddon.type == "theme" && newAddon.internalName == XPIProvider.defaultSkin) + newAddon.foreignInstall = false; + + if (isDetectedInstall && newAddon.foreignInstall) { + // If the add-on is a foreign install and is in a scope where add-ons + // that were dropped in should default to disabled then disable it + let disablingScopes = Preferences.get(PREF_EM_AUTO_DISABLED_SCOPES, 0); + if (aInstallLocation.scope & disablingScopes) { + logger.warn("Disabling foreign installed add-on " + newAddon.id + " in " + + aInstallLocation.name); + newAddon.userDisabled = true; + } + } + + // If we have a list of what add-ons should be marked as active then use + // it to guess at migration data. + if (!isNewInstall && XPIDatabase.activeBundles) { + // For themes we know which is active by the current skin setting + if (newAddon.type == "theme") + newAddon.active = newAddon.internalName == XPIProvider.currentSkin; + else + newAddon.active = XPIDatabase.activeBundles.indexOf(aAddonState.descriptor) != -1; + + // If the add-on wasn't active and it isn't already disabled in some way + // then it was probably either softDisabled or userDisabled + if (!newAddon.active && newAddon.visible && !newAddon.disabled) { + // If the add-on is softblocked then assume it is softDisabled + if (newAddon.blocklistState == Blocklist.STATE_SOFTBLOCKED) + newAddon.softDisabled = true; + else + newAddon.userDisabled = true; + } + } + else { + newAddon.active = (newAddon.visible && !newAddon.disabled); + } + + let newDBAddon = XPIDatabase.addAddonMetadata(newAddon, aAddonState.descriptor); + + if (newDBAddon.visible) { + // Remember add-ons that were first detected during startup. + if (isDetectedInstall) { + // If a copy from a higher priority location was removed then this + // add-on has changed + if (AddonManager.getStartupChanges(AddonManager.STARTUP_CHANGE_UNINSTALLED) + .indexOf(newDBAddon.id) != -1) { + AddonManagerPrivate.addStartupChange(AddonManager.STARTUP_CHANGE_CHANGED, + newDBAddon.id); + } + else { + AddonManagerPrivate.addStartupChange(AddonManager.STARTUP_CHANGE_INSTALLED, + newDBAddon.id); + } + } + + // Note if any visible add-on is not in the application install location + if (newDBAddon._installLocation.name != KEY_APP_GLOBAL) + XPIProvider.allAppGlobal = false; + + visibleAddons[newDBAddon.id] = newDBAddon; + + let installReason = BOOTSTRAP_REASONS.ADDON_INSTALL; + let extraParams = {}; + + // Copy add-on details (enabled, bootstrap, version, etc) to XPIState. + aAddonState.syncWithDB(newDBAddon); + + // If we're hiding a bootstrapped add-on then call its uninstall method + if (newDBAddon.id in oldBootstrappedAddons) { + let oldBootstrap = oldBootstrappedAddons[newDBAddon.id]; + extraParams.oldVersion = oldBootstrap.version; + XPIProvider.bootstrappedAddons[newDBAddon.id] = oldBootstrap; + + // If the old version is the same as the new version, or we're + // recovering from a corrupt DB, don't call uninstall and install + // methods. + if (sameVersion || !isNewInstall) { + logger.debug("addMetadata: early return, sameVersion " + sameVersion + + ", isNewInstall " + isNewInstall); + return false; + } + + installReason = Services.vc.compare(oldBootstrap.version, newDBAddon.version) < 0 ? + BOOTSTRAP_REASONS.ADDON_UPGRADE : + BOOTSTRAP_REASONS.ADDON_DOWNGRADE; + + let oldAddonFile = Cc["@mozilla.org/file/local;1"]. + createInstance(Ci.nsIFile); + oldAddonFile.persistentDescriptor = oldBootstrap.descriptor; + + XPIProvider.callBootstrapMethod(createAddonDetails(newDBAddon.id, oldBootstrap), + oldAddonFile, "uninstall", installReason, + { newVersion: newDBAddon.version }); + + XPIProvider.unloadBootstrapScope(newDBAddon.id); + + // If the new add-on is bootstrapped then we must flush the caches + // before calling the new bootstrap script + if (newDBAddon.bootstrap) + flushStartupCache(); + } + + if (!newDBAddon.bootstrap) + return true; + + // Visible bootstrapped add-ons need to have their install method called + let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); + file.persistentDescriptor = aAddonState.descriptor; + XPIProvider.callBootstrapMethod(newDBAddon, file, + "install", installReason, extraParams); + if (!newDBAddon.active) + XPIProvider.unloadBootstrapScope(newDBAddon.id); + } + + return false; + } + + let changed = false; + + // Get all the add-ons in the existing DB and Map them into Sets by install location + let allDBAddons = new Map(); + for (let a of XPIDatabase.getAddons()) { + let locationSet = allDBAddons.get(a.location); + if (!locationSet) { + locationSet = new Set(); + allDBAddons.set(a.location, locationSet); + } + locationSet.add(a); + } + + for (let installLocation of this.installLocations) { + // Get all the on-disk XPI states for this location, and keep track of which + // ones we see in the database. + let states = XPIStates.getLocation(installLocation.name); + let seen = new Set(); + // Iterate through the add-ons installed the last time the application + // ran + let dbAddons = allDBAddons.get(installLocation.name); + if (dbAddons) { + // we've processed this location + allDBAddons.delete(installLocation.name); + + logger.debug("processFileChanges reconciling DB for location ${l} state ${s} db ${d}", + {l: installLocation.name, s: states, d: [for (a of dbAddons) a.id]}); + for (let aOldAddon of dbAddons) { + // If a version of this add-on has been installed in an higher + // priority install location then count it as changed + if (AddonManager.getStartupChanges(AddonManager.STARTUP_CHANGE_INSTALLED) + .indexOf(aOldAddon.id) != -1) { + AddonManagerPrivate.addStartupChange(AddonManager.STARTUP_CHANGE_CHANGED, + aOldAddon.id); + } + + // Check if the add-on is still installed + let xpiState = states && states.get(aOldAddon.id); + if (xpiState) { + // in this block, the add-on is in both XPIStates and the DB + seen.add(xpiState); + + // The add-on has changed if the modification time has changed, or + // we have an updated manifest for it. Also reload the metadata for + // add-ons in the application directory when the application version + // has changed + if (aOldAddon.id in aManifests[installLocation.name] || + aOldAddon.updateDate != xpiState.mtime || + (aUpdateCompatibility && installLocation.name == KEY_APP_GLOBAL)) { + changed = updateMetadata(installLocation, aOldAddon, xpiState) || + changed; + } + else if (aOldAddon.descriptor != xpiState.descriptor) { + changed = updateDescriptor(installLocation, aOldAddon, xpiState) || + changed; + } + else { + changed = updateMetadata(installLocation, aOldAddon, xpiState) || + changed; + + changed = updateVisibilityAndCompatibility(installLocation, + aOldAddon, xpiState) || + changed; + } + if (aOldAddon.visible && aOldAddon._installLocation.name != KEY_APP_GLOBAL) + XPIProvider.allAppGlobal = false; + // Copy add-on details (enabled, bootstrap, version, etc) to XPIState. + xpiState.syncWithDB(aOldAddon); + } + else { + // The add-on is in the DB, but not in xpiState (and thus not on disk). + changed = removeMetadata(aOldAddon) || changed; + } + } + } + + // Any add-on in our current location that we haven't seen needs to + // be added to the database. + // Get the migration data for this install location so we can include that as + // we add, in case this is a database upgrade or rebuild. + let locMigrateData = {}; + if (XPIDatabase.migrateData && installLocation.name in XPIDatabase.migrateData) + locMigrateData = XPIDatabase.migrateData[installLocation.name]; + if (states) { + for (let [id, xpiState] of states) { + if (!seen.has(xpiState)) { + changed = addMetadata(installLocation, id, xpiState, + (locMigrateData[id] || null)) || changed; + } + } + } + } + + // Anything left in allDBAddons is a location where the database contains add-ons, + // but the browser is no longer configured to use that location. The metadata for those + // add-ons must be removed from the database. + for (let [locationName, addons] of allDBAddons) { + logger.debug("Removing orphaned DB add-on entries from " + locationName); + for (let a of addons) { + logger.debug("Remove ${location}:${id}", a); + changed = removeMetadata(a) || changed; + } + } + + XPIStates.save(); + this.persistBootstrappedAddons(); + + // Clear out any cached migration data. + XPIDatabase.migrateData = null; + + return changed; + }, + + /** * Imports the xpinstall permissions from preferences into the permissions * manager for the user to change later. */ - importPermissions: function() { + importPermissions: function XPI_importPermissions() { PermissionsUtils.importFromPrefs(PREF_XPI_PERMISSIONS_BRANCH, XPI_PERMISSION); }, - getDependentAddons: function(aAddon) { - return Array.from(XPIDatabase.getAddons()) - .filter(addon => addon.dependencies.includes(aAddon.id)); - }, - /** * Checks for any changes that have occurred since the last time the * application was launched. @@ -3717,7 +3503,7 @@ this.XPIProvider = { * if it is a new profile or the version is unknown * @return true if a change requiring a restart was detected */ - checkForChanges: function(aAppChanged, aOldAppVersion, + checkForChanges: function XPI_checkForChanges(aAppChanged, aOldAppVersion, aOldPlatformVersion) { logger.debug("checkForChanges"); @@ -3756,9 +3542,10 @@ this.XPIProvider = { } // If the application has changed then check for new distribution add-ons - if (Preferences.get(PREF_INSTALL_DISTRO_ADDONS, true)) + if (aAppChanged !== false && + Preferences.get(PREF_INSTALL_DISTRO_ADDONS, true)) { - updated = this.installDistributionAddons(manifests, aAppChanged); + updated = this.installDistributionAddons(manifests); if (updated) { updateReasons.push("installDistributionAddons"); } @@ -3798,8 +3585,8 @@ this.XPIProvider = { // XXX This will go away when we fold bootstrappedAddons into XPIStates. if (updateReasons.length == 0) { - let bootstrapDescriptors = new Set(Object.keys(this.bootstrappedAddons) - .map(b => this.bootstrappedAddons[b].descriptor)); + let bootstrapDescriptors = new Set([for (b of Object.keys(this.bootstrappedAddons)) + this.bootstrappedAddons[b].descriptor]); for (let location of XPIStates.db.values()) { for (let state of location.values()) { @@ -3809,7 +3596,7 @@ this.XPIProvider = { if (bootstrapDescriptors.size > 0) { logger.warn("Bootstrap state is invalid (missing add-ons: " - + Array.from(bootstrapDescriptors).join(", ") + ")"); + + [for (b of bootstrapDescriptors) b] + ")"); updateReasons.push("missingBootstrapAddon"); } } @@ -3823,11 +3610,10 @@ this.XPIProvider = { AddonManagerPrivate.recordSimpleMeasure("XPIDB_startup_load_reasons", updateReasons); XPIDatabase.syncLoadDB(false); try { - extensionListChanged = XPIDatabaseReconcile.processFileChanges(manifests, - aAppChanged, - aOldAppVersion, - aOldPlatformVersion, - updateReasons.includes("schemaChanged")); + extensionListChanged = this.processFileChanges(manifests, + aAppChanged, + aOldAppVersion, + aOldPlatformVersion); } catch (e) { logger.error("Failed to process extension changes at startup", e); @@ -3845,8 +3631,8 @@ this.XPIProvider = { // When upgrading remove the old extensions cache to force older // versions to rescan the entire list of extensions - let oldCache = FileUtils.getFile(KEY_PROFILEDIR, [FILE_OLD_CACHE], true); try { + let oldCache = FileUtils.getFile(KEY_PROFILEDIR, [FILE_OLD_CACHE], true); if (oldCache.exists()) oldCache.remove(true); } @@ -3893,7 +3679,7 @@ this.XPIProvider = { * The mimetype to check for * @return true if the mimetype is application/x-xpinstall */ - supportsMimetype: function(aMimetype) { + supportsMimetype: function XPI_supportsMimetype(aMimetype) { return aMimetype == "application/x-xpinstall"; }, @@ -3902,7 +3688,7 @@ this.XPIProvider = { * * @return true if installing is enabled */ - isInstallEnabled: function() { + isInstallEnabled: function XPI_isInstallEnabled() { // Default to enabled if the preference does not exist return Preferences.get(PREF_XPI_ENABLED, true); }, @@ -3913,7 +3699,7 @@ this.XPIProvider = { * * @return true if installing by direct requests is whitelisted */ - isDirectRequestWhitelisted: function() { + isDirectRequestWhitelisted: function XPI_isDirectRequestWhitelisted() { // Default to whitelisted if the preference does not exist. return Preferences.get(PREF_XPI_DIRECT_WHITELISTED, true); }, @@ -3924,7 +3710,7 @@ this.XPIProvider = { * * @return true if installing from file referrers is whitelisted */ - isFileRequestWhitelisted: function() { + isFileRequestWhitelisted: function XPI_isFileRequestWhitelisted() { // Default to whitelisted if the preference does not exist. return Preferences.get(PREF_XPI_FILE_WHITELISTED, true); }, @@ -3936,7 +3722,7 @@ this.XPIProvider = { * The nsIPrincipal that initiated the install * @return true if installing is allowed */ - isInstallAllowed: function(aInstallingPrincipal) { + isInstallAllowed: function XPI_isInstallAllowed(aInstallingPrincipal) { if (!this.isInstallEnabled()) return false; @@ -3987,9 +3773,9 @@ this.XPIProvider = { * @param aCallback * A callback to pass the AddonInstall to */ - getInstallForURL: function(aUrl, aHash, aName, aIcons, aVersion, aBrowser, - aCallback) { - createDownloadInstall(function(aInstall) { + getInstallForURL: function XPI_getInstallForURL(aUrl, aHash, aName, aIcons, + aVersion, aBrowser, aCallback) { + AddonInstall.createDownload(function getInstallForURL_createDownload(aInstall) { aCallback(aInstall.wrapper); }, aUrl, aHash, aName, aIcons, aVersion, aBrowser); }, @@ -4002,190 +3788,29 @@ this.XPIProvider = { * @param aCallback * A callback to pass the AddonInstall to */ - getInstallForFile: function(aFile, aCallback) { - createLocalInstall(aFile).then(install => { - aCallback(install ? install.wrapper : null); - }); - }, - - /** - * Temporarily installs add-on from a local XPI file or directory. - * As this is intended for development, the signature is not checked and - * the add-on does not persist on application restart. - * - * @param aFile - * An nsIFile for the unpacked add-on directory or XPI file. - * - * @return See installAddonFromLocation return value. - */ - installTemporaryAddon: function(aFile) { - return this.installAddonFromLocation(aFile, TemporaryInstallLocation); + getInstallForFile: function XPI_getInstallForFile(aFile, aCallback) { + AddonInstall.createInstall(function getInstallForFile_createInstall(aInstall) { + if (aInstall) + aCallback(aInstall.wrapper); + else + aCallback(null); + }, aFile); }, /** - * Permanently installs add-on from a local XPI file or directory. - * The signature is checked but the add-on persist on application restart. - * - * @param aFile - * An nsIFile for the unpacked add-on directory or XPI file. - * - * @return See installAddonFromLocation return value. - */ - installAddonFromSources: Task.async(function*(aFile) { - let location = XPIProvider.installLocationsByName[KEY_APP_PROFILE]; - return this.installAddonFromLocation(aFile, location, "proxy"); - }), - - /** - * Installs add-on from a local XPI file or directory. - * - * @param aFile - * An nsIFile for the unpacked add-on directory or XPI file. - * @param aInstallLocation - * Define a custom install location object to use for the install. - * @param aInstallAction - * Optional action mode to use when installing the addon - * (see MutableDirectoryInstallLocation.installAddon) - * - * @return a Promise that resolves to an Addon object on success, or rejects - * if the add-on is not a valid restartless add-on or if the - * same ID is already installed. - */ - installAddonFromLocation: Task.async(function*(aFile, aInstallLocation, aInstallAction) { - if (aFile.exists() && aFile.isFile()) { - flushJarCache(aFile); - } - let addon = yield loadManifestFromFile(aFile, aInstallLocation); - - aInstallLocation.installAddon({ id: addon.id, source: aFile, action: aInstallAction }); - - if (addon.appDisabled) { - let message = `Add-on ${addon.id} is not compatible with application version.`; - - let app = addon.matchingTargetApplication; - if (app) { - if (app.minVersion) { - message += ` add-on minVersion: ${app.minVersion}.`; - } - if (app.maxVersion) { - message += ` add-on maxVersion: ${app.maxVersion}.`; - } - } - throw new Error(message); - } - - if (!addon.bootstrap) { - throw new Error("Only restartless (bootstrap) add-ons" - + " can be installed from sources:", addon.id); - } - let installReason = BOOTSTRAP_REASONS.ADDON_INSTALL; - let oldAddon = yield new Promise( - resolve => XPIDatabase.getVisibleAddonForID(addon.id, resolve)); - if (oldAddon) { - if (!oldAddon.bootstrap) { - logger.warn("Non-restartless Add-on is already installed", addon.id); - throw new Error("Non-restartless add-on with ID " - + oldAddon.id + " is already installed"); - } - else { - logger.warn("Addon with ID " + oldAddon.id + " already installed," - + " older version will be disabled"); - - let existingAddonID = oldAddon.id; - let existingAddon = oldAddon._sourceBundle; - - // We'll be replacing a currently active bootstrapped add-on so - // call its uninstall method - let newVersion = addon.version; - let oldVersion = oldAddon.version; - if (Services.vc.compare(newVersion, oldVersion) >= 0) { - installReason = BOOTSTRAP_REASONS.ADDON_UPGRADE; - } else { - installReason = BOOTSTRAP_REASONS.ADDON_DOWNGRADE; - } - let uninstallReason = installReason; - - if (oldAddon.active) { - XPIProvider.callBootstrapMethod(oldAddon, existingAddon, - "shutdown", uninstallReason, - { newVersion }); - } - this.callBootstrapMethod(oldAddon, existingAddon, - "uninstall", uninstallReason, { newVersion }); - this.unloadBootstrapScope(existingAddonID); - flushChromeCaches(); - } - } - - let file = addon._sourceBundle; - - XPIProvider._addURIMapping(addon.id, file); - XPIProvider.callBootstrapMethod(addon, file, "install", installReason); - addon.state = AddonManager.STATE_INSTALLED; - logger.debug("Install of temporary addon in " + aFile.path + " completed."); - addon.visible = true; - addon.enabled = true; - addon.active = true; - - addon = XPIDatabase.addAddonMetadata(addon, file.persistentDescriptor); - - XPIStates.addAddon(addon); - XPIDatabase.saveChanges(); - XPIStates.save(); - - AddonManagerPrivate.callAddonListeners("onInstalling", addon.wrapper, - false); - XPIProvider.callBootstrapMethod(addon, file, "startup", - BOOTSTRAP_REASONS.ADDON_ENABLE); - AddonManagerPrivate.callInstallListeners("onExternalInstall", - null, addon.wrapper, - oldAddon ? oldAddon.wrapper : null, - false); - AddonManagerPrivate.callAddonListeners("onInstalled", addon.wrapper); - - return addon.wrapper; - }), - - /** - * Returns an Addon corresponding to an instance ID. - * @param aInstanceID - * An Addon Instance ID - * @return {Promise} - * @resolves The found Addon or null if no such add-on exists. - * @rejects Never - * @throws if the aInstanceID argument is not specified - */ - getAddonByInstanceID: function(aInstanceID) { - if (!aInstanceID || typeof aInstanceID != "symbol") - throw Components.Exception("aInstanceID must be a Symbol()", - Cr.NS_ERROR_INVALID_ARG); - - for (let [id, val] of this.activeAddons) { - if (aInstanceID == val.instanceID) { - if (val.safeWrapper) { - return Promise.resolve(val.safeWrapper); - } - - return new Promise(resolve => { - this.getAddonByID(id, function(addon) { - val.safeWrapper = new PrivateWrapper(addon); - resolve(val.safeWrapper); - }); - }); - } - } - - return Promise.resolve(null); - }, - - /** * Removes an AddonInstall from the list of active installs. * * @param install * The AddonInstall to remove */ - removeActiveInstall: function(aInstall) { - this.installs.delete(aInstall); + removeActiveInstall: function XPI_removeActiveInstall(aInstall) { + let where = this.installs.indexOf(aInstall); + if (where == -1) { + logger.warn("removeActiveInstall: could not find active install for " + + aInstall.sourceURI.spec); + return; + } + this.installs.splice(where, 1); }, /** @@ -4196,9 +3821,9 @@ this.XPIProvider = { * @param aCallback * A callback to pass the Addon to */ - getAddonByID: function(aId, aCallback) { - XPIDatabase.getVisibleAddonForID (aId, function(aAddon) { - aCallback(aAddon ? aAddon.wrapper : null); + getAddonByID: function XPI_getAddonByID(aId, aCallback) { + XPIDatabase.getVisibleAddonForID (aId, function getAddonByID_getVisibleAddonForID(aAddon) { + aCallback(createWrapper(aAddon)); }); }, @@ -4210,11 +3835,14 @@ this.XPIProvider = { * @param aCallback * A callback to pass an array of Addons to */ - getAddonsByTypes: function(aTypes, aCallback) { - let typesToGet = getAllAliasesForTypes(aTypes); - - XPIDatabase.getVisibleAddons(typesToGet, function(aAddons) { - aCallback(aAddons.map(a => a.wrapper)); + getAddonsByTypes: function XPI_getAddonsByTypes(aTypes, aCallback) { + XPIDatabase.getVisibleAddons(aTypes, function getAddonsByTypes_getVisibleAddons(aAddons) { + // Tycho: aCallback([createWrapper(a) for each (a in aAddons)]); + let result = []; + for each(let a in aAddons) { + result.push(createWrapper(a)); + } + aCallback(result); }); }, @@ -4226,9 +3854,9 @@ this.XPIProvider = { * @param aCallback * A callback to pass the Addon to. Receives null if not found. */ - getAddonBySyncGUID: function(aGUID, aCallback) { - XPIDatabase.getAddonBySyncGUID(aGUID, function(aAddon) { - aCallback(aAddon ? aAddon.wrapper : null); + getAddonBySyncGUID: function XPI_getAddonBySyncGUID(aGUID, aCallback) { + XPIDatabase.getAddonBySyncGUID(aGUID, function getAddonBySyncGUID_getAddonBySyncGUID(aAddon) { + aCallback(createWrapper(aAddon)); }); }, @@ -4240,16 +3868,21 @@ this.XPIProvider = { * @param aCallback * A callback to pass an array of Addons to */ - getAddonsWithOperationsByTypes: function(aTypes, aCallback) { - let typesToGet = getAllAliasesForTypes(aTypes); - - XPIDatabase.getVisibleAddonsWithPendingOperations(typesToGet, function(aAddons) { - let results = aAddons.map(a => a.wrapper); - for (let install of XPIProvider.installs) { - if (install.state == AddonManager.STATE_INSTALLED && - !(install.addon.inDatabase)) - results.push(install.addon.wrapper); - } + getAddonsWithOperationsByTypes: + function XPI_getAddonsWithOperationsByTypes(aTypes, aCallback) { + XPIDatabase.getVisibleAddonsWithPendingOperations(aTypes, + function getAddonsWithOpsByTypes_getVisibleAddonsWithPendingOps(aAddons) { + // Tycho: let results = [createWrapper(a) for each (a in aAddons)]; + let results = []; + for each(let a in aAddons) { + results.push(createWrapper(a)); + } + + XPIProvider.installs.forEach(function(aInstall) { + if (aInstall.state == AddonManager.STATE_INSTALLED && + !(aInstall.addon.inDatabase)) + results.push(createWrapper(aInstall.addon)); + }); aCallback(results); }); }, @@ -4263,15 +3896,13 @@ this.XPIProvider = { * @param aCallback * A callback to pass the array of AddonInstalls to */ - getInstallsByTypes: function(aTypes, aCallback) { - let results = [...this.installs]; - if (aTypes) { - results = results.filter(install => { - return aTypes.includes(getExternalType(install.type)); - }); - } - - aCallback(results.map(install => install.wrapper)); + getInstallsByTypes: function XPI_getInstallsByTypes(aTypes, aCallback) { + let results = []; + this.installs.forEach(function(aInstall) { + if (!aTypes || aTypes.indexOf(aInstall.type) >= 0) + results.push(aInstall.wrapper); + }); + aCallback(results); }, /** @@ -4287,7 +3918,7 @@ this.XPIProvider = { * @see AddonManager.mapURIToAddonID * @see amIAddonManager.mapURIToAddonID */ - mapURIToAddonID: function(aURI) { + mapURIToAddonID: function XPI_mapURIToAddonID(aURI) { // Returns `null` instead of empty string if the URI can't be mapped. return AddonPathService.mapURIToAddonId(aURI) || null; }, @@ -4304,7 +3935,7 @@ this.XPIProvider = { * true if the newly enabled add-on will only become enabled after a * restart */ - addonChanged: function(aId, aType, aPendingRestart) { + addonChanged: function XPI_addonChanged(aId, aType, aPendingRestart) { // We only care about themes in this provider if (aType != "theme") return; @@ -4320,14 +3951,14 @@ this.XPIProvider = { let previousTheme = null; let newSkin = this.defaultSkin; let addons = XPIDatabase.getAddonsByType("theme"); - for (let theme of addons) { - if (!theme.visible) + addons.forEach(function(aTheme) { + if (!aTheme.visible) return; - if (theme.id == aId) - newSkin = theme.internalName; - else if (theme.userDisabled == false && !theme.pendingUninstall) - previousTheme = theme; - } + if (aTheme.id == aId) + newSkin = aTheme.internalName; + else if (aTheme.userDisabled == false && !aTheme.pendingUninstall) + previousTheme = aTheme; + }, this); if (aPendingRestart) { Services.prefs.setBoolPref(PREF_DSS_SWITCHPENDING, true); @@ -4362,11 +3993,11 @@ this.XPIProvider = { /** * Update the appDisabled property for all add-ons. */ - updateAddonAppDisabledStates: function() { + updateAddonAppDisabledStates: function XPI_updateAddonAppDisabledStates() { let addons = XPIDatabase.getAddons(); - for (let addon of addons) { - this.updateAddonDisabledState(addon); - } + addons.forEach(function(aAddon) { + this.updateAddonDisabledState(aAddon); + }, this); }, /** @@ -4375,8 +4006,9 @@ this.XPIProvider = { * @param aCallback * Function to call when operation is complete. */ - updateAddonRepositoryData: function(aCallback) { - XPIDatabase.getVisibleAddons(null, aAddons => { + updateAddonRepositoryData: function XPI_updateAddonRepositoryData(aCallback) { + let self = this; + XPIDatabase.getVisibleAddons(null, function UARD_getVisibleAddonsCallback(aAddons) { let pending = aAddons.length; logger.debug("updateAddonRepositoryData found " + pending + " visible add-ons"); if (pending == 0) { @@ -4390,17 +4022,18 @@ this.XPIProvider = { } for (let addon of aAddons) { - AddonRepository.getCachedAddonByID(addon.id, aRepoAddon => { + AddonRepository.getCachedAddonByID(addon.id, + function UARD_getCachedAddonCallback(aRepoAddon) { if (aRepoAddon) { logger.debug("updateAddonRepositoryData got info for " + addon.id); addon._repositoryAddon = aRepoAddon; addon.compatibilityOverrides = aRepoAddon.compatibilityOverrides; - this.updateAddonDisabledState(addon); + self.updateAddonDisabledState(addon); } notifyComplete(); }); - } + }; }); }, @@ -4408,7 +4041,7 @@ this.XPIProvider = { * When the previously selected theme is removed this method will be called * to enable the default theme. */ - enableDefaultTheme: function() { + enableDefaultTheme: function XPI_enableDefaultTheme() { logger.debug("Activating default theme"); let addon = XPIDatabase.getVisibleAddonForInternalName(this.defaultSkin); if (addon) { @@ -4438,9 +4071,8 @@ this.XPIProvider = { if (aWhat != "opened") return; - for (let [id, val] of this.activeAddons) { - aConnection.setAddonOptions( - id, { global: val.debugGlobal || val.bootstrapScope }); + for (let id of Object.keys(this.bootstrapScopes)) { + aConnection.setAddonOptions(id, { global: this.bootstrapScopes[id] }); } }, @@ -4449,7 +4081,7 @@ this.XPIProvider = { * * @see nsIObserver */ - observe: function(aSubject, aTopic, aData) { + observe: function XPI_observe(aSubject, aTopic, aData) { if (aTopic == NOTIFICATION_FLUSH_PERMISSIONS) { if (!aData || aData == XPI_PERMISSION) { this.importPermissions(); @@ -4466,95 +4098,25 @@ this.XPIProvider = { if (aTopic == "nsPref:changed") { switch (aData) { case PREF_EM_MIN_COMPAT_APP_VERSION: + case PREF_EM_MIN_COMPAT_PLATFORM_VERSION: this.minCompatibleAppVersion = Preferences.get(PREF_EM_MIN_COMPAT_APP_VERSION, null); - this.updateAddonAppDisabledStates(); - break; - case PREF_EM_MIN_COMPAT_PLATFORM_VERSION: this.minCompatiblePlatformVersion = Preferences.get(PREF_EM_MIN_COMPAT_PLATFORM_VERSION, null); this.updateAddonAppDisabledStates(); break; - case PREF_XPI_SIGNATURES_REQUIRED: - this.updateAddonAppDisabledStates(); - break; - - case PREF_E10S_ADDON_BLOCKLIST: - case PREF_E10S_ADDON_POLICY: - XPIDatabase.updateAddonsBlockingE10s(); - break; } } }, /** - * Determine if an add-on should be blocking e10s if enabled. - * - * @param aAddon - * The add-on to test - * @return true if enabling the add-on should block e10s - */ - isBlockingE10s: function(aAddon) { - if (aAddon.type != "extension" && - aAddon.type != "webextension" && - aAddon.type != "theme") - return false; - - // The hotfix is exempt - let hotfixID = Preferences.get(PREF_EM_HOTFIX_ID, undefined); - if (hotfixID && hotfixID == aAddon.id) - return false; - - // The default theme is exempt - if (aAddon.type == "theme" && - aAddon.internalName == XPIProvider.defaultSkin) - return false; - - // System add-ons are exempt - let locName = aAddon._installLocation ? aAddon._installLocation.name - : undefined; - if (locName == KEY_APP_SYSTEM_DEFAULTS || - locName == KEY_APP_SYSTEM_ADDONS) - return false; - - if (isAddonPartOfE10SRollout(aAddon)) { - Preferences.set(PREF_E10S_HAS_NONEXEMPT_ADDON, true); - return false; - } - - logger.debug("Add-on " + aAddon.id + " blocks e10s rollout."); - return true; - }, - - /** - * In some cases having add-ons active blocks e10s but turning off e10s - * requires a restart so some add-ons that are normally restartless will - * require a restart to install or enable. - * - * @param aAddon - * The add-on to test - * @return true if enabling the add-on requires a restart - */ - e10sBlocksEnabling: function(aAddon) { - // If the preference isn't set then don't block anything - if (!Preferences.get(PREF_E10S_BLOCK_ENABLE, false)) - return false; - - // If e10s isn't active then don't block anything - if (!Services.appinfo.browserTabsRemoteAutostart) - return false; - - return this.isBlockingE10s(aAddon); - }, - - /** * Tests whether enabling an add-on will require a restart. * * @param aAddon * The add-on to test * @return true if the operation requires a restart */ - enableRequiresRestart: function(aAddon) { + enableRequiresRestart: function XPI_enableRequiresRestart(aAddon) { // If the platform couldn't have activated extensions then we can make // changes without any restart. if (!this.extensionsActive) @@ -4581,9 +4143,6 @@ this.XPIProvider = { return aAddon.internalName != this.currentSkin; } - if (this.e10sBlocksEnabling(aAddon)) - return true; - return !aAddon.bootstrap; }, @@ -4594,7 +4153,7 @@ this.XPIProvider = { * The add-on to test * @return true if the operation requires a restart */ - disableRequiresRestart: function(aAddon) { + disableRequiresRestart: function XPI_disableRequiresRestart(aAddon) { // If the platform couldn't have activated up extensions then we can make // changes without any restart. if (!this.extensionsActive) @@ -4640,7 +4199,7 @@ this.XPIProvider = { * The add-on to test * @return true if the operation requires a restart */ - installRequiresRestart: function(aAddon) { + installRequiresRestart: function XPI_installRequiresRestart(aAddon) { // If the platform couldn't have activated up extensions then we can make // changes without any restart. if (!this.extensionsActive) @@ -4674,9 +4233,6 @@ this.XPIProvider = { if (aAddon.disabled) return false; - if (this.e10sBlocksEnabling(aAddon)) - return true; - // Themes will require a restart (even if dynamic switching is enabled due // to some caching issues) and non-bootstrapped add-ons will require a // restart @@ -4690,7 +4246,7 @@ this.XPIProvider = { * The add-on to test * @return true if the operation requires a restart */ - uninstallRequiresRestart: function(aAddon) { + uninstallRequiresRestart: function XPI_uninstallRequiresRestart(aAddon) { // If the platform couldn't have activated up extensions then we can make // changes without any restart. if (!this.extensionsActive) @@ -4722,41 +4278,23 @@ this.XPIProvider = { * The type for the add-on * @param aMultiprocessCompatible * Boolean indicating whether the add-on is compatible with electrolysis. - * @param aRunInSafeMode - * Boolean indicating whether the add-on can run in safe mode. - * @param aDependencies - * An array of add-on IDs on which this add-on depends. - * @param hasEmbeddedWebExtension - * Boolean indicating whether the add-on has an embedded webextension. * @return a JavaScript scope */ - loadBootstrapScope: function(aId, aFile, aVersion, aType, - aMultiprocessCompatible, aRunInSafeMode, - aDependencies, hasEmbeddedWebExtension) { + loadBootstrapScope: function XPI_loadBootstrapScope(aId, aFile, aVersion, aType, + aMultiprocessCompatible) { // Mark the add-on as active for the crash reporter before loading this.bootstrappedAddons[aId] = { version: aVersion, type: aType, descriptor: aFile.persistentDescriptor, - multiprocessCompatible: aMultiprocessCompatible, - runInSafeMode: aRunInSafeMode, - dependencies: aDependencies, - hasEmbeddedWebExtension, + multiprocessCompatible: aMultiprocessCompatible }; this.persistBootstrappedAddons(); this.addAddonsToCrashReporter(); - this.activeAddons.set(aId, { - debugGlobal: null, - safeWrapper: null, - bootstrapScope: null, - // a Symbol passed to this add-on, which it can use to identify itself - instanceID: Symbol(aId), - }); - let activeAddon = this.activeAddons.get(aId); - // Locales only contain chrome and can't have bootstrap scripts if (aType == "locale") { + this.bootstrapScopes[aId] = null; return; } @@ -4768,11 +4306,10 @@ this.XPIProvider = { let interposition = Cc["@mozilla.org/addons/multiprocess-shims;1"]. getService(Ci.nsIAddonInterposition); Cu.setAddonInterposition(aId, interposition); - Cu.allowCPOWsInAddon(aId, true); } if (!aFile.exists()) { - activeAddon.bootstrapScope = + this.bootstrapScopes[aId] = new Cu.Sandbox(principal, { sandboxName: aFile.path, wantGlobalProperties: ["indexedDB"], addonId: aId, @@ -4784,12 +4321,8 @@ this.XPIProvider = { let uri = getURIForResourceInFile(aFile, "bootstrap.js").spec; if (aType == "dictionary") uri = "resource://gre/modules/addons/SpellCheckDictionaryBootstrap.js" - else if (aType == "webextension") - uri = "resource://gre/modules/addons/WebExtensionBootstrap.js" - else if (aType == "apiextension") - uri = "resource://gre/modules/addons/APIExtensionBootstrap.js" - activeAddon.bootstrapScope = + this.bootstrapScopes[aId] = new Cu.Sandbox(principal, { sandboxName: uri, wantGlobalProperties: ["indexedDB"], addonId: aId, @@ -4801,27 +4334,25 @@ this.XPIProvider = { try { // Copy the reason values from the global object into the bootstrap scope. for (let name in BOOTSTRAP_REASONS) - activeAddon.bootstrapScope[name] = BOOTSTRAP_REASONS[name]; + this.bootstrapScopes[aId][name] = BOOTSTRAP_REASONS[name]; // Add other stuff that extensions want. const features = [ "Worker", "ChromeWorker" ]; for (let feature of features) - activeAddon.bootstrapScope[feature] = gGlobalScope[feature]; + this.bootstrapScopes[aId][feature] = gGlobalScope[feature]; // Define a console for the add-on - activeAddon.bootstrapScope["console"] = new ConsoleAPI( - { consoleID: "addon/" + aId }); + this.bootstrapScopes[aId]["console"] = new ConsoleAPI({ consoleID: "addon/" + aId }); // As we don't want our caller to control the JS version used for the // bootstrap file, we run loadSubScript within the context of the // sandbox with the latest JS version set explicitly. - activeAddon.bootstrapScope.__SCRIPT_URI_SPEC__ = uri; + this.bootstrapScopes[aId].__SCRIPT_URI_SPEC__ = uri; Components.utils.evalInSandbox( "Components.classes['@mozilla.org/moz/jssubscript-loader;1'] \ .createInstance(Components.interfaces.mozIJSSubScriptLoader) \ - .loadSubScript(__SCRIPT_URI_SPEC__);", - activeAddon.bootstrapScope, "ECMAv5"); + .loadSubScript(__SCRIPT_URI_SPEC__);", this.bootstrapScopes[aId], "ECMAv5"); } catch (e) { logger.warn("Error loading bootstrap.js for " + aId, e); @@ -4831,8 +4362,7 @@ this.XPIProvider = { // initialized as otherwise, when it will be initialized, all addons' // globals will be added anyways if (this._toolboxProcessLoaded) { - BrowserToolboxProcess.setAddonOptions(aId, - { global: activeAddon.bootstrapScope }); + BrowserToolboxProcess.setAddonOptions(aId, { global: this.bootstrapScopes[aId] }); } }, @@ -4843,13 +4373,12 @@ this.XPIProvider = { * @param aId * The add-on's ID */ - unloadBootstrapScope: function(aId) { + unloadBootstrapScope: function XPI_unloadBootstrapScope(aId) { // In case the add-on was not multiprocess-compatible, deregister // any interpositions for it. Cu.setAddonInterposition(aId, null); - Cu.allowCPOWsInAddon(aId, false); - this.activeAddons.delete(aId); + delete this.bootstrapScopes[aId]; delete this.bootstrappedAddons[aId]; this.persistBootstrappedAddons(); this.addAddonsToCrashReporter(); @@ -4876,39 +4405,27 @@ this.XPIProvider = { * An object of additional key/value pairs to pass to the method in * the params argument */ - callBootstrapMethod: function(aAddon, aFile, aMethod, aReason, aExtraParams) { - if (!aAddon.id || !aAddon.version || !aAddon.type) { - throw new Error("aAddon must include an id, version, and type"); - } + callBootstrapMethod: function XPI_callBootstrapMethod(aAddon, aFile, aMethod, aReason, aExtraParams) { + // Never call any bootstrap methods in safe mode + if (Services.appinfo.inSafeMode) + return; - // Only run in safe mode if allowed to - let runInSafeMode = "runInSafeMode" in aAddon ? aAddon.runInSafeMode : canRunInSafeMode(aAddon); - if (Services.appinfo.inSafeMode && !runInSafeMode) + if (!aAddon.id || !aAddon.version || !aAddon.type) { + logger.error(new Error("aAddon must include an id, version, and type")); return; + } let timeStart = new Date(); - if (CHROME_TYPES.has(aAddon.type) && aMethod == "startup") { + if (aMethod == "startup") { logger.debug("Registering manifest for " + aFile.path); Components.manager.addBootstrappedManifestLocation(aFile); } try { // Load the scope if it hasn't already been loaded - let activeAddon = this.activeAddons.get(aAddon.id); - if (!activeAddon) { + if (!(aAddon.id in this.bootstrapScopes)) this.loadBootstrapScope(aAddon.id, aFile, aAddon.version, aAddon.type, - aAddon.multiprocessCompatible || false, - runInSafeMode, aAddon.dependencies, - aAddon.hasEmbeddedWebExtension || false); - activeAddon = this.activeAddons.get(aAddon.id); - } - - if (aMethod == "startup" || aMethod == "shutdown") { - if (!aExtraParams) { - aExtraParams = {}; - } - aExtraParams["instanceID"] = this.activeAddons.get(aAddon.id).instanceID; - } + aAddon.multiprocessCompatible || false); // Nothing to call for locales if (aAddon.type == "locale") @@ -4917,7 +4434,8 @@ this.XPIProvider = { let method = undefined; try { method = Components.utils.evalInSandbox(`${aMethod};`, - activeAddon.bootstrapScope, "ECMAv5"); + this.bootstrapScopes[aAddon.id], + "ECMAv5"); } catch (e) { // An exception will be caught if the expected method is not defined. @@ -4929,15 +4447,6 @@ this.XPIProvider = { return; } - // Extensions are automatically deinitialized in the correct order at shutdown. - if (aMethod == "shutdown" && aReason != BOOTSTRAP_REASONS.APP_SHUTDOWN) { - activeAddon.disable = true; - for (let addon of this.getDependentAddons(aAddon)) { - if (addon.active) - this.updateAddonDisabledState(addon); - } - } - let params = { id: aAddon.id, version: aAddon.version, @@ -4951,19 +4460,8 @@ this.XPIProvider = { } } - if (aAddon.hasEmbeddedWebExtension) { - if (aMethod == "startup") { - const webExtension = LegacyExtensionsUtils.getEmbeddedExtensionFor(params); - params.webExtension = { - startup: () => webExtension.startup(), - }; - } else if (aMethod == "shutdown") { - LegacyExtensionsUtils.getEmbeddedExtensionFor(params).shutdown(); - } - } - logger.debug("Calling bootstrap method " + aMethod + " on " + aAddon.id + " version " + - aAddon.version); + aAddon.version); try { method(params, aReason); } @@ -4972,13 +4470,7 @@ this.XPIProvider = { } } finally { - // Extensions are automatically initialized in the correct order at startup. - if (aMethod == "startup" && aReason != BOOTSTRAP_REASONS.APP_STARTUP) { - for (let addon of this.getDependentAddons(aAddon)) - this.updateAddonDisabledState(addon); - } - - if (CHROME_TYPES.has(aAddon.type) && aMethod == "shutdown" && aReason != BOOTSTRAP_REASONS.APP_SHUTDOWN) { + if (aMethod == "shutdown" && aReason != BOOTSTRAP_REASONS.APP_SHUTDOWN) { logger.debug("Removing manifest for " + aFile.path); Components.manager.removeBootstrappedManifestLocation(aFile); @@ -4989,7 +4481,6 @@ this.XPIProvider = { } } } - this.setTelemetry(aAddon.id, aMethod + "_MS", new Date() - timeStart); } }, @@ -5006,13 +4497,11 @@ this.XPIProvider = { * @param aSoftDisabled * Value for the softDisabled property. If undefined the value will * not change. If true this will force userDisabled to be true - * @return a tri-state indicating the action taken for the add-on: - * - undefined: The add-on did not change state - * - true: The add-on because disabled - * - false: The add-on became enabled * @throws if addon is not a DBAddonInternal */ - updateAddonDisabledState: function(aAddon, aUserDisabled, aSoftDisabled) { + updateAddonDisabledState: function XPI_updateAddonDisabledState(aAddon, + aUserDisabled, + aSoftDisabled) { if (!(aAddon.inDatabase)) throw new Error("Can only update addon states for installed addons."); if (aUserDisabled !== undefined && aSoftDisabled !== undefined) { @@ -5038,7 +4527,7 @@ this.XPIProvider = { if (aAddon.userDisabled == aUserDisabled && aAddon.appDisabled == appDisabled && aAddon.softDisabled == aSoftDisabled) - return undefined; + return; let wasDisabled = aAddon.disabled; let isDisabled = aUserDisabled || aSoftDisabled || appDisabled; @@ -5048,28 +4537,31 @@ this.XPIProvider = { let appDisabledChanged = aAddon.appDisabled != appDisabled; // Update the properties in the database. - XPIDatabase.setAddonProperties(aAddon, { - userDisabled: aUserDisabled, - appDisabled: appDisabled, - softDisabled: aSoftDisabled - }); - - let wrapper = aAddon.wrapper; + // We never persist this for experiments because the disabled flags + // are controlled by the Experiments Manager. + if (aAddon.type != "experiment") { + XPIDatabase.setAddonProperties(aAddon, { + userDisabled: aUserDisabled, + appDisabled: appDisabled, + softDisabled: aSoftDisabled + }); + } if (appDisabledChanged) { AddonManagerPrivate.callAddonListeners("onPropertyChanged", - wrapper, - ["appDisabled"]); + aAddon, + ["appDisabled"]); } // If the add-on is not visible or the add-on is not changing state then // there is no need to do anything else if (!aAddon.visible || (wasDisabled == isDisabled)) - return undefined; + return; // Flag that active states in the database need to be updated on shutdown Services.prefs.setBoolPref(PREF_PENDING_OPERATIONS, true); + let wrapper = createWrapper(aAddon); // Have we just gone back to the current state? if (isDisabled != aAddon.active) { AddonManagerPrivate.callAddonListeners("onOperationCancelled", wrapper); @@ -5088,10 +4580,10 @@ this.XPIProvider = { if (!needsRestart) { XPIDatabase.updateAddonActive(aAddon, !isDisabled); - if (isDisabled) { if (aAddon.bootstrap) { - this.callBootstrapMethod(aAddon, aAddon._sourceBundle, "shutdown", + let file = aAddon._installLocation.getLocationForID(aAddon.id); + this.callBootstrapMethod(aAddon, file, "shutdown", BOOTSTRAP_REASONS.ADDON_DISABLE); this.unloadBootstrapScope(aAddon.id); } @@ -5099,31 +4591,13 @@ this.XPIProvider = { } else { if (aAddon.bootstrap) { - this.callBootstrapMethod(aAddon, aAddon._sourceBundle, "startup", + let file = aAddon._installLocation.getLocationForID(aAddon.id); + this.callBootstrapMethod(aAddon, file, "startup", BOOTSTRAP_REASONS.ADDON_ENABLE); } AddonManagerPrivate.callAddonListeners("onEnabled", wrapper); } } - else if (aAddon.bootstrap) { - // Something blocked the restartless add-on from enabling or disabling - // make sure it happens on the next startup - if (isDisabled) { - this.bootstrappedAddons[aAddon.id].disable = true; - } - else { - this.bootstrappedAddons[aAddon.id] = { - version: aAddon.version, - type: aAddon.type, - descriptor: aAddon._sourceBundle.persistentDescriptor, - multiprocessCompatible: aAddon.multiprocessCompatible, - runInSafeMode: canRunInSafeMode(aAddon), - dependencies: aAddon.dependencies, - hasEmbeddedWebExtension: aAddon.hasEmbeddedWebExtension, - }; - this.persistBootstrappedAddons(); - } - } } // Sync with XPIStates. @@ -5139,8 +4613,6 @@ this.XPIProvider = { // Notify any other providers that a new theme has been enabled if (aAddon.type == "theme" && !isDisabled) AddonManagerPrivate.notifyAddonChanged(aAddon.id, aAddon.type, needsRestart); - - return isDisabled; }, /** @@ -5156,7 +4628,7 @@ this.XPIProvider = { * @throws if the addon cannot be uninstalled because it is in an install * location that does not allow it */ - uninstallAddon: function(aAddon, aForcePending) { + uninstallAddon: function XPI_uninstallAddon(aAddon, aForcePending) { if (!(aAddon.inDatabase)) throw new Error("Cannot uninstall addon " + aAddon.id + " because it is not installed"); @@ -5174,7 +4646,8 @@ this.XPIProvider = { if (makePending && aAddon.pendingUninstall) throw new Error("Add-on is already marked to be uninstalled"); - aAddon._hasResourceCache.clear(); + if ("_hasResourceCache" in aAddon) + aAddon._hasResourceCache = new Map(); if (aAddon._updateCheck) { logger.debug("Cancel in-progress update check for " + aAddon.id); @@ -5185,15 +4658,11 @@ this.XPIProvider = { if (makePending) { // We create an empty directory in the staging directory to indicate - // that an uninstall is necessary on next startup. Temporary add-ons are - // automatically uninstalled on shutdown anyway so there is no need to - // do this for them. - if (aAddon._installLocation.name != KEY_APP_TEMPORARY) { - let stage = aAddon._installLocation.getStagingDir(); - stage.append(aAddon.id); - if (!stage.exists()) - stage.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY); - } + // that an uninstall is necessary on next startup. + let stage = aAddon._installLocation.getStagingDir(); + stage.append(aAddon.id); + if (!stage.exists()) + stage.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY); XPIDatabase.setAddonProperties(aAddon, { pendingUninstall: true @@ -5212,7 +4681,7 @@ this.XPIProvider = { if (!aAddon.visible) return; - let wrapper = aAddon.wrapper; + let wrapper = createWrapper(aAddon); // If the add-on wasn't already pending uninstall then notify listeners. if (!wasPending) { @@ -5228,7 +4697,7 @@ this.XPIProvider = { function revealAddon(aAddon) { XPIDatabase.makeAddonVisible(aAddon); - let wrappedAddon = aAddon.wrapper; + let wrappedAddon = createWrapper(aAddon); AddonManagerPrivate.callAddonListeners("onInstalling", wrappedAddon, false); if (!aAddon.disabled && !XPIProvider.enableRequiresRestart(aAddon)) { @@ -5236,11 +4705,12 @@ this.XPIProvider = { } if (aAddon.bootstrap) { - XPIProvider.callBootstrapMethod(aAddon, aAddon._sourceBundle, + let file = aAddon._installLocation.getLocationForID(aAddon.id); + XPIProvider.callBootstrapMethod(aAddon, file, "install", BOOTSTRAP_REASONS.ADDON_INSTALL); if (aAddon.active) { - XPIProvider.callBootstrapMethod(aAddon, aAddon._sourceBundle, + XPIProvider.callBootstrapMethod(aAddon, file, "startup", BOOTSTRAP_REASONS.ADDON_INSTALL); } else { @@ -5262,15 +4732,16 @@ this.XPIProvider = { if (!makePending) { if (aAddon.bootstrap) { + let file = aAddon._installLocation.getLocationForID(aAddon.id); if (aAddon.active) { - this.callBootstrapMethod(aAddon, aAddon._sourceBundle, "shutdown", + this.callBootstrapMethod(aAddon, file, "shutdown", BOOTSTRAP_REASONS.ADDON_UNINSTALL); } - this.callBootstrapMethod(aAddon, aAddon._sourceBundle, "uninstall", + this.callBootstrapMethod(aAddon, file, "uninstall", BOOTSTRAP_REASONS.ADDON_UNINSTALL); this.unloadBootstrapScope(aAddon.id); - flushChromeCaches(); + flushStartupCache(); } aAddon._installLocation.uninstallAddon(aAddon.id); XPIDatabase.removeAddonMetadata(aAddon); @@ -5297,14 +4768,14 @@ this.XPIProvider = { * @param aAddon * The DBAddonInternal to cancel uninstall for */ - cancelUninstallAddon: function(aAddon) { + cancelUninstallAddon: function XPI_cancelUninstallAddon(aAddon) { if (!(aAddon.inDatabase)) throw new Error("Can only cancel uninstall for installed addons."); + if (!aAddon.pendingUninstall) throw new Error("Add-on is not marked to be uninstalled"); - if (aAddon._installLocation.name != KEY_APP_TEMPORARY) - aAddon._installLocation.cleanStagingDir([aAddon.id]); + aAddon._installLocation.cleanStagingDir([aAddon.id]); XPIDatabase.setAddonProperties(aAddon, { pendingUninstall: false @@ -5316,7 +4787,7 @@ this.XPIProvider = { Services.prefs.setBoolPref(PREF_PENDING_OPERATIONS, true); // TODO hide hidden add-ons (bug 557710) - let wrapper = aAddon.wrapper; + let wrapper = createWrapper(aAddon); AddonManagerPrivate.callAddonListeners("onOperationCancelled", wrapper); if (aAddon.bootstrap && !aAddon.disabled && !this.enableRequiresRestart(aAddon)) { @@ -5342,81 +4813,262 @@ function getHashStringForCrypto(aCrypto) { } /** - * Base class for objects that manage the installation of an addon. - * This class isn't instantiated directly, see the derived classes below. + * Instantiates an AddonInstall. + * + * @param aInstallLocation + * The install location the add-on will be installed into + * @param aUrl + * The nsIURL to get the add-on from. If this is an nsIFileURL then + * the add-on will not need to be downloaded + * @param aHash + * An optional hash for the add-on + * @param aReleaseNotesURI + * An optional nsIURI of release notes for the add-on + * @param aExistingAddon + * The add-on this install will update if known + * @param aBrowser + * The browser performing the install + * @throws if the url is the url of a local file and the hash does not match + * or the add-on does not contain an valid install manifest */ -class AddonInstall { +function AddonInstall(aInstallLocation, aUrl, aHash, aReleaseNotesURI, + aExistingAddon, aBrowser) { + this.wrapper = new AddonInstallWrapper(this); + this.installLocation = aInstallLocation; + this.sourceURI = aUrl; + this.releaseNotesURI = aReleaseNotesURI; + if (aHash) { + let hashSplit = aHash.toLowerCase().split(":"); + this.originalHash = { + algorithm: hashSplit[0], + data: hashSplit[1] + }; + } + this.hash = this.originalHash; + this.browser = aBrowser; + this.listeners = []; + this.icons = {}; + this.existingAddon = aExistingAddon; + this.error = 0; + this.window = aBrowser ? aBrowser.contentWindow : null; + + // Giving each instance of AddonInstall a reference to the logger. + this.logger = logger; +} + +AddonInstall.prototype = { + installLocation: null, + wrapper: null, + stream: null, + crypto: null, + originalHash: null, + hash: null, + browser: null, + badCertHandler: null, + listeners: null, + restartDownload: false, + + name: null, + type: null, + version: null, + icons: null, + releaseNotesURI: null, + sourceURI: null, + file: null, + ownsTempFile: false, + certificate: null, + certName: null, + + linkedInstalls: null, + existingAddon: null, + addon: null, + + state: null, + error: null, + progress: null, + maxProgress: null, + /** - * Instantiates an AddonInstall. + * Initialises this install to be a staged install waiting to be applied * - * @param aInstallLocation - * The install location the add-on will be installed into - * @param aUrl - * The nsIURL to get the add-on from. If this is an nsIFileURL then - * the add-on will not need to be downloaded - * @param aHash - * An optional hash for the add-on - * @param aExistingAddon - * The add-on this install will update if known + * @param aManifest + * The cached manifest for the staged install + */ + initStagedInstall: function AI_initStagedInstall(aManifest) { + this.name = aManifest.name; + this.type = aManifest.type; + this.version = aManifest.version; + this.icons = aManifest.icons; + this.releaseNotesURI = aManifest.releaseNotesURI ? + NetUtil.newURI(aManifest.releaseNotesURI) : + null + this.sourceURI = aManifest.sourceURI ? + NetUtil.newURI(aManifest.sourceURI) : + null; + this.file = null; + this.addon = aManifest; + + this.state = AddonManager.STATE_INSTALLED; + + XPIProvider.installs.push(this); + }, + + /** + * Initialises this install to be an install from a local file. + * + * @param aCallback + * The callback to pass the initialised AddonInstall to */ - constructor(aInstallLocation, aUrl, aHash, aExistingAddon) { - this.wrapper = new AddonInstallWrapper(this); - this.installLocation = aInstallLocation; - this.sourceURI = aUrl; - - if (aHash) { - let hashSplit = aHash.toLowerCase().split(":"); - this.originalHash = { - algorithm: hashSplit[0], - data: hashSplit[1] - }; + initLocalInstall: function AI_initLocalInstall(aCallback) { + aCallback = makeSafe(aCallback); + this.file = this.sourceURI.QueryInterface(Ci.nsIFileURL).file; + + if (!this.file.exists()) { + logger.warn("XPI file " + this.file.path + " does not exist"); + this.state = AddonManager.STATE_DOWNLOAD_FAILED; + this.error = AddonManager.ERROR_NETWORK_FAILURE; + aCallback(this); + return; } - this.hash = this.originalHash; - this.existingAddon = aExistingAddon; - this.releaseNotesURI = null; - this.listeners = []; - this.icons = {}; - this.error = 0; + this.state = AddonManager.STATE_DOWNLOADED; + this.progress = this.file.fileSize; + this.maxProgress = this.file.fileSize; - this.progress = 0; - this.maxProgress = -1; + if (this.hash) { + let crypto = Cc["@mozilla.org/security/hash;1"]. + createInstance(Ci.nsICryptoHash); + try { + crypto.initWithString(this.hash.algorithm); + } + catch (e) { + logger.warn("Unknown hash algorithm '" + this.hash.algorithm + "' for addon " + this.sourceURI.spec, e); + this.state = AddonManager.STATE_DOWNLOAD_FAILED; + this.error = AddonManager.ERROR_INCORRECT_HASH; + aCallback(this); + return; + } - // Giving each instance of AddonInstall a reference to the logger. - this.logger = logger; + let fis = Cc["@mozilla.org/network/file-input-stream;1"]. + createInstance(Ci.nsIFileInputStream); + fis.init(this.file, -1, -1, false); + crypto.updateFromStream(fis, this.file.fileSize); + let calculatedHash = getHashStringForCrypto(crypto); + if (calculatedHash != this.hash.data) { + logger.warn("File hash (" + calculatedHash + ") did not match provided hash (" + + this.hash.data + ")"); + this.state = AddonManager.STATE_DOWNLOAD_FAILED; + this.error = AddonManager.ERROR_INCORRECT_HASH; + aCallback(this); + return; + } + } - this.name = null; - this.type = null; - this.version = null; + try { + let self = this; + this.loadManifest(function initLocalInstall_loadManifest() { + XPIDatabase.getVisibleAddonForID(self.addon.id, function initLocalInstall_getVisibleAddon(aAddon) { + self.existingAddon = aAddon; + if (aAddon) + applyBlocklistChanges(aAddon, self.addon); + self.addon.updateDate = Date.now(); + self.addon.installDate = aAddon ? aAddon.installDate : self.addon.updateDate; + + if (!self.addon.isCompatible) { + // TODO Should we send some event here? + self.state = AddonManager.STATE_CHECKING; + new UpdateChecker(self.addon, { + onUpdateFinished: function updateChecker_onUpdateFinished(aAddon) { + self.state = AddonManager.STATE_DOWNLOADED; + XPIProvider.installs.push(self); + AddonManagerPrivate.callInstallListeners("onNewInstall", + self.listeners, + self.wrapper); + + aCallback(self); + } + }, AddonManager.UPDATE_WHEN_ADDON_INSTALLED); + } + else { + XPIProvider.installs.push(self); + AddonManagerPrivate.callInstallListeners("onNewInstall", + self.listeners, + self.wrapper); - this.file = null; - this.ownsTempFile = null; - this.certificate = null; - this.certName = null; + aCallback(self); + } + }); + }); + } + catch (e) { + this.state = AddonManager.STATE_DOWNLOAD_FAILED; + if (e.webext) { + logger.warn("WebExtension XPI", e); + this.error = AddonManager.ERROR_WEBEXT_FILE; + } else { + logger.warn("Invalid XPI", e); + this.error = AddonManager.ERROR_CORRUPT_FILE; + } + aCallback(this); + return; + } + }, - this.linkedInstalls = null; - this.addon = null; - this.state = null; + /** + * Initialises this install to be a download from a remote url. + * + * @param aCallback + * The callback to pass the initialised AddonInstall to + * @param aName + * An optional name for the add-on + * @param aType + * An optional type for the add-on + * @param aIcons + * Optional icons for the add-on + * @param aVersion + * An optional version for the add-on + */ + initAvailableDownload: function AI_initAvailableDownload(aName, aType, aIcons, aVersion, aCallback) { + this.state = AddonManager.STATE_AVAILABLE; + this.name = aName; + this.type = aType; + this.version = aVersion; + this.icons = aIcons; + this.progress = 0; + this.maxProgress = -1; - XPIProvider.installs.add(this); - } + XPIProvider.installs.push(this); + AddonManagerPrivate.callInstallListeners("onNewInstall", this.listeners, + this.wrapper); + + makeSafe(aCallback)(this); + }, /** * Starts installation of this add-on from whatever state it is currently at * if possible. * - * Note this method is overridden to handle additional state in - * the subclassses below. - * * @throws if installation cannot proceed from the current state */ - install() { + install: function AI_install() { switch (this.state) { + case AddonManager.STATE_AVAILABLE: + this.startDownload(); + break; case AddonManager.STATE_DOWNLOADED: this.startInstall(); break; - case AddonManager.STATE_POSTPONED: - logger.debug(`Postponing install of ${this.addon.id}`); + case AddonManager.STATE_DOWNLOAD_FAILED: + case AddonManager.STATE_INSTALL_FAILED: + case AddonManager.STATE_CANCELLED: + this.removeTemporaryFile(); + this.state = AddonManager.STATE_AVAILABLE; + this.error = 0; + this.progress = 0; + this.maxProgress = -1; + this.hash = this.originalHash; + XPIProvider.installs.push(this); + this.startDownload(); break; case AddonManager.STATE_DOWNLOADING: case AddonManager.STATE_CHECKING: @@ -5426,18 +5078,21 @@ class AddonInstall { default: throw new Error("Cannot start installing from this state"); } - } + }, /** * Cancels installation of this add-on. * - * Note this method is overridden to handle additional state in - * the subclass DownloadAddonInstall. - * * @throws if installation cannot be cancelled from the current state */ - cancel() { + cancel: function AI_cancel() { switch (this.state) { + case AddonManager.STATE_DOWNLOADING: + if (this.channel) { + logger.debug("Cancelling download of " + this.sourceURI.spec); + this.channel.cancel(Cr.NS_BINDING_ABORTED); + } + break; case AddonManager.STATE_AVAILABLE: case AddonManager.STATE_DOWNLOADED: logger.debug("Cancelling download of " + this.sourceURI.spec); @@ -5462,28 +5117,16 @@ class AddonInstall { this.existingAddon.pendingUpgrade = null; } - AddonManagerPrivate.callAddonListeners("onOperationCancelled", this.addon.wrapper); + AddonManagerPrivate.callAddonListeners("onOperationCancelled", createWrapper(this.addon)); AddonManagerPrivate.callInstallListeners("onInstallCancelled", this.listeners, this.wrapper); break; - case AddonManager.STATE_POSTPONED: - logger.debug(`Cancelling postponed install of ${this.addon.id}`); - this.state = AddonManager.STATE_CANCELLED; - XPIProvider.removeActiveInstall(this); - AddonManagerPrivate.callInstallListeners("onInstallCancelled", - this.listeners, this.wrapper); - this.removeTemporaryFile(); - - let stagingDir = this.installLocation.getStagingDir(); - let stagedAddon = stagingDir.clone(); - - this.unstageInstall(stagedAddon); default: throw new Error("Cannot cancel install of " + this.sourceURI.spec + " from this state (" + this.state + ")"); } - } + }, /** * Adds an InstallListener for this instance if the listener is not already @@ -5492,10 +5135,10 @@ class AddonInstall { * @param aListener * The InstallListener to add */ - addListener(aListener) { - if (!this.listeners.some(function(i) { return i == aListener; })) + addListener: function AI_addListener(aListener) { + if (!this.listeners.some(function addListener_matchListener(i) { return i == aListener; })) this.listeners.push(aListener); - } + }, /** * Removes an InstallListener for this instance if it is registered. @@ -5503,16 +5146,16 @@ class AddonInstall { * @param aListener * The InstallListener to remove */ - removeListener(aListener) { - this.listeners = this.listeners.filter(function(i) { + removeListener: function AI_removeListener(aListener) { + this.listeners = this.listeners.filter(function removeListener_filterListener(i) { return i != aListener; }); - } + }, /** * Removes the temporary file owned by this AddonInstall if there is one. */ - removeTemporaryFile() { + removeTemporaryFile: function AI_removeTemporaryFile() { // Only proceed if this AddonInstall owns its XPI file if (!this.ownsTempFile) { this.logger.debug("removeTemporaryFile: " + this.sourceURI.spec + " does not own temp file"); @@ -5530,58 +5173,17 @@ class AddonInstall { this.sourceURI.spec, e); } - } + }, /** * Updates the sourceURI and releaseNotesURI values on the Addon being * installed by this AddonInstall instance. */ - updateAddonURIs() { + updateAddonURIs: function AI_updateAddonURIs() { this.addon.sourceURI = this.sourceURI.spec; if (this.releaseNotesURI) this.addon.releaseNotesURI = this.releaseNotesURI.spec; - } - - /** - * Fills out linkedInstalls with AddonInstall instances for the other files - * in a multi-package XPI. - * - * @param aFiles - * An array of { entryName, file } for each remaining file from the - * multi-package XPI. - */ - _createLinkedInstalls(aFiles) { - return Task.spawn((function*() { - if (aFiles.length == 0) - return; - - // Create new AddonInstall instances for every remaining file - if (!this.linkedInstalls) - this.linkedInstalls = []; - - for (let { entryName, file } of aFiles) { - logger.debug("Creating linked install from " + entryName); - let install = yield createLocalInstall(file); - - // Make the new install own its temporary file - install.ownsTempFile = true; - - this.linkedInstalls.push(install); - - // If one of the internal XPIs was multipackage then move its linked - // installs to the outer install - if (install.linkedInstalls) { - this.linkedInstalls.push(...install.linkedInstalls); - install.linkedInstalls = null; - } - - install.sourceURI = this.sourceURI; - install.releaseNotesURI = this.releaseNotesURI; - if (install.state != AddonManager.STATE_DOWNLOAD_FAILED) - install.updateAddonURIs(); - } - }).bind(this)); - } + }, /** * Loads add-on manifests from a multi-package XPI file. Each of the @@ -5593,683 +5195,216 @@ class AddonInstall { * @param aZipReader * An open nsIZipReader for the multi-package XPI's files. This will * be closed before this method returns. - */ - _loadMultipackageManifests(aZipReader) { - return Task.spawn((function*() { - let files = []; - let entries = aZipReader.findEntries("(*.[Xx][Pp][Ii]|*.[Jj][Aa][Rr])"); - while (entries.hasMore()) { - let entryName = entries.getNext(); - let file = getTemporaryFile(); - try { - aZipReader.extract(entryName, file); - files.push({ entryName, file }); - } - catch (e) { - logger.warn("Failed to extract " + entryName + " from multi-package " + - "XPI", e); - file.remove(false); - } - } - - aZipReader.close(); - - if (files.length == 0) { - return Promise.reject([AddonManager.ERROR_CORRUPT_FILE, - "Multi-package XPI does not contain any packages to install"]); - } - - let addon = null; - - // Find the first file that is a valid install and use it for - // the add-on that this AddonInstall instance will install. - for (let { entryName, file } of files) { - this.removeTemporaryFile(); - try { - yield this.loadManifest(file); - logger.debug("Base multi-package XPI install came from " + entryName); - this.file = file; - this.ownsTempFile = true; - - yield this._createLinkedInstalls(files.filter(f => f.file != file)); - return undefined; - } - catch (e) { - // _createLinkedInstalls will log errors when it tries to process this - // file - } - } - - // No valid add-on was found, delete all the temporary files - for (let { file } of files) { - try { - file.remove(true); - } catch (e) { - this.logger.warn("Could not remove temp file " + file.path); - } - } - - return Promise.reject([AddonManager.ERROR_CORRUPT_FILE, - "Multi-package XPI does not contain any valid packages to install"]); - }).bind(this)); - } - - /** - * Called after the add-on is a local file and the signature and install - * manifest can be read. - * * @param aCallback - * A function to call when the manifest has been loaded - * @throws if the add-on does not contain a valid install manifest or the - * XPI is incorrectly signed - */ - loadManifest(file) { - return Task.spawn((function*() { - let zipreader = Cc["@mozilla.org/libjar/zip-reader;1"]. - createInstance(Ci.nsIZipReader); + * A function to call when all of the add-on manifests have been + * loaded. Because this loadMultipackageManifests is an internal API + * we don't exception-wrap this callback + */ + _loadMultipackageManifests: function AI_loadMultipackageManifests(aZipReader, + aCallback) { + let files = []; + let entries = aZipReader.findEntries("(*.[Xx][Pp][Ii]|*.[Jj][Aa][Rr])"); + while (entries.hasMore()) { + let entryName = entries.getNext(); + var target = getTemporaryFile(); try { - zipreader.open(file); + aZipReader.extract(entryName, target); + files.push(target); } catch (e) { - zipreader.close(); - return Promise.reject([AddonManager.ERROR_CORRUPT_FILE, e]); - } - - try { - // loadManifestFromZipReader performs the certificate verification for us - this.addon = yield loadManifestFromZipReader(zipreader, this.installLocation); - } - catch (e) { - zipreader.close(); - return Promise.reject([AddonManager.ERROR_CORRUPT_FILE, e]); - } - - // A multi-package XPI is a container, the add-ons it holds each - // have their own id. Everything else had better have an id here. - if (!this.addon.id && this.addon.type != "multipackage") { - let err = new Error(`Cannot find id for addon ${file.path}`); - return Promise.reject([AddonManager.ERROR_CORRUPT_FILE, err]); + logger.warn("Failed to extract " + entryName + " from multi-package " + + "XPI", e); + target.remove(false); } + } - if (this.existingAddon) { - // Check various conditions related to upgrades - if (this.addon.id != this.existingAddon.id) { - zipreader.close(); - return Promise.reject([AddonManager.ERROR_INCORRECT_ID, - `Refusing to upgrade addon ${this.existingAddon.id} to different ID {this.addon.id}`]); - } - - if (this.addon.type == "multipackage") { - zipreader.close(); - return Promise.reject([AddonManager.ERROR_UNEXPECTED_ADDON_TYPE, - `Refusing to upgrade addon ${this.existingAddon.id} to a multi-package xpi`]); - } - - if (this.existingAddon.type == "webextension" && this.addon.type != "webextension") { - zipreader.close(); - return Promise.reject([AddonManager.ERROR_UNEXPECTED_ADDON_TYPE, - "WebExtensions may not be upated to other extension types"]); - } - } + aZipReader.close(); - if (mustSign(this.addon.type)) { - if (this.addon.signedState <= AddonManager.SIGNEDSTATE_MISSING) { - // This add-on isn't properly signed by a signature that chains to the - // trusted root. - let state = this.addon.signedState; - this.addon = null; - zipreader.close(); + if (files.length == 0) { + throw new Error("Multi-package XPI does not contain any packages " + + "to install"); + } - if (state == AddonManager.SIGNEDSTATE_MISSING) - return Promise.reject([AddonManager.ERROR_SIGNEDSTATE_REQUIRED, - "signature is required but missing"]) + let addon = null; - return Promise.reject([AddonManager.ERROR_CORRUPT_FILE, - "signature verification failed"]) - } + // Find the first file that has a valid install manifest and use it for + // the add-on that this AddonInstall instance will install. + while (files.length > 0) { + this.removeTemporaryFile(); + this.file = files.shift(); + this.ownsTempFile = true; + try { + addon = loadManifestFromZipFile(this.file); + break; } - else if (this.addon.signedState == AddonManager.SIGNEDSTATE_UNKNOWN || - this.addon.signedState == AddonManager.SIGNEDSTATE_NOT_REQUIRED) { - // Check object signing certificate, if any - let x509 = zipreader.getSigningCert(null); - if (x509) { - logger.debug("Verifying XPI signature"); - if (verifyZipSigning(zipreader, x509)) { - this.certificate = x509; - if (this.certificate.commonName.length > 0) { - this.certName = this.certificate.commonName; - } else { - this.certName = this.certificate.organization; - } - } else { - zipreader.close(); - return Promise.reject([AddonManager.ERROR_CORRUPT_FILE, - "XPI is incorrectly signed"]); - } - } + catch (e) { + logger.warn(this.file.leafName + " cannot be installed from multi-package " + + "XPI", e); } - - if (this.addon.type == "multipackage") - return this._loadMultipackageManifests(zipreader); - - zipreader.close(); - - this.updateAddonURIs(); - - this.addon._install = this; - this.name = this.addon.selectedLocale.name; - this.type = this.addon.type; - this.version = this.addon.version; - - // Setting the iconURL to something inside the XPI locks the XPI and - // makes it impossible to delete on Windows. - - // Try to load from the existing cache first - let repoAddon = yield new Promise(resolve => AddonRepository.getCachedAddonByID(this.addon.id, resolve)); - - // It wasn't there so try to re-download it - if (!repoAddon) { - yield new Promise(resolve => AddonRepository.cacheAddons([this.addon.id], resolve)); - repoAddon = yield new Promise(resolve => AddonRepository.getCachedAddonByID(this.addon.id, resolve)); - } - - this.addon._repositoryAddon = repoAddon; - this.name = this.name || this.addon._repositoryAddon.name; - this.addon.compatibilityOverrides = repoAddon ? - repoAddon.compatibilityOverrides : - null; - this.addon.appDisabled = !isUsableAddon(this.addon); - return undefined; - }).bind(this)); - } - - // TODO This relies on the assumption that we are always installing into the - // highest priority install location so the resulting add-on will be visible - // overriding any existing copy in another install location (bug 557710). - /** - * Installs the add-on into the install location. - */ - startInstall() { - this.state = AddonManager.STATE_INSTALLING; - if (!AddonManagerPrivate.callInstallListeners("onInstallStarted", - this.listeners, this.wrapper)) { - this.state = AddonManager.STATE_DOWNLOADED; - XPIProvider.removeActiveInstall(this); - AddonManagerPrivate.callInstallListeners("onInstallCancelled", - this.listeners, this.wrapper) - return; } - // Find and cancel any pending installs for the same add-on in the same - // install location - for (let aInstall of XPIProvider.installs) { - if (aInstall.state == AddonManager.STATE_INSTALLED && - aInstall.installLocation == this.installLocation && - aInstall.addon.id == this.addon.id) { - logger.debug("Cancelling previous pending install of " + aInstall.addon.id); - aInstall.cancel(); - } + if (!addon) { + // No valid add-on was found + aCallback(); + return; } - let isUpgrade = this.existingAddon && - this.existingAddon._installLocation == this.installLocation; - let requiresRestart = XPIProvider.installRequiresRestart(this.addon); - - logger.debug("Starting install of " + this.addon.id + " from " + this.sourceURI.spec); - AddonManagerPrivate.callAddonListeners("onInstalling", - this.addon.wrapper, - requiresRestart); - - let stagedAddon = this.installLocation.getStagingDir(); - - Task.spawn((function*() { - let installedUnpacked = 0; - - yield this.installLocation.requestStagingDir(); - - // remove any previously staged files - yield this.unstageInstall(stagedAddon); - - stagedAddon.append(this.addon.id); - stagedAddon.leafName = this.addon.id + ".xpi"; - - installedUnpacked = yield this.stageInstall(requiresRestart, stagedAddon, isUpgrade); - - if (requiresRestart) { - this.state = AddonManager.STATE_INSTALLED; - AddonManagerPrivate.callInstallListeners("onInstallEnded", - this.listeners, this.wrapper, - this.addon.wrapper); - } - else { - // The install is completed so it should be removed from the active list - XPIProvider.removeActiveInstall(this); - - // Deactivate and remove the old add-on as necessary - let reason = BOOTSTRAP_REASONS.ADDON_INSTALL; - if (this.existingAddon) { - if (Services.vc.compare(this.existingAddon.version, this.addon.version) < 0) - reason = BOOTSTRAP_REASONS.ADDON_UPGRADE; - else - reason = BOOTSTRAP_REASONS.ADDON_DOWNGRADE; - - if (this.existingAddon.bootstrap) { - let file = this.existingAddon._sourceBundle; - if (this.existingAddon.active) { - XPIProvider.callBootstrapMethod(this.existingAddon, file, - "shutdown", reason, - { newVersion: this.addon.version }); - } - - XPIProvider.callBootstrapMethod(this.existingAddon, file, - "uninstall", reason, - { newVersion: this.addon.version }); - XPIProvider.unloadBootstrapScope(this.existingAddon.id); - flushChromeCaches(); - } - - if (!isUpgrade && this.existingAddon.active) { - XPIDatabase.updateAddonActive(this.existingAddon, false); - } - } - - // Install the new add-on into its final location - let existingAddonID = this.existingAddon ? this.existingAddon.id : null; - let file = this.installLocation.installAddon({ - id: this.addon.id, - source: stagedAddon, - existingAddonID - }); - - // Update the metadata in the database - this.addon._sourceBundle = file; - this.addon.visible = true; - - if (isUpgrade) { - this.addon = XPIDatabase.updateAddonMetadata(this.existingAddon, this.addon, - file.persistentDescriptor); - let state = XPIStates.getAddon(this.installLocation.name, this.addon.id); - if (state) { - state.syncWithDB(this.addon, true); - } else { - logger.warn("Unexpected missing XPI state for add-on ${id}", this.addon); + this.addon = addon; + + this.updateAddonURIs(); + + this.addon._install = this; + this.name = this.addon.selectedLocale.name || this.addon.defaultLocale.name; + this.type = this.addon.type; + this.version = this.addon.version; + + // Setting the iconURL to something inside the XPI locks the XPI and + // makes it impossible to delete on Windows. + //let newIcon = createWrapper(this.addon).iconURL; + //if (newIcon) + // this.iconURL = newIcon; + + // Create new AddonInstall instances for every remaining file + if (files.length > 0) { + this.linkedInstalls = []; + let count = 0; + let self = this; + files.forEach(function(file) { + AddonInstall.createInstall(function loadMultipackageManifests_createInstall(aInstall) { + // Ignore bad add-ons (createInstall will have logged the error) + if (aInstall.state == AddonManager.STATE_DOWNLOAD_FAILED) { + // Manually remove the temporary file + file.remove(true); } - } - else { - this.addon.active = (this.addon.visible && !this.addon.disabled); - this.addon = XPIDatabase.addAddonMetadata(this.addon, file.persistentDescriptor); - XPIStates.addAddon(this.addon); - this.addon.installDate = this.addon.updateDate; - XPIDatabase.saveChanges(); - } - XPIStates.save(); - - let extraParams = {}; - if (this.existingAddon) { - extraParams.oldVersion = this.existingAddon.version; - } - - if (this.addon.bootstrap) { - XPIProvider.callBootstrapMethod(this.addon, file, "install", - reason, extraParams); - } - - AddonManagerPrivate.callAddonListeners("onInstalled", - this.addon.wrapper); + else { + // Make the new install own its temporary file + aInstall.ownsTempFile = true; - logger.debug("Install of " + this.sourceURI.spec + " completed."); - this.state = AddonManager.STATE_INSTALLED; - AddonManagerPrivate.callInstallListeners("onInstallEnded", - this.listeners, this.wrapper, - this.addon.wrapper); + self.linkedInstalls.push(aInstall) - if (this.addon.bootstrap) { - if (this.addon.active) { - XPIProvider.callBootstrapMethod(this.addon, file, "startup", - reason, extraParams); + aInstall.sourceURI = self.sourceURI; + aInstall.releaseNotesURI = self.releaseNotesURI; + aInstall.updateAddonURIs(); } - else { - // XXX this makes it dangerous to do some things in onInstallEnded - // listeners because important cleanup hasn't been done yet - XPIProvider.unloadBootstrapScope(this.addon.id); - } - } - XPIProvider.setTelemetry(this.addon.id, "unpacked", installedUnpacked); - recordAddonTelemetry(this.addon); - } - }).bind(this)).then(null, (e) => { - logger.warn(`Failed to install ${this.file.path} from ${this.sourceURI.spec} to ${stagedAddon.path}`, e); - if (stagedAddon.exists()) - recursiveRemove(stagedAddon); - this.state = AddonManager.STATE_INSTALL_FAILED; - this.error = AddonManager.ERROR_FILE_ACCESS; - XPIProvider.removeActiveInstall(this); - AddonManagerPrivate.callAddonListeners("onOperationCancelled", - this.addon.wrapper); - AddonManagerPrivate.callInstallListeners("onInstallFailed", - this.listeners, - this.wrapper); - }).then(() => { - this.removeTemporaryFile(); - return this.installLocation.releaseStagingDir(); - }); - } + count++; + if (count == files.length) + aCallback(); + }, file); + }, this); + } + else { + aCallback(); + } + }, /** - * Stages an upgrade for next application restart. + * Called after the add-on is a local file and the signature and install + * manifest can be read. + * + * @param aCallback + * A function to call when the manifest has been loaded + * @throws if the add-on does not contain a valid install manifest or the + * XPI is incorrectly signed */ - stageInstall(restartRequired, stagedAddon, isUpgrade) { - return Task.spawn((function*() { - let stagedJSON = stagedAddon.clone(); - stagedJSON.leafName = this.addon.id + ".json"; - - let installedUnpacked = 0; - - // First stage the file regardless of whether restarting is necessary - if (this.addon.unpack || Preferences.get(PREF_XPI_UNPACK, false)) { - logger.debug("Addon " + this.addon.id + " will be installed as " + - "an unpacked directory"); - stagedAddon.leafName = this.addon.id; - yield OS.File.makeDir(stagedAddon.path); - yield ZipUtils.extractFilesAsync(this.file, stagedAddon); - installedUnpacked = 1; - } - else { - logger.debug(`Addon ${this.addon.id} will be installed as a packed xpi`); - stagedAddon.leafName = this.addon.id + ".xpi"; - - yield OS.File.copy(this.file.path, stagedAddon.path); - } - - if (restartRequired) { - // Point the add-on to its extracted files as the xpi may get deleted - this.addon._sourceBundle = stagedAddon; - - // Cache the AddonInternal as it may have updated compatibility info - writeStringToFile(stagedJSON, JSON.stringify(this.addon)); - - logger.debug("Staged install of " + this.addon.id + " from " + this.sourceURI.spec + " ready; waiting for restart."); - if (isUpgrade) { - delete this.existingAddon.pendingUpgrade; - this.existingAddon.pendingUpgrade = this.addon; + loadManifest: function AI_loadManifest(aCallback) { + aCallback = makeSafe(aCallback); + let self = this; + function addRepositoryData(aAddon) { + // Try to load from the existing cache first + AddonRepository.getCachedAddonByID(aAddon.id, function loadManifest_getCachedAddonByID(aRepoAddon) { + if (aRepoAddon) { + aAddon._repositoryAddon = aRepoAddon; + self.name = self.name || aAddon._repositoryAddon.name; + aAddon.compatibilityOverrides = aRepoAddon.compatibilityOverrides; + aAddon.appDisabled = !isUsableAddon(aAddon); + aCallback(); + return; } - } - - return installedUnpacked; - }).bind(this)); - } - - /** - * Removes any previously staged upgrade. - */ - unstageInstall(stagedAddon) { - return Task.spawn((function*() { - let stagedJSON = stagedAddon.clone(); - let removedAddon = stagedAddon.clone(); - - stagedJSON.append(this.addon.id + ".json"); - - if (stagedJSON.exists()) { - stagedJSON.remove(true); - } - removedAddon.append(this.addon.id); - yield removeAsync(removedAddon); - removedAddon.leafName = this.addon.id + ".xpi"; - yield removeAsync(removedAddon); - }).bind(this)); - } - - /** - * Postone a pending update, until restart or until the add-on resumes. - * - * @param {Function} resumeFunction - a function for the add-on to run - * when resuming. - */ - postpone(resumeFunction) { - return Task.spawn((function*() { - this.state = AddonManager.STATE_POSTPONED; - - let stagingDir = this.installLocation.getStagingDir(); - let stagedAddon = stagingDir.clone(); - - yield this.installLocation.requestStagingDir(); - yield this.unstageInstall(stagedAddon); - - stagedAddon.append(this.addon.id); - stagedAddon.leafName = this.addon.id + ".xpi"; - - yield this.stageInstall(true, stagedAddon, true); - - AddonManagerPrivate.callInstallListeners("onInstallPostponed", - this.listeners, this.wrapper) - - // upgrade has been staged for restart, provide a way for it to call the - // resume function. - if (resumeFunction) { - let callback = AddonManagerPrivate.getUpgradeListener(this.addon.id); - if (callback) { - callback({ - version: this.version, - install: () => { - switch (this.state) { - case AddonManager.STATE_POSTPONED: - resumeFunction(); - break; - default: - logger.warn(`${this.addon.id} cannot resume postponed upgrade from state (${this.state})`); - break; - } - }, + // It wasn't there so try to re-download it + AddonRepository.cacheAddons([aAddon.id], function loadManifest_cacheAddons() { + AddonRepository.getCachedAddonByID(aAddon.id, function loadManifest_getCachedAddonByID(aRepoAddon) { + aAddon._repositoryAddon = aRepoAddon; + self.name = self.name || aAddon._repositoryAddon.name; + aAddon.compatibilityOverrides = aRepoAddon ? + aRepoAddon.compatibilityOverrides : + null; + aAddon.appDisabled = !isUsableAddon(aAddon); + aCallback(); }); - } - } - this.installLocation.releaseStagingDir(); - }).bind(this)); - } -} - -class LocalAddonInstall extends AddonInstall { - /** - * Initialises this install to be an install from a local file. - * - * @returns Promise - * A Promise that resolves when the object is ready to use. - */ - init() { - return Task.spawn((function*() { - this.file = this.sourceURI.QueryInterface(Ci.nsIFileURL).file; - - if (!this.file.exists()) { - logger.warn("XPI file " + this.file.path + " does not exist"); - this.state = AddonManager.STATE_DOWNLOAD_FAILED; - this.error = AddonManager.ERROR_NETWORK_FAILURE; - XPIProvider.removeActiveInstall(this); - return; - } - - this.state = AddonManager.STATE_DOWNLOADED; - this.progress = this.file.fileSize; - this.maxProgress = this.file.fileSize; + }); + }); + } - if (this.hash) { - let crypto = Cc["@mozilla.org/security/hash;1"]. - createInstance(Ci.nsICryptoHash); - try { - crypto.initWithString(this.hash.algorithm); - } - catch (e) { - logger.warn("Unknown hash algorithm '" + this.hash.algorithm + "' for addon " + this.sourceURI.spec, e); - this.state = AddonManager.STATE_DOWNLOAD_FAILED; - this.error = AddonManager.ERROR_INCORRECT_HASH; - XPIProvider.removeActiveInstall(this); - return; - } + let zipreader = Cc["@mozilla.org/libjar/zip-reader;1"]. + createInstance(Ci.nsIZipReader); + try { + zipreader.open(this.file); + } + catch (e) { + zipreader.close(); + throw e; + } - let fis = Cc["@mozilla.org/network/file-input-stream;1"]. - createInstance(Ci.nsIFileInputStream); - fis.init(this.file, -1, -1, false); - crypto.updateFromStream(fis, this.file.fileSize); - let calculatedHash = getHashStringForCrypto(crypto); - if (calculatedHash != this.hash.data) { - logger.warn("File hash (" + calculatedHash + ") did not match provided hash (" + - this.hash.data + ")"); - this.state = AddonManager.STATE_DOWNLOAD_FAILED; - this.error = AddonManager.ERROR_INCORRECT_HASH; - XPIProvider.removeActiveInstall(this); - return; + let x509 = zipreader.getSigningCert(null); + if (x509) { + logger.debug("Verifying XPI signature"); + if (verifyZipSigning(zipreader, x509)) { + this.certificate = x509; + if (this.certificate.commonName.length > 0) { + this.certName = this.certificate.commonName; + } else { + this.certName = this.certificate.organization; } + } else { + zipreader.close(); + throw new Error("XPI is incorrectly signed"); } + } - try { - yield this.loadManifest(this.file); - } catch ([error, message]) { - logger.warn("Invalid XPI", message); - this.state = AddonManager.STATE_DOWNLOAD_FAILED; - this.error = error; - XPIProvider.removeActiveInstall(this); - AddonManagerPrivate.callInstallListeners("onNewInstall", - this.listeners, - this.wrapper); - return; - } + try { + this.addon = loadManifestFromZipReader(zipreader); + } + catch (e) { + zipreader.close(); + throw e; + } - let addon = yield new Promise(resolve => { - XPIDatabase.getVisibleAddonForID(this.addon.id, resolve); + if (this.addon.type == "multipackage") { + this._loadMultipackageManifests(zipreader, function loadManifest_loadMultipackageManifests() { + addRepositoryData(self.addon); }); - - this.existingAddon = addon; - if (addon) - applyBlocklistChanges(addon, this.addon); - this.addon.updateDate = Date.now(); - this.addon.installDate = addon ? addon.installDate : this.addon.updateDate; - - if (!this.addon.isCompatible) { - this.state = AddonManager.STATE_CHECKING; - - yield new Promise(resolve => { - new UpdateChecker(this.addon, { - onUpdateFinished: aAddon => { - this.state = AddonManager.STATE_DOWNLOADED; - AddonManagerPrivate.callInstallListeners("onNewInstall", - this.listeners, - this.wrapper); - resolve(); - } - }, AddonManager.UPDATE_WHEN_ADDON_INSTALLED); - }); - } - else { - AddonManagerPrivate.callInstallListeners("onNewInstall", - this.listeners, - this.wrapper); - - } - }).bind(this)); - } - - install() { - if (this.state == AddonManager.STATE_DOWNLOAD_FAILED) { - // For a local install, this state means that verification of the - // file failed (e.g., the hash or signature or manifest contents - // were invalid). It doesn't make sense to retry anything in this - // case but we have callers who don't know if their AddonInstall - // object is a local file or a download so accomodate them here. - AddonManagerPrivate.callInstallListeners("onDownloadFailed", - this.listeners, this.wrapper); return; } - super.install(); - } -} -class DownloadAddonInstall extends AddonInstall { - /** - * Instantiates a DownloadAddonInstall - * - * @param installLocation - * The InstallLocation the add-on will be installed into - * @param url - * The nsIURL to get the add-on from - * @param name - * An optional name for the add-on - * @param hash - * An optional hash for the add-on - * @param existingAddon - * The add-on this install will update if known - * @param browser - * The browser performing the install, used to display - * authentication prompts. - * @param type - * An optional type for the add-on - * @param icons - * Optional icons for the add-on - * @param version - * An optional version for the add-on - */ - constructor(installLocation, url, hash, existingAddon, browser, - name, type, icons, version) { - super(installLocation, url, hash, existingAddon); + zipreader.close(); - this.browser = browser; + this.updateAddonURIs(); - this.state = AddonManager.STATE_AVAILABLE; - this.name = name; - this.type = type; - this.version = version; - this.icons = icons; - - this.stream = null; - this.crypto = null; - this.badCertHandler = null; - this.restartDownload = false; - - AddonManagerPrivate.callInstallListeners("onNewInstall", this.listeners, - this.wrapper); - } + this.addon._install = this; + this.name = this.addon.selectedLocale.name || this.addon.defaultLocale.name; + this.type = this.addon.type; + this.version = this.addon.version; - install() { - switch (this.state) { - case AddonManager.STATE_AVAILABLE: - this.startDownload(); - break; - case AddonManager.STATE_DOWNLOAD_FAILED: - case AddonManager.STATE_INSTALL_FAILED: - case AddonManager.STATE_CANCELLED: - this.removeTemporaryFile(); - this.state = AddonManager.STATE_AVAILABLE; - this.error = 0; - this.progress = 0; - this.maxProgress = -1; - this.hash = this.originalHash; - this.startDownload(); - break; - default: - super.install(); - } - } + // Setting the iconURL to something inside the XPI locks the XPI and + // makes it impossible to delete on Windows. + //let newIcon = createWrapper(this.addon).iconURL; + //if (newIcon) + // this.iconURL = newIcon; - cancel() { - if (this.state == AddonManager.STATE_DOWNLOADING) { - if (this.channel) { - logger.debug("Cancelling download of " + this.sourceURI.spec); - this.channel.cancel(Cr.NS_BINDING_ABORTED); - } - } else { - super.cancel(); - } - } + addRepositoryData(this.addon); + }, - observe(aSubject, aTopic, aData) { + observe: function AI_observe(aSubject, aTopic, aData) { // Network is going offline this.cancel(); - } + }, /** * Starts downloading the add-on's XPI file. */ - startDownload() { + startDownload: function AI_startDownload() { this.state = AddonManager.STATE_DOWNLOADING; if (!AddonManagerPrivate.callInstallListeners("onDownloadStarted", this.listeners, this.wrapper)) { @@ -6294,9 +5429,9 @@ class DownloadAddonInstall extends AddonInstall { } this.openChannel(); - } + }, - openChannel() { + openChannel: function AI_openChannel() { this.restartDownload = false; try { @@ -6321,8 +5456,9 @@ class DownloadAddonInstall extends AddonInstall { createInstance(Ci.nsIStreamListenerTee); listener.init(this, this.stream); try { + Components.utils.import("resource://gre/modules/CertUtils.jsm"); let requireBuiltIn = Preferences.get(PREF_INSTALL_REQUIREBUILTINCERTS, true); - this.badCertHandler = new CertUtils.BadCertHandler(!requireBuiltIn); + this.badCertHandler = new BadCertHandler(!requireBuiltIn); this.channel = NetUtil.newChannel({ uri: this.sourceURI, @@ -6346,21 +5482,22 @@ class DownloadAddonInstall extends AddonInstall { AddonManagerPrivate.callInstallListeners("onDownloadFailed", this.listeners, this.wrapper); } - } + }, /** * Update the crypto hasher with the new data and call the progress listeners. * * @see nsIStreamListener */ - onDataAvailable(aRequest, aContext, aInputstream, aOffset, aCount) { + onDataAvailable: function AI_onDataAvailable(aRequest, aContext, aInputstream, + aOffset, aCount) { this.crypto.updateFromStream(aInputstream, aCount); this.progress += aCount; if (!AddonManagerPrivate.callInstallListeners("onDownloadProgress", this.listeners, this.wrapper)) { // TODO cancel the download and make it available again (bug 553024) } - } + }, /** * Check the redirect response for a hash of the target XPI and verify that @@ -6368,7 +5505,7 @@ class DownloadAddonInstall extends AddonInstall { * * @see nsIChannelEventSink */ - asyncOnChannelRedirect(aOldChannel, aNewChannel, aFlags, aCallback) { + asyncOnChannelRedirect: function AI_asyncOnChannelRedirect(aOldChannel, aNewChannel, aFlags, aCallback) { if (!this.hash && aOldChannel.originalURI.schemeIs("https") && aOldChannel instanceof Ci.nsIHttpChannel) { try { @@ -6391,14 +5528,14 @@ class DownloadAddonInstall extends AddonInstall { aCallback.onRedirectVerifyCallback(Cr.NS_OK); this.channel = aNewChannel; - } + }, /** * This is the first chance to get at real headers on the channel. * * @see nsIStreamListener */ - onStartRequest(aRequest, aContext) { + onStartRequest: function AI_onStartRequest(aRequest, aContext) { this.crypto = Cc["@mozilla.org/security/hash;1"]. createInstance(Ci.nsICryptoHash); if (this.hash) { @@ -6432,14 +5569,14 @@ class DownloadAddonInstall extends AddonInstall { logger.debug("Download started for " + this.sourceURI.spec + " to file " + this.file.path); } - } + }, /** * The download is complete. * * @see nsIStreamListener */ - onStopRequest(aRequest, aContext, aStatus) { + onStopRequest: function AI_onStopRequest(aRequest, aContext, aStatus) { this.stream.close(); this.channel = null; this.badCerthandler = null; @@ -6471,8 +5608,8 @@ class DownloadAddonInstall extends AddonInstall { if (!(aRequest instanceof Ci.nsIHttpChannel) || aRequest.requestSucceeded) { if (!this.hash && (aRequest instanceof Ci.nsIChannel)) { try { - CertUtils.checkCert(aRequest, - !Preferences.get(PREF_INSTALL_REQUIREBUILTINCERTS, true)); + checkCert(aRequest, + !Preferences.get(PREF_INSTALL_REQUIREBUILTINCERTS, true)); } catch (e) { this.downloadFailed(AddonManager.ERROR_NETWORK_FAILURE, e); @@ -6489,36 +5626,44 @@ class DownloadAddonInstall extends AddonInstall { ") did not match provided hash (" + this.hash.data + ")"); return; } - - this.loadManifest(this.file).then(() => { - if (this.addon.isCompatible) { - this.downloadCompleted(); - } - else { - // TODO Should we send some event here (bug 557716)? - this.state = AddonManager.STATE_CHECKING; - new UpdateChecker(this.addon, { - onUpdateFinished: aAddon => this.downloadCompleted(), - }, AddonManager.UPDATE_WHEN_ADDON_INSTALLED); + try { + let self = this; + this.loadManifest(function onStopRequest_loadManifest() { + if (self.addon.isCompatible) { + self.downloadCompleted(); + } + else { + // TODO Should we send some event here (bug 557716)? + self.state = AddonManager.STATE_CHECKING; + new UpdateChecker(self.addon, { + onUpdateFinished: function onStopRequest_onUpdateFinished(aAddon) { + self.downloadCompleted(); + } + }, AddonManager.UPDATE_WHEN_ADDON_INSTALLED); + } + }); + } + catch (e) { + if (e.webext) { + this.downloadFailed(AddonManager.ERROR_WEBEXT_FILE, e); + } else { + this.downloadFailed(AddonManager.ERROR_CORRUPT_FILE, e); } - }, ([error, message]) => { - this.removeTemporaryFile(); - this.downloadFailed(error, message); - }); - } - else if (aRequest instanceof Ci.nsIHttpChannel) { - this.downloadFailed(AddonManager.ERROR_NETWORK_FAILURE, - aRequest.responseStatus + " " + - aRequest.responseStatusText); + } } else { - this.downloadFailed(AddonManager.ERROR_NETWORK_FAILURE, aStatus); + if (aRequest instanceof Ci.nsIHttpChannel) + this.downloadFailed(AddonManager.ERROR_NETWORK_FAILURE, + aRequest.responseStatus + " " + + aRequest.responseStatusText); + else + this.downloadFailed(AddonManager.ERROR_NETWORK_FAILURE, aStatus); } } else { this.downloadFailed(AddonManager.ERROR_NETWORK_FAILURE, aStatus); } - } + }, /** * Notify listeners that the download failed. @@ -6528,7 +5673,7 @@ class DownloadAddonInstall extends AddonInstall { * @param error * The error code to pass to the listeners */ - downloadFailed(aReason, aError) { + downloadFailed: function AI_downloadFailed(aReason, aError) { logger.warn("Download of " + this.sourceURI.spec + " failed", aError); this.state = AddonManager.STATE_DOWNLOAD_FAILED; this.error = aReason; @@ -6545,72 +5690,276 @@ class DownloadAddonInstall extends AddonInstall { else logger.debug("downloadFailed: listener changed AddonInstall state for " + this.sourceURI.spec + " to " + this.state); - } + }, /** * Notify listeners that the download completed. */ - downloadCompleted() { - XPIDatabase.getVisibleAddonForID(this.addon.id, aAddon => { + downloadCompleted: function AI_downloadCompleted() { + let self = this; + XPIDatabase.getVisibleAddonForID(this.addon.id, function downloadCompleted_getVisibleAddonForID(aAddon) { if (aAddon) - this.existingAddon = aAddon; + self.existingAddon = aAddon; - this.state = AddonManager.STATE_DOWNLOADED; - this.addon.updateDate = Date.now(); + self.state = AddonManager.STATE_DOWNLOADED; + self.addon.updateDate = Date.now(); - if (this.existingAddon) { - this.addon.existingAddonID = this.existingAddon.id; - this.addon.installDate = this.existingAddon.installDate; - applyBlocklistChanges(this.existingAddon, this.addon); + if (self.existingAddon) { + self.addon.existingAddonID = self.existingAddon.id; + self.addon.installDate = self.existingAddon.installDate; + applyBlocklistChanges(self.existingAddon, self.addon); } else { - this.addon.installDate = this.addon.updateDate; + self.addon.installDate = self.addon.updateDate; } if (AddonManagerPrivate.callInstallListeners("onDownloadEnded", - this.listeners, - this.wrapper)) { + self.listeners, + self.wrapper)) { // If a listener changed our state then do not proceed with the install - if (this.state != AddonManager.STATE_DOWNLOADED) + if (self.state != AddonManager.STATE_DOWNLOADED) return; - // If an upgrade listener is registered for this add-on, pass control - // over the upgrade to the add-on. - if (AddonManagerPrivate.hasUpgradeListener(this.addon.id)) { - logger.info(`add-on ${this.addon.id} has an upgrade listener, postponing upgrade until restart`); - let resumeFn = () => { - logger.info(`${this.addon.id} has resumed a previously postponed upgrade`); - this.state = AddonManager.STATE_DOWNLOADED; - this.install(); - } - this.postpone(resumeFn); - } else { - // no upgrade listener present, so proceed with normal install - this.install(); - if (this.linkedInstalls) { - for (let install of this.linkedInstalls) { - if (install.state == AddonManager.STATE_DOWNLOADED) - install.install(); + self.install(); + + if (self.linkedInstalls) { + self.linkedInstalls.forEach(function(aInstall) { + aInstall.install(); + }); + } + } + }); + }, + + // TODO This relies on the assumption that we are always installing into the + // highest priority install location so the resulting add-on will be visible + // overriding any existing copy in another install location (bug 557710). + /** + * Installs the add-on into the install location. + */ + startInstall: function AI_startInstall() { + this.state = AddonManager.STATE_INSTALLING; + if (!AddonManagerPrivate.callInstallListeners("onInstallStarted", + this.listeners, this.wrapper)) { + this.state = AddonManager.STATE_DOWNLOADED; + XPIProvider.removeActiveInstall(this); + AddonManagerPrivate.callInstallListeners("onInstallCancelled", + this.listeners, this.wrapper) + return; + } + + // Find and cancel any pending installs for the same add-on in the same + // install location + for (let aInstall of XPIProvider.installs) { + if (aInstall.state == AddonManager.STATE_INSTALLED && + aInstall.installLocation == this.installLocation && + aInstall.addon.id == this.addon.id) { + logger.debug("Cancelling previous pending install of " + aInstall.addon.id); + aInstall.cancel(); + } + } + + let isUpgrade = this.existingAddon && + this.existingAddon._installLocation == this.installLocation; + let requiresRestart = XPIProvider.installRequiresRestart(this.addon); + + logger.debug("Starting install of " + this.addon.id + " from " + this.sourceURI.spec); + AddonManagerPrivate.callAddonListeners("onInstalling", + createWrapper(this.addon), + requiresRestart); + + let stagingDir = this.installLocation.getStagingDir(); + let stagedAddon = stagingDir.clone(); + + Task.spawn((function() { + let installedUnpacked = 0; + yield this.installLocation.requestStagingDir(); + + // Remove any staged items for this add-on + stagedAddon.append(this.addon.id); + yield removeAsync(stagedAddon); + stagedAddon.leafName = this.addon.id + ".xpi"; + yield removeAsync(stagedAddon); + + // First stage the file regardless of whether restarting is necessary + if (this.addon.unpack || Preferences.get(PREF_XPI_UNPACK, false)) { + logger.debug("Addon " + this.addon.id + " will be installed as " + + "an unpacked directory"); + stagedAddon.leafName = this.addon.id; + yield OS.File.makeDir(stagedAddon.path); + yield ZipUtils.extractFilesAsync(this.file, stagedAddon); + installedUnpacked = 1; + } + else { + logger.debug("Addon " + this.addon.id + " will be installed as " + + "a packed xpi"); + stagedAddon.leafName = this.addon.id + ".xpi"; + yield OS.File.copy(this.file.path, stagedAddon.path); + } + + if (requiresRestart) { + // Point the add-on to its extracted files as the xpi may get deleted + this.addon._sourceBundle = stagedAddon; + + // Cache the AddonInternal as it may have updated compatibility info + let stagedJSON = stagedAddon.clone(); + stagedJSON.leafName = this.addon.id + ".json"; + if (stagedJSON.exists()) + stagedJSON.remove(true); + let stream = Cc["@mozilla.org/network/file-output-stream;1"]. + createInstance(Ci.nsIFileOutputStream); + let converter = Cc["@mozilla.org/intl/converter-output-stream;1"]. + createInstance(Ci.nsIConverterOutputStream); + + try { + stream.init(stagedJSON, FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE | + FileUtils.MODE_TRUNCATE, FileUtils.PERMS_FILE, + 0); + converter.init(stream, "UTF-8", 0, 0x0000); + converter.writeString(JSON.stringify(this.addon)); + } + finally { + converter.close(); + stream.close(); + } + + logger.debug("Staged install of " + this.addon.id + " from " + this.sourceURI.spec + " ready; waiting for restart."); + this.state = AddonManager.STATE_INSTALLED; + if (isUpgrade) { + delete this.existingAddon.pendingUpgrade; + this.existingAddon.pendingUpgrade = this.addon; + } + AddonManagerPrivate.callInstallListeners("onInstallEnded", + this.listeners, this.wrapper, + createWrapper(this.addon)); + } + else { + // The install is completed so it should be removed from the active list + XPIProvider.removeActiveInstall(this); + + // TODO We can probably reduce the number of DB operations going on here + // We probably also want to support rolling back failed upgrades etc. + // See bug 553015. + + // Deactivate and remove the old add-on as necessary + let reason = BOOTSTRAP_REASONS.ADDON_INSTALL; + if (this.existingAddon) { + if (Services.vc.compare(this.existingAddon.version, this.addon.version) < 0) + reason = BOOTSTRAP_REASONS.ADDON_UPGRADE; + else + reason = BOOTSTRAP_REASONS.ADDON_DOWNGRADE; + + if (this.existingAddon.bootstrap) { + let file = this.existingAddon._installLocation + .getLocationForID(this.existingAddon.id); + if (this.existingAddon.active) { + XPIProvider.callBootstrapMethod(this.existingAddon, file, + "shutdown", reason, + { newVersion: this.addon.version }); } + + XPIProvider.callBootstrapMethod(this.existingAddon, file, + "uninstall", reason, + { newVersion: this.addon.version }); + XPIProvider.unloadBootstrapScope(this.existingAddon.id); + flushStartupCache(); + } + + if (!isUpgrade && this.existingAddon.active) { + XPIDatabase.updateAddonActive(this.existingAddon, false); + } + } + + // Install the new add-on into its final location + let existingAddonID = this.existingAddon ? this.existingAddon.id : null; + let file = this.installLocation.installAddon(this.addon.id, stagedAddon, + existingAddonID); + + // Update the metadata in the database + this.addon._sourceBundle = file; + this.addon._installLocation = this.installLocation; + this.addon.visible = true; + + if (isUpgrade) { + this.addon = XPIDatabase.updateAddonMetadata(this.existingAddon, this.addon, + file.persistentDescriptor); + let state = XPIStates.getAddon(this.installLocation.name, this.addon.id); + if (state) { + state.syncWithDB(this.addon, true); + } else { + logger.warn("Unexpected missing XPI state for add-on ${id}", this.addon); + } + } + else { + this.addon.active = (this.addon.visible && !this.addon.disabled); + this.addon = XPIDatabase.addAddonMetadata(this.addon, file.persistentDescriptor); + XPIStates.addAddon(this.addon); + this.addon.installDate = this.addon.updateDate; + XPIDatabase.saveChanges(); + } + XPIStates.save(); + + let extraParams = {}; + if (this.existingAddon) { + extraParams.oldVersion = this.existingAddon.version; + } + + if (this.addon.bootstrap) { + XPIProvider.callBootstrapMethod(this.addon, file, "install", + reason, extraParams); + } + + AddonManagerPrivate.callAddonListeners("onInstalled", + createWrapper(this.addon)); + + logger.debug("Install of " + this.sourceURI.spec + " completed."); + this.state = AddonManager.STATE_INSTALLED; + AddonManagerPrivate.callInstallListeners("onInstallEnded", + this.listeners, this.wrapper, + createWrapper(this.addon)); + + if (this.addon.bootstrap) { + if (this.addon.active) { + XPIProvider.callBootstrapMethod(this.addon, file, "startup", + reason, extraParams); + } + else { + // XXX this makes it dangerous to do some things in onInstallEnded + // listeners because important cleanup hasn't been done yet + XPIProvider.unloadBootstrapScope(this.addon.id); } } } + }).bind(this)).then(null, (e) => { + logger.warn("Failed to install " + this.file.path + " from " + this.sourceURI.spec, e); + if (stagedAddon.exists()) + recursiveRemove(stagedAddon); + this.state = AddonManager.STATE_INSTALL_FAILED; + this.error = AddonManager.ERROR_FILE_ACCESS; + XPIProvider.removeActiveInstall(this); + AddonManagerPrivate.callAddonListeners("onOperationCancelled", + createWrapper(this.addon)); + AddonManagerPrivate.callInstallListeners("onInstallFailed", + this.listeners, + this.wrapper); + }).then(() => { + this.removeTemporaryFile(); + return this.installLocation.releaseStagingDir(); }); - } + }, - getInterface(iid) { + getInterface: function AI_getInterface(iid) { if (iid.equals(Ci.nsIAuthPrompt2)) { - let win = null; - if (this.browser) { - win = this.browser.contentWindow || this.browser.ownerDocument.defaultView; - } + let win = this.window; + if (!win && this.browser) + win = this.browser.ownerDocument.defaultView; let factory = Cc["@mozilla.org/prompter;1"]. getService(Ci.nsIPromptFactory); let prompt = factory.getPrompt(win, Ci.nsIAuthPrompt2); - if (this.browser && prompt instanceof Ci.nsILoginManagerPrompter) - prompt.browser = this.browser; + if (this.browser && this.browser.isRemoteBrowser && prompt instanceof Ci.nsILoginManagerPrompter) + prompt.setE10sData(this.browser, null); return prompt; } @@ -6620,113 +5969,46 @@ class DownloadAddonInstall extends AddonInstall { return this.badCertHandler.getInterface(iid); } - - /** - * Postone a pending update, until restart or until the add-on resumes. - * - * @param {Function} resumeFn - a function for the add-on to run - * when resuming. - */ - postpone(resumeFn) { - return Task.spawn((function*() { - this.state = AddonManager.STATE_POSTPONED; - - let stagingDir = this.installLocation.getStagingDir(); - let stagedAddon = stagingDir.clone(); - - yield this.installLocation.requestStagingDir(); - yield this.unstageInstall(stagedAddon); - - stagedAddon.append(this.addon.id); - stagedAddon.leafName = this.addon.id + ".xpi"; - - yield this.stageInstall(true, stagedAddon, true); - - AddonManagerPrivate.callInstallListeners("onInstallPostponed", - this.listeners, this.wrapper) - - // upgrade has been staged for restart, provide a way for it to call the - // resume function. - let callback = AddonManagerPrivate.getUpgradeListener(this.addon.id); - if (callback) { - callback({ - version: this.version, - install: () => { - switch (this.state) { - case AddonManager.STATE_POSTPONED: - if (resumeFn) { - resumeFn(); - } - break; - default: - logger.warn(`${this.addon.id} cannot resume postponed upgrade from state (${this.state})`); - break; - } - }, - }); - } - // Release the staging directory lock, but since the staging dir is populated - // it will not be removed until resumed or installed by restart. - // See also cleanStagingDir() - this.installLocation.releaseStagingDir(); - }).bind(this)); - } } /** - * This class exists just for the specific case of staged add-ons that - * fail to install at startup. When that happens, the add-on remains - * staged but we want to keep track of it like other installs so that we - * can clean it up if the same add-on is installed again (see the comment - * about "pending installs for the same add-on" in AddonInstall.startInstall) + * Creates a new AddonInstall for an already staged install. Used when + * installing the staged install failed for some reason. + * + * @param aDir + * The directory holding the staged install + * @param aManifest + * The cached manifest for the install */ -class StagedAddonInstall extends AddonInstall { - constructor(installLocation, dir, manifest) { - super(installLocation, dir); - - this.name = manifest.name; - this.type = manifest.type; - this.version = manifest.version; - this.icons = manifest.icons; - this.releaseNotesURI = manifest.releaseNotesURI ? - NetUtil.newURI(manifest.releaseNotesURI) : - null; - this.sourceURI = manifest.sourceURI ? - NetUtil.newURI(manifest.sourceURI) : - null; - this.file = null; - this.addon = manifest; +AddonInstall.createStagedInstall = function AI_createStagedInstall(aInstallLocation, aDir, aManifest) { + let url = Services.io.newFileURI(aDir); - this.state = AddonManager.STATE_INSTALLED; - } -} + let install = new AddonInstall(aInstallLocation, aDir); + install.initStagedInstall(aManifest); +}; /** - * Creates a new AddonInstall to install an add-on from a local file. + * Creates a new AddonInstall to install an add-on from a local file. Installs + * always go into the profile install location. * - * @param file + * @param aCallback + * The callback to pass the new AddonInstall to + * @param aFile * The file to install - * @param location - * The location to install to - * @returns Promise - * A Promise that resolves with the new install object. */ -function createLocalInstall(file, location) { - if (!location) { - location = XPIProvider.installLocationsByName[KEY_APP_PROFILE]; - } - let url = Services.io.newFileURI(file); +AddonInstall.createInstall = function AI_createInstall(aCallback, aFile) { + let location = XPIProvider.installLocationsByName[KEY_APP_PROFILE]; + let url = Services.io.newFileURI(aFile); try { - let install = new LocalAddonInstall(location, url); - return install.init().then(() => install); + let install = new AddonInstall(location, url); + install.initLocalInstall(aCallback); } - catch (e) { + catch(e) { logger.error("Error creating install", e); - XPIProvider.removeActiveInstall(this); - return Promise.resolve(null); + makeSafe(aCallback)(null); } -} +}; /** * Creates a new AddonInstall to download and install a URL. @@ -6746,21 +6028,17 @@ function createLocalInstall(file, location) { * @param aBrowser * The browser performing the install */ -function createDownloadInstall(aCallback, aUri, aHash, aName, aIcons, - aVersion, aBrowser) { +AddonInstall.createDownload = function AI_createDownload(aCallback, aUri, aHash, aName, aIcons, + aVersion, aBrowser) { let location = XPIProvider.installLocationsByName[KEY_APP_PROFILE]; let url = NetUtil.newURI(aUri); - if (url instanceof Ci.nsIFileURL) { - let install = new LocalAddonInstall(location, url, aHash); - install.init().then(() => { aCallback(install); }); - } else { - let install = new DownloadAddonInstall(location, url, aHash, null, - aBrowser, aName, null, aIcons, - aVersion); - aCallback(install); - } -} + let install = new AddonInstall(location, url, aHash, null, null, aBrowser); + if (url instanceof Ci.nsIFileURL) + install.initLocalInstall(aCallback); + else + install.initAvailableDownload(aName, null, aIcons, aVersion, aCallback); +}; /** * Creates a new AddonInstall for an update. @@ -6772,37 +6050,28 @@ function createDownloadInstall(aCallback, aUri, aHash, aName, aIcons, * @param aUpdate * The metadata about the new version from the update manifest */ -function createUpdate(aCallback, aAddon, aUpdate) { +AddonInstall.createUpdate = function AI_createUpdate(aCallback, aAddon, aUpdate) { let url = NetUtil.newURI(aUpdate.updateURL); + let releaseNotesURI = null; + try { + if (aUpdate.updateInfoURL) + releaseNotesURI = NetUtil.newURI(escapeAddonURI(aAddon, aUpdate.updateInfoURL)); + } + catch (e) { + // If the releaseNotesURI cannot be parsed then just ignore it. + } - Task.spawn(function*() { - let install; - if (url instanceof Ci.nsIFileURL) { - install = new LocalAddonInstall(aAddon._installLocation, url, - aUpdate.updateHash, aAddon); - yield install.init(); - } else { - install = new DownloadAddonInstall(aAddon._installLocation, url, - aUpdate.updateHash, aAddon, null, - aAddon.selectedLocale.name, aAddon.type, - aAddon.icons, aUpdate.version); - } - try { - if (aUpdate.updateInfoURL) - install.releaseNotesURI = NetUtil.newURI(escapeAddonURI(aAddon, aUpdate.updateInfoURL)); - } - catch (e) { - // If the releaseNotesURI cannot be parsed then just ignore it. - } - - aCallback(install); - }); -} - -// This map is shared between AddonInstallWrapper and AddonWrapper -const wrapperMap = new WeakMap(); -let installFor = wrapper => wrapperMap.get(wrapper); -let addonFor = installFor; + let install = new AddonInstall(aAddon._installLocation, url, + aUpdate.updateHash, releaseNotesURI, aAddon); + if (url instanceof Ci.nsIFileURL) { + install.initLocalInstall(aCallback); + } + else { + install.initAvailableDownload(aAddon.selectedLocale.name ? + aAddon.selectedLocale.name : aAddon.defaultLocale.name, + aAddon.type, aAddon.icons, aUpdate.version, aCallback); + } +}; /** * Creates a wrapper for an AddonInstall that only exposes the public API @@ -6811,69 +6080,55 @@ let addonFor = installFor; * The AddonInstall to create a wrapper for */ function AddonInstallWrapper(aInstall) { - wrapperMap.set(this, aInstall); -} - -AddonInstallWrapper.prototype = { - get __AddonInstallInternal__() { - return AppConstants.DEBUG ? installFor(this) : undefined; - }, - - get type() { - return getExternalType(installFor(this).type); - }, +#ifdef MOZ_EM_DEBUG + this.__defineGetter__("__AddonInstallInternal__", function AIW_debugGetter() { + return aInstall; + }); +#endif - get iconURL() { - return installFor(this).icons[32]; - }, + ["name", "type", "version", "icons", "releaseNotesURI", "file", "state", "error", + "progress", "maxProgress", "certificate", "certName"].forEach(function(aProp) { + this.__defineGetter__(aProp, function AIW_propertyGetter() aInstall[aProp]); + }, this); - get existingAddon() { - let install = installFor(this); - return install.existingAddon ? install.existingAddon.wrapper : null; - }, + this.__defineGetter__("iconURL", function AIW_iconURL() aInstall.icons[32]); - get addon() { - let install = installFor(this); - return install.addon ? install.addon.wrapper : null; - }, - - get sourceURI() { - return installFor(this).sourceURI; - }, + this.__defineGetter__("existingAddon", function AIW_existingAddonGetter() { + return createWrapper(aInstall.existingAddon); + }); + this.__defineGetter__("addon", function AIW_addonGetter() createWrapper(aInstall.addon)); + this.__defineGetter__("sourceURI", function AIW_sourceURIGetter() aInstall.sourceURI); - get linkedInstalls() { - let install = installFor(this); - if (!install.linkedInstalls) + this.__defineGetter__("linkedInstalls", function AIW_linkedInstallsGetter() { + if (!aInstall.linkedInstalls) return null; - return install.linkedInstalls.map(i => i.wrapper); - }, + // Tycho: return [i.wrapper for each (i in aInstall.linkedInstalls)]; + let result = []; + for each (let i in aInstall.linkedInstalls) { + result.push(i.wrapper); + } + + return result; + }); - install: function() { - installFor(this).install(); - }, + this.install = function AIW_install() { + aInstall.install(); + } - cancel: function() { - installFor(this).cancel(); - }, + this.cancel = function AIW_cancel() { + aInstall.cancel(); + } - addListener: function(listener) { - installFor(this).addListener(listener); - }, + this.addListener = function AIW_addListener(listener) { + aInstall.addListener(listener); + } - removeListener: function(listener) { - installFor(this).removeListener(listener); - }, -}; + this.removeListener = function AIW_removeListener(listener) { + aInstall.removeListener(listener); + } +} -["name", "version", "icons", "releaseNotesURI", "file", "state", "error", - "progress", "maxProgress", "certificate", "certName"].forEach(function(aProp) { - Object.defineProperty(AddonInstallWrapper.prototype, aProp, { - get: function() { - return installFor(this)[aProp]; - }, - enumerable: true, - }); -}); +AddonInstallWrapper.prototype = {}; /** * Creates a new update checker. @@ -6940,7 +6195,7 @@ UpdateChecker.prototype = { * @param aMethod * The method to call on the listener */ - callListener: function(aMethod, ...aArgs) { + callListener: function UC_callListener(aMethod, ...aArgs) { if (!(aMethod in this.listener)) return; @@ -6958,7 +6213,7 @@ UpdateChecker.prototype = { * @param updates * The list of update details for the add-on */ - onUpdateCheckComplete: function(aUpdates) { + onUpdateCheckComplete: function UC_onUpdateCheckComplete(aUpdates) { XPIProvider.done(this.addon._updateCheck); this.addon._updateCheck = null; let AUC = AddonUpdateChecker; @@ -7000,19 +6255,19 @@ UpdateChecker.prototype = { } if (compatUpdate) - this.callListener("onCompatibilityUpdateAvailable", this.addon.wrapper); + this.callListener("onCompatibilityUpdateAvailable", createWrapper(this.addon)); else - this.callListener("onNoCompatibilityUpdateAvailable", this.addon.wrapper); + this.callListener("onNoCompatibilityUpdateAvailable", createWrapper(this.addon)); function sendUpdateAvailableMessages(aSelf, aInstall) { if (aInstall) { - aSelf.callListener("onUpdateAvailable", aSelf.addon.wrapper, + aSelf.callListener("onUpdateAvailable", createWrapper(aSelf.addon), aInstall.wrapper); } else { - aSelf.callListener("onNoUpdateAvailable", aSelf.addon.wrapper); + aSelf.callListener("onNoUpdateAvailable", createWrapper(aSelf.addon)); } - aSelf.callListener("onUpdateFinished", aSelf.addon.wrapper, + aSelf.callListener("onUpdateFinished", createWrapper(aSelf.addon), AddonManager.UPDATE_STATUS_NO_ERROR); } @@ -7021,14 +6276,13 @@ UpdateChecker.prototype = { this.addon.compatibilityOverrides; let update = AUC.getNewestCompatibleUpdate(aUpdates, - this.appVersion, - this.platformVersion, - ignoreMaxVersion, - ignoreStrictCompat, - compatOverrides); - - if (update && Services.vc.compare(this.addon.version, update.version) < 0 - && !this.addon._installLocation.locked) { + this.appVersion, + this.platformVersion, + ignoreMaxVersion, + ignoreStrictCompat, + compatOverrides); + + if (update && Services.vc.compare(this.addon.version, update.version) < 0) { for (let currentInstall of XPIProvider.installs) { // Skip installs that don't match the available update if (currentInstall.existingAddon != this.addon || @@ -7047,8 +6301,9 @@ UpdateChecker.prototype = { return; } - createUpdate(aInstall => { - sendUpdateAvailableMessages(this, aInstall); + let self = this; + AddonInstall.createUpdate(function onUpdateCheckComplete_createUpdate(aInstall) { + sendUpdateAvailableMessages(self, aInstall); }, this.addon, update); } else { @@ -7062,18 +6317,18 @@ UpdateChecker.prototype = { * @param aError * An error status */ - onUpdateCheckError: function(aError) { + onUpdateCheckError: function UC_onUpdateCheckError(aError) { XPIProvider.done(this.addon._updateCheck); this.addon._updateCheck = null; - this.callListener("onNoCompatibilityUpdateAvailable", this.addon.wrapper); - this.callListener("onNoUpdateAvailable", this.addon.wrapper); - this.callListener("onUpdateFinished", this.addon.wrapper, aError); + this.callListener("onNoCompatibilityUpdateAvailable", createWrapper(this.addon)); + this.callListener("onNoUpdateAvailable", createWrapper(this.addon)); + this.callListener("onUpdateFinished", createWrapper(this.addon), aError); }, /** * Called to cancel an in-progress update check */ - cancel: function() { + cancel: function UC_cancel() { let parser = this._parser; if (parser) { this._parser = null; @@ -7089,16 +6344,10 @@ UpdateChecker.prototype = { * or an install manifest. */ function AddonInternal() { - this._hasResourceCache = new Map(); - - XPCOMUtils.defineLazyGetter(this, "wrapper", () => { - return new AddonWrapper(this); - }); } AddonInternal.prototype = { _selectedLocale: null, - _hasResourceCache: null, active: false, visible: false, userDisabled: false, @@ -7107,22 +6356,11 @@ AddonInternal.prototype = { sourceURI: null, releaseNotesURI: null, foreignInstall: false, - seen: true, - skinnable: false, - - /** - * @property {Array<string>} dependencies - * An array of bootstrapped add-on IDs on which this add-on depends. - * The add-on will remain appDisabled if any of the dependent - * add-ons is not installed and enabled. - */ - dependencies: Object.freeze([]), - hasEmbeddedWebExtension: false, get selectedLocale() { if (this._selectedLocale) return this._selectedLocale; - let locale = Locale.findClosestLocale(this.locales); + let locale = findClosestLocale(this.locales); this._selectedLocale = locale ? locale : this.defaultLocale; return this._selectedLocale; }, @@ -7132,32 +6370,6 @@ AddonInternal.prototype = { this.updateURL.substring(0, 6) == "https:"); }, - get isCorrectlySigned() { - switch (this._installLocation.name) { - case KEY_APP_SYSTEM_ADDONS: - // System add-ons must be signed by the system key. - return this.signedState == AddonManager.SIGNEDSTATE_SYSTEM - - case KEY_APP_SYSTEM_DEFAULTS: - case KEY_APP_TEMPORARY: - // Temporary and built-in system add-ons do not require signing. - return true; - - case KEY_APP_SYSTEM_SHARE: - case KEY_APP_SYSTEM_LOCAL: - // On UNIX platforms except OSX, an additional location for system - // add-ons exists in /usr/{lib,share}/mozilla/extensions. Add-ons - // installed there do not require signing. - if (Services.appinfo.OS != "Darwin") - return true; - break; - } - - if (this.signedState === AddonManager.SIGNEDSTATE_NOT_REQUIRED) - return true; - return this.signedState > AddonManager.SIGNEDSTATE_MISSING; - }, - get isCompatible() { return this.isCompatibleWith(); }, @@ -7209,23 +6421,42 @@ AddonInternal.prototype = { return matchedOS && !needsABI; }, - isCompatibleWith: function(aAppVersion, aPlatformVersion) { + isCompatibleWith: function AddonInternal_isCompatibleWith(aAppVersion, aPlatformVersion) { + // Experiments are installed through an external mechanism that + // limits target audience to compatible clients. We trust it knows what + // it's doing and skip compatibility checks. + // + // This decision does forfeit defense in depth. If the experiments system + // is ever wrong about targeting an add-on to a specific application + // or platform, the client will likely see errors. + if (this.type == "experiment") { + return true; + } + let app = this.matchingTargetApplication; if (!app) return false; - // set reasonable defaults for minVersion and maxVersion - let minVersion = app.minVersion || "0"; - let maxVersion = app.maxVersion || "*"; - if (!aAppVersion) aAppVersion = Services.appinfo.version; if (!aPlatformVersion) aPlatformVersion = Services.appinfo.platformVersion; + this.native = false; + let version; - if (app.id == Services.appinfo.ID) + if (app.id == Services.appinfo.ID) { version = aAppVersion; + this.native = true; + } +#ifdef MOZ_PHOENIX_EXTENSIONS + else if (app.id == FIREFOX_ID) { + version = FIREFOX_APPCOMPATVERSION; + if (this.type == "locale") + //Never allow language packs in Firefox compatibility mode + return false; + } +#endif else if (app.id == TOOLKIT_ID) version = aPlatformVersion @@ -7248,20 +6479,24 @@ AddonInternal.prototype = { // Extremely old extensions should not be compatible by default. let minCompatVersion; +#ifdef MOZ_PHOENIX_EXTENSIONS + if (app.id == Services.appinfo.ID || app.id == FIREFOX_ID) +#else if (app.id == Services.appinfo.ID) +#endif minCompatVersion = XPIProvider.minCompatibleAppVersion; else if (app.id == TOOLKIT_ID) minCompatVersion = XPIProvider.minCompatiblePlatformVersion; if (minCompatVersion && - Services.vc.compare(minCompatVersion, maxVersion) > 0) + Services.vc.compare(minCompatVersion, app.maxVersion) > 0) return false; - return Services.vc.compare(version, minVersion) >= 0; + return Services.vc.compare(version, app.minVersion) >= 0; } - return (Services.vc.compare(version, minVersion) >= 0) && - (Services.vc.compare(version, maxVersion) <= 0) + return (Services.vc.compare(version, app.minVersion) >= 0) && + (Services.vc.compare(version, app.maxVersion) <= 0) }, get matchingTargetApplication() { @@ -7272,6 +6507,16 @@ AddonInternal.prototype = { if (targetApp.id == TOOLKIT_ID) app = targetApp; } +#ifdef MOZ_PHOENIX_EXTENSIONS + //Special case: check for Firefox TargetApps. this has to be done AFTER + //the initial check to make sure appinfo.ID is preferred, even if + //Firefox is listed before it in the install manifest. + for (let targetApp of this.targetApplications) { + if (targetApp.id == FIREFOX_ID) //Firefox GUID + return targetApp; + } +#endif + // Return toolkit ID if toolkit. return app; }, @@ -7280,7 +6525,7 @@ AddonInternal.prototype = { if (staticItem) return staticItem.level; - return Blocklist.getAddonBlocklistState(this.wrapper); + return Blocklist.getAddonBlocklistState(createWrapper(this)); }, get blocklistURL() { @@ -7290,19 +6535,22 @@ AddonInternal.prototype = { return url.replace(/%blockID%/g, staticItem.blockID); } - return Blocklist.getAddonBlocklistURL(this.wrapper); + return Blocklist.getAddonBlocklistURL(createWrapper(this)); }, - applyCompatibilityUpdate: function(aUpdate, aSyncCompatibility) { - for (let targetApp of this.targetApplications) { - for (let updateTarget of aUpdate.targetApplications) { - if (targetApp.id == updateTarget.id && (aSyncCompatibility || - Services.vc.compare(targetApp.maxVersion, updateTarget.maxVersion) < 0)) { - targetApp.minVersion = updateTarget.minVersion; - targetApp.maxVersion = updateTarget.maxVersion; - } - } + applyCompatibilityUpdate: function AddonInternal_applyCompatibilityUpdate(aUpdate, aSyncCompatibility) { + if (this.strictCompatibility) { + return; } + this.targetApplications.forEach(function(aTargetApp) { + aUpdate.targetApplications.forEach(function(aUpdateTarget) { + if (aTargetApp.id == aUpdateTarget.id && (aSyncCompatibility || + Services.vc.compare(aTargetApp.maxVersion, aUpdateTarget.maxVersion) < 0)) { + aTargetApp.minVersion = aUpdateTarget.minVersion; + aTargetApp.maxVersion = aUpdateTarget.maxVersion; + } + }); + }); if (aUpdate.multiprocessCompatible !== undefined) this.multiprocessCompatible = aUpdate.multiprocessCompatible; this.appDisabled = !isUsableAddon(this); @@ -7337,13 +6585,9 @@ AddonInternal.prototype = { * @return an object containing copies of the properties of this object * ignoring private properties, functions, getters and setters */ - toJSON: function(aKey) { + toJSON: function AddonInternal_toJSON(aKey) { let obj = {}; for (let prop in this) { - // Ignore the wrapper property - if (prop == "wrapper") - continue; - // Ignore private properties if (prop.substring(0, 1) == "_") continue; @@ -7374,25 +6618,32 @@ AddonInternal.prototype = { * @param aObj * A JS object containing the cached metadata */ - importMetadata: function(aObj) { - for (let prop of PENDING_INSTALL_METADATA) { - if (!(prop in aObj)) - continue; + importMetadata: function AddonInternal_importMetaData(aObj) { + PENDING_INSTALL_METADATA.forEach(function(aProp) { + if (!(aProp in aObj)) + return; - this[prop] = aObj[prop]; - } + this[aProp] = aObj[aProp]; + }, this); // Compatibility info may have changed so update appDisabled this.appDisabled = !isUsableAddon(this); }, - permissions: function() { + permissions: function AddonInternal_permissions() { let permissions = 0; // Add-ons that aren't installed cannot be modified in any way if (!(this.inDatabase)) return permissions; + // Experiments can only be uninstalled. An uninstall reflects the user + // intent of "disable this experiment." This is partially managed by the + // experiments manager. + if (this.type == "experiment") { + return AddonManager.PERM_CAN_UNINSTALL; + } + if (!this.appDisabled) { if (this.userDisabled || this.softDisabled) { permissions |= AddonManager.PERM_CAN_ENABLE; @@ -7405,13 +6656,8 @@ AddonInternal.prototype = { // Add-ons that are in locked install locations, or are pending uninstall // cannot be upgraded or uninstalled if (!this._installLocation.locked && !this.pendingUninstall) { - // Experiments cannot be upgraded. - // System add-on upgrades are triggered through a different mechanism (see updateSystemAddons()) - let isSystem = (this._installLocation.name == KEY_APP_SYSTEM_DEFAULTS || - this._installLocation.name == KEY_APP_SYSTEM_ADDONS); - // Add-ons that are installed by a file link cannot be upgraded. - if (this.type != "experiment" && - !this._installLocation.isLinkedAddon(this.id) && !isSystem) { + // Add-ons that are installed by a file link cannot be upgraded + if (!this._installLocation.isLinkedAddon(this.id)) { permissions |= AddonManager.PERM_CAN_UPGRADE; } @@ -7423,91 +6669,109 @@ AddonInternal.prototype = { }; /** + * Creates an AddonWrapper for an AddonInternal. + * + * @param addon + * The AddonInternal to wrap + * @return an AddonWrapper or null if addon was null + */ +function createWrapper(aAddon) { + if (!aAddon) + return null; + if (!aAddon._wrapper) { + aAddon._hasResourceCache = new Map(); + aAddon._wrapper = new AddonWrapper(aAddon); + } + return aAddon._wrapper; +} + +/** * The AddonWrapper wraps an Addon to provide the data visible to consumers of * the public API. */ function AddonWrapper(aAddon) { - wrapperMap.set(this, aAddon); -} - -AddonWrapper.prototype = { - get __AddonInternal__() { - return AppConstants.DEBUG ? addonFor(this) : undefined; - }, +#ifdef MOZ_EM_DEBUG + this.__defineGetter__("__AddonInternal__", function AW_debugGetter() { + return aAddon; + }); +#endif - get seen() { - return addonFor(this).seen; - }, + function chooseValue(aObj, aProp) { + let repositoryAddon = aAddon._repositoryAddon; + let objValue = aObj[aProp]; - get hasEmbeddedWebExtension() { - return addonFor(this).hasEmbeddedWebExtension; - }, + if (repositoryAddon && (aProp in repositoryAddon) && + (objValue === undefined || objValue === null)) { + return [repositoryAddon[aProp], true]; + } - markAsSeen: function() { - addonFor(this).seen = true; - XPIDatabase.saveChanges(); - }, + return [objValue, false]; + } - get type() { - return getExternalType(addonFor(this).type); - }, + ["id", "syncGUID", "version", "type", "isCompatible", "isPlatformCompatible", + "providesUpdatesSecurely", "blocklistState", "blocklistURL", "appDisabled", + "softDisabled", "skinnable", "size", "foreignInstall", "hasBinaryComponents", + "strictCompatibility", "compatibilityOverrides", "updateURL", + "getDataDirectory", "multiprocessCompatible", "native"].forEach(function(aProp) { + this.__defineGetter__(aProp, function AddonWrapper_propertyGetter() aAddon[aProp]); + }, this); + + ["fullDescription", "developerComments", "eula", "supportURL", + "contributionURL", "contributionAmount", "averageRating", "reviewCount", + "reviewURL", "totalDownloads", "weeklyDownloads", "dailyUsers", + "repositoryStatus"].forEach(function(aProp) { + this.__defineGetter__(aProp, function AddonWrapper_repoPropertyGetter() { + if (aAddon._repositoryAddon) + return aAddon._repositoryAddon[aProp]; - get isWebExtension() { - return addonFor(this).type == "webextension"; - }, + return null; + }); + }, this); - get temporarilyInstalled() { - return addonFor(this)._installLocation == TemporaryInstallLocation; - }, + this.__defineGetter__("aboutURL", function AddonWrapper_aboutURLGetter() { + return this.isActive ? aAddon["aboutURL"] : null; + }); - get aboutURL() { - return this.isActive ? addonFor(this)["aboutURL"] : null; - }, + ["installDate", "updateDate"].forEach(function(aProp) { + this.__defineGetter__(aProp, function AddonWrapper_datePropertyGetter() new Date(aAddon[aProp])); + }, this); - get optionsURL() { - if (!this.isActive) { - return null; - } + ["sourceURI", "releaseNotesURI"].forEach(function(aProp) { + this.__defineGetter__(aProp, function AddonWrapper_URIPropertyGetter() { + let [target, fromRepo] = chooseValue(aAddon, aProp); + if (!target) + return null; + if (fromRepo) + return target; + return NetUtil.newURI(target); + }); + }, this); - let addon = addonFor(this); - if (addon.optionsURL) { - if (this.isWebExtension || this.hasEmbeddedWebExtension) { - // The internal object's optionsURL property comes from the addons - // DB and should be a relative URL. However, extensions with - // options pages installed before bug 1293721 was fixed got absolute - // URLs in the addons db. This code handles both cases. - let base = ExtensionManagement.getURLForExtension(addon.id); - if (!base) { - return null; - } - return new URL(addon.optionsURL, base).href; - } - return addon.optionsURL; - } + this.__defineGetter__("optionsURL", function AddonWrapper_optionsURLGetter() { + if (this.isActive && aAddon.optionsURL) + return aAddon.optionsURL; - if (this.hasResource("options.xul")) + if (this.isActive && this.hasResource("options.xul")) return this.getResourceURI("options.xul").spec; return null; - }, + }, this); - get optionsType() { + this.__defineGetter__("optionsType", function AddonWrapper_optionsTypeGetter() { if (!this.isActive) return null; - let addon = addonFor(this); let hasOptionsXUL = this.hasResource("options.xul"); let hasOptionsURL = !!this.optionsURL; - if (addon.optionsType) { - switch (parseInt(addon.optionsType, 10)) { + if (aAddon.optionsType) { + switch (parseInt(aAddon.optionsType, 10)) { case AddonManager.OPTIONS_TYPE_DIALOG: case AddonManager.OPTIONS_TYPE_TAB: - return hasOptionsURL ? addon.optionsType : null; + return hasOptionsURL ? aAddon.optionsType : null; case AddonManager.OPTIONS_TYPE_INLINE: case AddonManager.OPTIONS_TYPE_INLINE_INFO: - case AddonManager.OPTIONS_TYPE_INLINE_BROWSER: - return (hasOptionsXUL || hasOptionsURL) ? addon.optionsType : null; + return (hasOptionsXUL || hasOptionsURL) ? aAddon.optionsType : null; } return null; } @@ -7519,78 +6783,132 @@ AddonWrapper.prototype = { return AddonManager.OPTIONS_TYPE_DIALOG; return null; - }, + }, this); - get iconURL() { - return AddonManager.getPreferredIconURL(this, 48); - }, + this.__defineGetter__("iconURL", function AddonWrapper_iconURLGetter() { + return this.icons[32] || undefined; + }, this); - get icon64URL() { - return AddonManager.getPreferredIconURL(this, 64); - }, + this.__defineGetter__("icon64URL", function AddonWrapper_icon64URLGetter() { + return this.icons[64] || undefined; + }, this); - get icons() { - let addon = addonFor(this); + this.__defineGetter__("icons", function AddonWrapper_iconsGetter() { let icons = {}; - - if (addon._repositoryAddon) { - for (let size in addon._repositoryAddon.icons) { - icons[size] = addon._repositoryAddon.icons[size]; + if (aAddon._repositoryAddon) { + for (let size in aAddon._repositoryAddon.icons) { + icons[size] = aAddon._repositoryAddon.icons[size]; } } + if (this.isActive && aAddon.iconURL) { + icons[32] = aAddon.iconURL; + } else if (this.hasResource("icon.png")) { + icons[32] = this.getResourceURI("icon.png").spec; + } + if (this.isActive && aAddon.icon64URL) { + icons[64] = aAddon.icon64URL; + } else if (this.hasResource("icon64.png")) { + icons[64] = this.getResourceURI("icon64.png").spec; + } + Object.freeze(icons); + return icons; + }, this); - if (addon.icons) { - for (let size in addon.icons) { - icons[size] = this.getResourceURI(addon.icons[size]).spec; + PROP_LOCALE_SINGLE.forEach(function(aProp) { + this.__defineGetter__(aProp, function AddonWrapper_singleLocaleGetter() { + // Override XPI creator if repository creator is defined + if (aProp == "creator" && + aAddon._repositoryAddon && aAddon._repositoryAddon.creator) { + return aAddon._repositoryAddon.creator; } - } else { - // legacy add-on that did not update its icon data yet - if (this.hasResource("icon.png")) { - icons[32] = icons[48] = this.getResourceURI("icon.png").spec; + + let result = null; + + if (aAddon.active) { + try { + let pref = PREF_EM_EXTENSION_FORMAT + aAddon.id + "." + aProp; + let value = Preferences.get(pref, null, Ci.nsIPrefLocalizedString); + if (value) + result = value; + } + catch (e) { + } } - if (this.hasResource("icon64.png")) { - icons[64] = this.getResourceURI("icon64.png").spec; + + if (result == null) { + if (typeof aAddon.selectedLocale[aProp] == "string" && aAddon.selectedLocale[aProp].length) + [result, ] = chooseValue(aAddon.selectedLocale, aProp); + else + [result, ] = chooseValue(aAddon.defaultLocale, aProp); } - } - if (this.isActive && addon.iconURL) { - icons[32] = addon.iconURL; - icons[48] = addon.iconURL; - } + if (aProp == "creator") + return result ? new AddonManagerPrivate.AddonAuthor(result) : null; - if (this.isActive && addon.icon64URL) { - icons[64] = addon.icon64URL; - } + return result; + }); + }, this); + + PROP_LOCALE_MULTI.forEach(function(aProp) { + this.__defineGetter__(aProp, function AddonWrapper_multiLocaleGetter() { + let results = null; + let usedRepository = false; + + if (aAddon.active) { + let pref = PREF_EM_EXTENSION_FORMAT + aAddon.id + "." + + aProp.substring(0, aProp.length - 1); + let list = Services.prefs.getChildList(pref, {}); + if (list.length > 0) { + list.sort(); + results = []; + list.forEach(function(aPref) { + let value = Preferences.get(aPref, null, Ci.nsIPrefLocalizedString); + if (value) + results.push(value); + }); + } + } - Object.freeze(icons); - return icons; - }, + if (results == null) { + if (aAddon.selectedLocale[aProp] instanceof Array && aAddon.selectedLocale[aProp].length) + [results, usedRepository] = chooseValue(aAddon.selectedLocale, aProp); + else + [results, usedRepository] = chooseValue(aAddon.defaultLocale, aProp); + } + + if (results && !usedRepository) { + results = results.map(function mapResult(aResult) { + return new AddonManagerPrivate.AddonAuthor(aResult); + }); + } - get screenshots() { - let addon = addonFor(this); - let repositoryAddon = addon._repositoryAddon; + return results; + }); + }, this); + + this.__defineGetter__("screenshots", function AddonWrapper_screenshotsGetter() { + let repositoryAddon = aAddon._repositoryAddon; if (repositoryAddon && ("screenshots" in repositoryAddon)) { let repositoryScreenshots = repositoryAddon.screenshots; if (repositoryScreenshots && repositoryScreenshots.length > 0) return repositoryScreenshots; } - if (addon.type == "theme" && this.hasResource("preview.png")) { + if (aAddon.type == "theme" && this.hasResource("preview.png")) { let url = this.getResourceURI("preview.png").spec; return [new AddonManagerPrivate.AddonScreenshot(url)]; } return null; - }, + }); - get applyBackgroundUpdates() { - return addonFor(this).applyBackgroundUpdates; - }, - set applyBackgroundUpdates(val) { - let addon = addonFor(this); + this.__defineGetter__("applyBackgroundUpdates", function AddonWrapper_applyBackgroundUpdatesGetter() { + return aAddon.applyBackgroundUpdates; + }); + this.__defineSetter__("applyBackgroundUpdates", function AddonWrapper_applyBackgroundUpdatesSetter(val) { if (this.type == "experiment") { logger.warn("Setting applyBackgroundUpdates on an experiment is not supported."); - return addon.applyBackgroundUpdates; + return; } if (val != AddonManager.AUTOUPDATE_DEFAULT && @@ -7600,211 +6918,184 @@ AddonWrapper.prototype = { AddonManager.AUTOUPDATE_DISABLE; } - if (val == addon.applyBackgroundUpdates) + if (val == aAddon.applyBackgroundUpdates) return val; - XPIDatabase.setAddonProperties(addon, { + XPIDatabase.setAddonProperties(aAddon, { applyBackgroundUpdates: val }); AddonManagerPrivate.callAddonListeners("onPropertyChanged", this, ["applyBackgroundUpdates"]); return val; - }, + }); - set syncGUID(val) { - let addon = addonFor(this); - if (addon.syncGUID == val) + this.__defineSetter__("syncGUID", function AddonWrapper_syncGUIDGetter(val) { + if (aAddon.syncGUID == val) return val; - if (addon.inDatabase) - XPIDatabase.setAddonSyncGUID(addon, val); + if (aAddon.inDatabase) + XPIDatabase.setAddonSyncGUID(aAddon, val); - addon.syncGUID = val; + aAddon.syncGUID = val; return val; - }, + }); - get install() { - let addon = addonFor(this); - if (!("_install" in addon) || !addon._install) + this.__defineGetter__("install", function AddonWrapper_installGetter() { + if (!("_install" in aAddon) || !aAddon._install) return null; - return addon._install.wrapper; - }, + return aAddon._install.wrapper; + }); - get pendingUpgrade() { - let addon = addonFor(this); - return addon.pendingUpgrade ? addon.pendingUpgrade.wrapper : null; - }, + this.__defineGetter__("pendingUpgrade", function AddonWrapper_pendingUpgradeGetter() { + return createWrapper(aAddon.pendingUpgrade); + }); - get scope() { - let addon = addonFor(this); - if (addon._installLocation) - return addon._installLocation.scope; + this.__defineGetter__("scope", function AddonWrapper_scopeGetter() { + if (aAddon._installLocation) + return aAddon._installLocation.scope; return AddonManager.SCOPE_PROFILE; - }, + }); - get pendingOperations() { - let addon = addonFor(this); + this.__defineGetter__("pendingOperations", function AddonWrapper_pendingOperationsGetter() { let pending = 0; - if (!(addon.inDatabase)) { + if (!(aAddon.inDatabase)) { // Add-on is pending install if there is no associated install (shouldn't // happen here) or if the install is in the process of or has successfully // completed the install. If an add-on is pending install then we ignore // any other pending operations. - if (!addon._install || addon._install.state == AddonManager.STATE_INSTALLING || - addon._install.state == AddonManager.STATE_INSTALLED) + if (!aAddon._install || aAddon._install.state == AddonManager.STATE_INSTALLING || + aAddon._install.state == AddonManager.STATE_INSTALLED) return AddonManager.PENDING_INSTALL; } - else if (addon.pendingUninstall) { + else if (aAddon.pendingUninstall) { // If an add-on is pending uninstall then we ignore any other pending // operations return AddonManager.PENDING_UNINSTALL; } - if (addon.active && addon.disabled) - pending |= AddonManager.PENDING_DISABLE; - else if (!addon.active && !addon.disabled) - pending |= AddonManager.PENDING_ENABLE; + // Extensions have an intentional inconsistency between what the DB says is + // enabled and what we say to the ouside world. so we need to cover up that + // lie here as well. + if (aAddon.type != "experiment") { + if (aAddon.active && aAddon.disabled) + pending |= AddonManager.PENDING_DISABLE; + else if (!aAddon.active && !aAddon.disabled) + pending |= AddonManager.PENDING_ENABLE; + } - if (addon.pendingUpgrade) + if (aAddon.pendingUpgrade) pending |= AddonManager.PENDING_UPGRADE; return pending; - }, + }); - get operationsRequiringRestart() { - let addon = addonFor(this); + this.__defineGetter__("operationsRequiringRestart", function AddonWrapper_operationsRequiringRestartGetter() { let ops = 0; - if (XPIProvider.installRequiresRestart(addon)) + if (XPIProvider.installRequiresRestart(aAddon)) ops |= AddonManager.OP_NEEDS_RESTART_INSTALL; - if (XPIProvider.uninstallRequiresRestart(addon)) + if (XPIProvider.uninstallRequiresRestart(aAddon)) ops |= AddonManager.OP_NEEDS_RESTART_UNINSTALL; - if (XPIProvider.enableRequiresRestart(addon)) + if (XPIProvider.enableRequiresRestart(aAddon)) ops |= AddonManager.OP_NEEDS_RESTART_ENABLE; - if (XPIProvider.disableRequiresRestart(addon)) + if (XPIProvider.disableRequiresRestart(aAddon)) ops |= AddonManager.OP_NEEDS_RESTART_DISABLE; return ops; - }, + }); - get isDebuggable() { - return this.isActive && addonFor(this).bootstrap; - }, + this.__defineGetter__("isDebuggable", function AddonWrapper_isDebuggable() { + return this.isActive && aAddon.bootstrap; + }); - get permissions() { - return addonFor(this).permissions(); - }, + this.__defineGetter__("permissions", function AddonWrapper_permisionsGetter() { + return aAddon.permissions(); + }); - get isActive() { - let addon = addonFor(this); - if (!addon.active) + this.__defineGetter__("isActive", function AddonWrapper_isActiveGetter() { + if (Services.appinfo.inSafeMode) return false; - if (!Services.appinfo.inSafeMode) - return true; - return addon.bootstrap && canRunInSafeMode(addon); - }, + return aAddon.active; + }); - get userDisabled() { - let addon = addonFor(this); - return addon.softDisabled || addon.userDisabled; - }, - set userDisabled(val) { - let addon = addonFor(this); + this.__defineGetter__("userDisabled", function AddonWrapper_userDisabledGetter() { + if (XPIProvider._enabledExperiments.has(aAddon.id)) { + return false; + } + + return aAddon.softDisabled || aAddon.userDisabled; + }); + this.__defineSetter__("userDisabled", function AddonWrapper_userDisabledSetter(val) { if (val == this.userDisabled) { return val; } - if (addon.inDatabase) { - if (addon.type == "theme" && val) { - if (addon.internalName == XPIProvider.defaultSkin) + if (aAddon.type == "experiment") { + if (val) { + XPIProvider._enabledExperiments.delete(aAddon.id); + } else { + XPIProvider._enabledExperiments.add(aAddon.id); + } + } + + if (aAddon.inDatabase) { + if (aAddon.type == "theme" && val) { + if (aAddon.internalName == XPIProvider.defaultSkin) throw new Error("Cannot disable the default theme"); XPIProvider.enableDefaultTheme(); } else { - // hidden and system add-ons should not be user disasbled, - // as there is no UI to re-enable them. - if (this.hidden) { - throw new Error(`Cannot disable hidden add-on ${addon.id}`); - } - XPIProvider.updateAddonDisabledState(addon, val); + XPIProvider.updateAddonDisabledState(aAddon, val); } } else { - addon.userDisabled = val; + aAddon.userDisabled = val; // When enabling remove the softDisabled flag if (!val) - addon.softDisabled = false; + aAddon.softDisabled = false; } return val; - }, + }); - set softDisabled(val) { - let addon = addonFor(this); - if (val == addon.softDisabled) + this.__defineSetter__("softDisabled", function AddonWrapper_softDisabledSetter(val) { + if (val == aAddon.softDisabled) return val; - if (addon.inDatabase) { + if (aAddon.inDatabase) { // When softDisabling a theme just enable the active theme - if (addon.type == "theme" && val && !addon.userDisabled) { - if (addon.internalName == XPIProvider.defaultSkin) + if (aAddon.type == "theme" && val && !aAddon.userDisabled) { + if (aAddon.internalName == XPIProvider.defaultSkin) throw new Error("Cannot disable the default theme"); XPIProvider.enableDefaultTheme(); } else { - XPIProvider.updateAddonDisabledState(addon, undefined, val); + XPIProvider.updateAddonDisabledState(aAddon, undefined, val); } } - else if (!addon.userDisabled) { + else { // Only set softDisabled if not already disabled - addon.softDisabled = val; + if (!aAddon.userDisabled) + aAddon.softDisabled = val; } return val; - }, - - get hidden() { - let addon = addonFor(this); - if (addon._installLocation.name == KEY_APP_TEMPORARY) - return false; - - return (addon._installLocation.name == KEY_APP_SYSTEM_DEFAULTS || - addon._installLocation.name == KEY_APP_SYSTEM_ADDONS); - }, - - get isSystem() { - let addon = addonFor(this); - return (addon._installLocation.name == KEY_APP_SYSTEM_DEFAULTS || - addon._installLocation.name == KEY_APP_SYSTEM_ADDONS); - }, - - // Returns true if Firefox Sync should sync this addon. Only non-hotfixes - // directly in the profile are considered syncable. - get isSyncable() { - let addon = addonFor(this); - let hotfixID = Preferences.get(PREF_EM_HOTFIX_ID, undefined); - if (hotfixID && hotfixID == addon.id) { - return false; - } - return (addon._installLocation.name == KEY_APP_PROFILE); - }, + }); - isCompatibleWith: function(aAppVersion, aPlatformVersion) { - return addonFor(this).isCompatibleWith(aAppVersion, aPlatformVersion); - }, + this.isCompatibleWith = function AddonWrapper_isCompatiblewith(aAppVersion, aPlatformVersion) { + return aAddon.isCompatibleWith(aAppVersion, aPlatformVersion); + }; - uninstall: function(alwaysAllowUndo) { - let addon = addonFor(this); - XPIProvider.uninstallAddon(addon, alwaysAllowUndo); - }, + this.uninstall = function AddonWrapper_uninstall(alwaysAllowUndo) { + XPIProvider.uninstallAddon(aAddon, alwaysAllowUndo); + }; - cancelUninstall: function() { - let addon = addonFor(this); - XPIProvider.cancelUninstallAddon(addon); - }, + this.cancelUninstall = function AddonWrapper_cancelUninstall() { + XPIProvider.cancelUninstallAddon(aAddon); + }; - findUpdates: function(aListener, aReason, aAppVersion, aPlatformVersion) { + this.findUpdates = function AddonWrapper_findUpdates(aListener, aReason, aAppVersion, aPlatformVersion) { // Short-circuit updates for experiments because updates are handled // through the Experiments Manager. if (this.type == "experiment") { @@ -7813,40 +7104,41 @@ AddonWrapper.prototype = { return; } - new UpdateChecker(addonFor(this), aListener, aReason, aAppVersion, aPlatformVersion); - }, + new UpdateChecker(aAddon, aListener, aReason, aAppVersion, aPlatformVersion); + }; // Returns true if there was an update in progress, false if there was no update to cancel - cancelUpdate: function() { - let addon = addonFor(this); - if (addon._updateCheck) { - addon._updateCheck.cancel(); + this.cancelUpdate = function AddonWrapper_cancelUpdate() { + if (aAddon._updateCheck) { + aAddon._updateCheck.cancel(); return true; } return false; - }, + }; - hasResource: function(aPath) { - let addon = addonFor(this); - if (addon._hasResourceCache.has(aPath)) - return addon._hasResourceCache.get(aPath); + this.hasResource = function AddonWrapper_hasResource(aPath) { + if (aAddon._hasResourceCache.has(aPath)) + return aAddon._hasResourceCache.get(aPath); - let bundle = addon._sourceBundle.clone(); + let bundle = aAddon._sourceBundle.clone(); // Bundle may not exist any more if the addon has just been uninstalled, // but explicitly first checking .exists() results in unneeded file I/O. try { var isDir = bundle.isDirectory(); } catch (e) { - addon._hasResourceCache.set(aPath, false); + aAddon._hasResourceCache.set(aPath, false); return false; } if (isDir) { - if (aPath) - aPath.split("/").forEach(part => bundle.append(part)); + if (aPath) { + aPath.split("/").forEach(function(aPart) { + bundle.append(aPart); + }); + } let result = bundle.exists(); - addon._hasResourceCache.set(aPath, result); + aAddon._hasResourceCache.set(aPath, result); return result; } @@ -7855,11 +7147,11 @@ AddonWrapper.prototype = { try { zipReader.open(bundle); let result = zipReader.hasEntry(aPath); - addon._hasResourceCache.set(aPath, result); + aAddon._hasResourceCache.set(aPath, result); return result; } catch (e) { - addon._hasResourceCache.set(aPath, false); + aAddon._hasResourceCache.set(aPath, false); return false; } finally { @@ -7868,34 +7160,6 @@ AddonWrapper.prototype = { }, /** - * Reloads the add-on. - * - * For temporarily installed add-ons, this uninstalls and re-installs the - * add-on. Otherwise, the addon is disabled and then re-enabled, and the cache - * is flushed. - * - * @return Promise - */ - reload: function() { - return new Promise((resolve) => { - const addon = addonFor(this); - - logger.debug(`reloading add-on ${addon.id}`); - - if (!this.temporarilyInstalled) { - let addonFile = addon.getResourceURI; - XPIProvider.updateAddonDisabledState(addon, true); - Services.obs.notifyObservers(addonFile, "flush-cache-entry", null); - XPIProvider.updateAddonDisabledState(addon, false) - resolve(); - } else { - // This function supports re-installing an existing add-on. - resolve(AddonManager.installTemporaryAddon(addon._sourceBundle)); - } - }); - }, - - /** * Returns a URI to the selected resource or to the add-on bundle if aPath * is null. URIs to the bundle will always be file: URIs. URIs to resources * will be file: URIs if the add-on is unpacked or jar: URIs if the add-on is @@ -7906,216 +7170,14 @@ AddonWrapper.prototype = { * the file or directory the add-on is installed as. * @return an nsIURI */ - getResourceURI: function(aPath) { - let addon = addonFor(this); + this.getResourceURI = function AddonWrapper_getResourceURI(aPath) { if (!aPath) - return NetUtil.newURI(addon._sourceBundle); - - return getURIForResourceInFile(addon._sourceBundle, aPath); - } -}; - -/** - * The PrivateWrapper is used to expose certain functionality only when being - * called with the add-on instanceID, disallowing other add-ons to access it. - */ -function PrivateWrapper(aAddon) { - AddonWrapper.call(this, aAddon); -} - -PrivateWrapper.prototype = Object.create(AddonWrapper.prototype); -Object.assign(PrivateWrapper.prototype, { - addonId() { - return this.id; - }, + return NetUtil.newURI(aAddon._sourceBundle); - /** - * Retrieves the preferred global context to be used from the - * add-on debugging window. - * - * @returns global - * The object set as global context. Must be a window object. - */ - getDebugGlobal(global) { - let activeAddon = XPIProvider.activeAddons.get(this.id); - if (activeAddon) { - return activeAddon.debugGlobal; - } - - return null; - }, - - /** - * Defines a global context to be used in the console - * of the add-on debugging window. - * - * @param global - * The object to set as global context. Must be a window object. - */ - setDebugGlobal(global) { - if (!global) { - // If the new global is null, notify the listeners regardless - // from the current state of the addon. - // NOTE: this happen after the addon has been disabled and - // the global will never be set to null otherwise. - AddonManagerPrivate.callAddonListeners("onPropertyChanged", - addonFor(this), - ["debugGlobal"]); - } else { - let activeAddon = XPIProvider.activeAddons.get(this.id); - if (activeAddon) { - let globalChanged = activeAddon.debugGlobal != global; - activeAddon.debugGlobal = global; - - if (globalChanged) { - AddonManagerPrivate.callAddonListeners("onPropertyChanged", - addonFor(this), - ["debugGlobal"]); - } - } - } - } -}); - -function chooseValue(aAddon, aObj, aProp) { - let repositoryAddon = aAddon._repositoryAddon; - let objValue = aObj[aProp]; - - if (repositoryAddon && (aProp in repositoryAddon) && - (objValue === undefined || objValue === null)) { - return [repositoryAddon[aProp], true]; + return getURIForResourceInFile(aAddon._sourceBundle, aPath); } - - return [objValue, false]; -} - -function defineAddonWrapperProperty(name, getter) { - Object.defineProperty(AddonWrapper.prototype, name, { - get: getter, - enumerable: true, - }); } -["id", "syncGUID", "version", "isCompatible", "isPlatformCompatible", - "providesUpdatesSecurely", "blocklistState", "blocklistURL", "appDisabled", - "softDisabled", "skinnable", "size", "foreignInstall", "hasBinaryComponents", - "strictCompatibility", "compatibilityOverrides", "updateURL", "dependencies", - "getDataDirectory", "multiprocessCompatible", "signedState", "mpcOptedOut", - "isCorrectlySigned"].forEach(function(aProp) { - defineAddonWrapperProperty(aProp, function() { - let addon = addonFor(this); - return (aProp in addon) ? addon[aProp] : undefined; - }); -}); - -["fullDescription", "developerComments", "eula", "supportURL", - "contributionURL", "contributionAmount", "averageRating", "reviewCount", - "reviewURL", "totalDownloads", "weeklyDownloads", "dailyUsers", - "repositoryStatus"].forEach(function(aProp) { - defineAddonWrapperProperty(aProp, function() { - let addon = addonFor(this); - if (addon._repositoryAddon) - return addon._repositoryAddon[aProp]; - - return null; - }); -}); - -["installDate", "updateDate"].forEach(function(aProp) { - defineAddonWrapperProperty(aProp, function() { - return new Date(addonFor(this)[aProp]); - }); -}); - -["sourceURI", "releaseNotesURI"].forEach(function(aProp) { - defineAddonWrapperProperty(aProp, function() { - let addon = addonFor(this); - - // Temporary Installed Addons do not have a "sourceURI", - // But we can use the "_sourceBundle" as an alternative, - // which points to the path of the addon xpi installed - // or its source dir (if it has been installed from a - // directory). - if (aProp == "sourceURI" && this.temporarilyInstalled) { - return Services.io.newFileURI(addon._sourceBundle); - } - - let [target, fromRepo] = chooseValue(addon, addon, aProp); - if (!target) - return null; - if (fromRepo) - return target; - return NetUtil.newURI(target); - }); -}); - -PROP_LOCALE_SINGLE.forEach(function(aProp) { - defineAddonWrapperProperty(aProp, function() { - let addon = addonFor(this); - // Override XPI creator if repository creator is defined - if (aProp == "creator" && - addon._repositoryAddon && addon._repositoryAddon.creator) { - return addon._repositoryAddon.creator; - } - - let result = null; - - if (addon.active) { - try { - let pref = PREF_EM_EXTENSION_FORMAT + addon.id + "." + aProp; - let value = Preferences.get(pref, null, Ci.nsIPrefLocalizedString); - if (value) - result = value; - } - catch (e) { - } - } - - let rest; - if (result == null) - [result, ...rest] = chooseValue(addon, addon.selectedLocale, aProp); - - if (aProp == "creator") - return result ? new AddonManagerPrivate.AddonAuthor(result) : null; - - return result; - }); -}); - -PROP_LOCALE_MULTI.forEach(function(aProp) { - defineAddonWrapperProperty(aProp, function() { - let addon = addonFor(this); - let results = null; - let usedRepository = false; - - if (addon.active) { - let pref = PREF_EM_EXTENSION_FORMAT + addon.id + "." + - aProp.substring(0, aProp.length - 1); - let list = Services.prefs.getChildList(pref, {}); - if (list.length > 0) { - list.sort(); - results = []; - for (let childPref of list) { - let value = Preferences.get(childPref, null, Ci.nsIPrefLocalizedString); - if (value) - results.push(value); - } - } - } - - if (results == null) - [results, usedRepository] = chooseValue(addon, addon.selectedLocale, aProp); - - if (results && !usedRepository) { - results = results.map(function(aResult) { - return new AddonManagerPrivate.AddonAuthor(aResult); - }); - } - - return results; - }); -}); - /** * An object which identifies a directory install location for add-ons. The * location consists of a directory which contains the add-ons installed in the @@ -8126,22 +7188,33 @@ PROP_LOCALE_MULTI.forEach(function(aProp) { * containing the add-ons files. The directory or text file must have the same * name as the add-on's ID. * + * There may also a special directory named "staged" which can contain + * directories with the same name as an add-on ID. If the directory is empty + * then it means the add-on will be uninstalled from this location during the + * next startup. If the directory contains the add-on's files then they will be + * installed during the next startup. + * * @param aName * The string identifier for the install location * @param aDirectory * The nsIFile directory for the install location * @param aScope * The scope of add-ons installed in this location + * @param aLocked + * true if add-ons cannot be installed, uninstalled or upgraded in the + * install location */ -function DirectoryInstallLocation(aName, aDirectory, aScope) { +function DirectoryInstallLocation(aName, aDirectory, aScope, aLocked) { this._name = aName; - this.locked = true; + this.locked = aLocked; this._directory = aDirectory; this._scope = aScope this._IDToFileMap = {}; + this._FileToIDMap = {}; this._linkedAddons = []; + this._stagingDirLock = 0; - if (!aDirectory || !aDirectory.exists()) + if (!aDirectory.exists()) return; if (!aDirectory.isDirectory()) throw new Error("Location must be a directory."); @@ -8153,6 +7226,7 @@ DirectoryInstallLocation.prototype = { _name : "", _directory : null, _IDToFileMap : null, // mapping from add-on ID to nsIFile + _FileToIDMap : null, // mapping from add-on path to add-on ID /** * Reads a directory linked to in a file. @@ -8161,40 +7235,25 @@ DirectoryInstallLocation.prototype = { * The file containing the directory path * @return An nsIFile object representing the linked directory. */ - _readDirectoryFromFile: function(aFile) { - let linkedDirectory; - if (aFile.isSymlink()) { - linkedDirectory = aFile.clone(); + _readDirectoryFromFile: function DirInstallLocation__readDirectoryFromFile(aFile) { + let fis = Cc["@mozilla.org/network/file-input-stream;1"]. + createInstance(Ci.nsIFileInputStream); + fis.init(aFile, -1, -1, false); + let line = { value: "" }; + if (fis instanceof Ci.nsILineInputStream) + fis.readLine(line); + fis.close(); + if (line.value) { + let linkedDirectory = Cc["@mozilla.org/file/local;1"]. + createInstance(Ci.nsIFile); + try { - linkedDirectory.normalize(); - } catch (e) { - logger.warn("Symbolic link " + aFile.path + " points to a path" + - " which does not exist"); - return null; + linkedDirectory.initWithPath(line.value); } - } - else { - let fis = Cc["@mozilla.org/network/file-input-stream;1"]. - createInstance(Ci.nsIFileInputStream); - fis.init(aFile, -1, -1, false); - let line = { value: "" }; - if (fis instanceof Ci.nsILineInputStream) - fis.readLine(line); - fis.close(); - if (line.value) { - linkedDirectory = Cc["@mozilla.org/file/local;1"]. - createInstance(Ci.nsIFile); - - try { - linkedDirectory.initWithPath(line.value); - } - catch (e) { - linkedDirectory.setRelativeDescriptor(aFile.parent, line.value); - } + catch (e) { + linkedDirectory.setRelativeDescriptor(aFile.parent, line.value); } - } - if (linkedDirectory) { if (!linkedDirectory.exists()) { logger.warn("File pointer " + aFile.path + " points to " + linkedDirectory.path + " which does not exist"); @@ -8217,7 +7276,7 @@ DirectoryInstallLocation.prototype = { /** * Finds all the add-ons installed in this location. */ - _readAddons: function() { + _readAddons: function DirInstallLocation__readAddons() { // Use a snapshot of the directory contents to avoid possible issues with // iterating over a directory while removing files from it (the YAFFS2 // embedded filesystem has this issue, see bug 772238). @@ -8225,7 +7284,7 @@ DirectoryInstallLocation.prototype = { for (let entry of entries) { let id = entry.leafName; - if (id == DIR_STAGE || id == DIR_TRASH) + if (id == DIR_STAGE || id == DIR_XPI_STAGE || id == DIR_TRASH) continue; let directLoad = false; @@ -8241,7 +7300,7 @@ DirectoryInstallLocation.prototype = { continue; } - if (!directLoad && (entry.isFile() || entry.isSymlink())) { + if (entry.isFile() && !directLoad) { let newEntry = this._readDirectoryFromFile(entry); if (!newEntry) { logger.debug("Deleting stale pointer file " + entry.path); @@ -8260,6 +7319,7 @@ DirectoryInstallLocation.prototype = { } this._IDToFileMap[id] = entry; + this._FileToIDMap[entry.path] = id; XPIProvider._addURIMapping(id, entry); } }, @@ -8281,66 +7341,21 @@ DirectoryInstallLocation.prototype = { /** * Gets an array of nsIFiles for add-ons installed in this location. */ - getAddonLocations: function() { - let locations = new Map(); + get addonLocations() { + let locations = []; for (let id in this._IDToFileMap) { - locations.set(id, this._IDToFileMap[id].clone()); + locations.push(this._IDToFileMap[id].clone()); } return locations; }, /** - * Gets the directory that the add-on with the given ID is installed in. - * - * @param aId - * The ID of the add-on - * @return The nsIFile - * @throws if the ID does not match any of the add-ons installed - */ - getLocationForID: function(aId) { - if (aId in this._IDToFileMap) - return this._IDToFileMap[aId].clone(); - throw new Error("Unknown add-on ID " + aId); - }, - - /** - * Returns true if the given addon was installed in this location by a text - * file pointing to its real path. - * - * @param aId - * The ID of the addon - */ - isLinkedAddon: function(aId) { - return this._linkedAddons.indexOf(aId) != -1; - } -}; - -/** - * An extension of DirectoryInstallLocation which adds methods to installing - * and removing add-ons from the directory at runtime. - * - * @param aName - * The string identifier for the install location - * @param aDirectory - * The nsIFile directory for the install location - * @param aScope - * The scope of add-ons installed in this location - */ -function MutableDirectoryInstallLocation(aName, aDirectory, aScope) { - DirectoryInstallLocation.call(this, aName, aDirectory, aScope); - this.locked = false; - this._stagingDirLock = 0; -} - -MutableDirectoryInstallLocation.prototype = Object.create(DirectoryInstallLocation.prototype); -Object.assign(MutableDirectoryInstallLocation.prototype, { - /** * Gets the staging directory to put add-ons that are pending install and * uninstall into. * * @return an nsIFile */ - getStagingDir: function() { + getStagingDir: function DirInstallLocation_getStagingDir() { let dir = this._directory.clone(); dir.append(DIR_STAGE); return dir; @@ -8413,6 +7428,18 @@ Object.assign(MutableDirectoryInstallLocation.prototype, { }, /** + * Gets the directory used by old versions for staging XPI and JAR files ready + * to be installed. + * + * @return an nsIFile + */ + getXPIStagingDir: function DirInstallLocation_getXPIStagingDir() { + let dir = this._directory.clone(); + dir.append(DIR_XPI_STAGE); + return dir; + }, + + /** * Returns a directory that is normally on the same filesystem as the rest of * the install location and can be used for temporarily storing files during * safe move operations. Calling this method will delete the existing trash @@ -8420,7 +7447,7 @@ Object.assign(MutableDirectoryInstallLocation.prototype, { * * @return an nsIFile */ - getTrashDir: function() { + getTrashDir: function DirInstallLocation_getTrashDir() { let trashDir = this._directory.clone(); trashDir.append(DIR_TRASH); let trashDirExists = trashDir.exists(); @@ -8433,43 +7460,39 @@ Object.assign(MutableDirectoryInstallLocation.prototype, { } if (!trashDirExists) trashDir.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY); - return trashDir; }, /** * Installs an add-on into the install location. * - * @param id + * @param aId * The ID of the add-on to install - * @param source + * @param aSource * The source nsIFile to install from - * @param existingAddonID + * @param aExistingAddonID * The ID of an existing add-on to uninstall at the same time - * @param action - * What to we do with the given source file: - * "move" - * Default action, the source files will be moved to the new - * location, - * "copy" - * The source files will be copied, - * "proxy" - * A "proxy file" is going to refer to the source file path + * @param aCopy + * If false the source files will be moved to the new location, + * otherwise they will only be copied * @return an nsIFile indicating where the add-on was installed to */ - installAddon: function({ id, source, existingAddonID, action = "move" }) { + installAddon: function DirInstallLocation_installAddon(aId, aSource, + aExistingAddonID, + aCopy) { let trashDir = this.getTrashDir(); let transaction = new SafeInstallOperation(); - let moveOldAddon = aId => { - let file = this._directory.clone(); + let self = this; + function moveOldAddon(aId) { + let file = self._directory.clone(); file.append(aId); if (file.exists()) transaction.moveUnder(file, trashDir); - file = this._directory.clone(); + file = self._directory.clone(); file.append(aId + ".xpi"); if (file.exists()) { flushJarCache(file); @@ -8480,9 +7503,9 @@ Object.assign(MutableDirectoryInstallLocation.prototype, { // If any of these operations fails the finally block will clean up the // temporary directory try { - moveOldAddon(id); - if (existingAddonID && existingAddonID != id) { - moveOldAddon(existingAddonID); + moveOldAddon(aId); + if (aExistingAddonID && aExistingAddonID != aId) { + moveOldAddon(aExistingAddonID); { // Move the data directories. @@ -8491,12 +7514,12 @@ Object.assign(MutableDirectoryInstallLocation.prototype, { * for porting to OS.File. */ let oldDataDir = FileUtils.getDir( - KEY_PROFILEDIR, ["extension-data", existingAddonID], false, true + KEY_PROFILEDIR, ["extension-data", aExistingAddonID], false, true ); if (oldDataDir.exists()) { let newDataDir = FileUtils.getDir( - KEY_PROFILEDIR, ["extension-data", id], false, true + KEY_PROFILEDIR, ["extension-data", aId], false, true ); if (newDataDir.exists()) { let trashData = trashDir.clone(); @@ -8509,16 +7532,15 @@ Object.assign(MutableDirectoryInstallLocation.prototype, { } } - if (action == "copy") { - transaction.copy(source, this._directory); + if (aCopy) { + transaction.copy(aSource, this._directory); } - else if (action == "move") { - if (source.isFile()) - flushJarCache(source); + else { + if (aSource.isFile()) + flushJarCache(aSource); - transaction.moveUnder(source, this._directory); + transaction.moveUnder(aSource, this._directory); } - // Do nothing for the proxy file as we sideload an addon permanently } finally { // It isn't ideal if this cleanup fails but it isn't worth rolling back @@ -8527,33 +7549,25 @@ Object.assign(MutableDirectoryInstallLocation.prototype, { recursiveRemove(trashDir); } catch (e) { - logger.warn("Failed to remove trash directory when installing " + id, e); + logger.warn("Failed to remove trash directory when installing " + aId, e); } } let newFile = this._directory.clone(); - - if (action == "proxy") { - // When permanently installing sideloaded addon, we just put a proxy file - // refering to the addon sources - newFile.append(id); - - writeStringToFile(newFile, source.path); - } else { - newFile.append(source.leafName); - } - + newFile.append(aSource.leafName); try { newFile.lastModifiedTime = Date.now(); } catch (e) { logger.warn("failed to set lastModifiedTime on " + newFile.path, e); } - this._IDToFileMap[id] = newFile; - XPIProvider._addURIMapping(id, newFile); + this._FileToIDMap[newFile.path] = aId; + this._IDToFileMap[aId] = newFile; + XPIProvider._addURIMapping(aId, newFile); - if (existingAddonID && existingAddonID != id && - existingAddonID in this._IDToFileMap) { - delete this._IDToFileMap[existingAddonID]; + if (aExistingAddonID && aExistingAddonID != aId && + aExistingAddonID in this._IDToFileMap) { + delete this._FileToIDMap[this._IDToFileMap[aExistingAddonID]]; + delete this._IDToFileMap[aExistingAddonID]; } return newFile; @@ -8566,7 +7580,7 @@ Object.assign(MutableDirectoryInstallLocation.prototype, { * The ID of the add-on to uninstall * @throws if the ID does not match any of the add-ons installed */ - uninstallAddon: function(aId) { + uninstallAddon: function DirInstallLocation_uninstallAddon(aId) { let file = this._IDToFileMap[aId]; if (!file) { logger.warn("Attempted to remove " + aId + " from " + @@ -8583,6 +7597,7 @@ Object.assign(MutableDirectoryInstallLocation.prototype, { logger.warn("Attempted to remove " + aId + " from " + this._name + " but it was already gone"); + delete this._FileToIDMap[file.path]; delete this._IDToFileMap[aId]; return; } @@ -8610,550 +7625,51 @@ Object.assign(MutableDirectoryInstallLocation.prototype, { } } + delete this._FileToIDMap[file.path]; delete this._IDToFileMap[aId]; }, -}); - -/** - * An object which identifies a directory install location for system add-ons - * upgrades. - * - * The location consists of a directory which contains the add-ons installed. - * - * @param aName - * The string identifier for the install location - * @param aDirectory - * The nsIFile directory for the install location - * @param aScope - * The scope of add-ons installed in this location - * @param aResetSet - * True to throw away the current add-on set - */ -function SystemAddonInstallLocation(aName, aDirectory, aScope, aResetSet) { - this._baseDir = aDirectory; - this._nextDir = null; - - this._stagingDirLock = 0; - - if (aResetSet) - this.resetAddonSet(); - - this._addonSet = this._loadAddonSet(); - - this._directory = null; - if (this._addonSet.directory) { - this._directory = aDirectory.clone(); - this._directory.append(this._addonSet.directory); - logger.info("SystemAddonInstallLocation scanning directory " + this._directory.path); - } - else { - logger.info("SystemAddonInstallLocation directory is missing"); - } - - DirectoryInstallLocation.call(this, aName, this._directory, aScope); - this.locked = false; -} - -SystemAddonInstallLocation.prototype = Object.create(DirectoryInstallLocation.prototype); -Object.assign(SystemAddonInstallLocation.prototype, { - /** - * Removes the specified files or directories in the staging directory and - * then if the staging directory is empty attempts to remove it. - * - * @param aLeafNames - * An array of file or directory to remove from the directory, the - * array may be empty - */ - cleanStagingDir: function(aLeafNames = []) { - let dir = this.getStagingDir(); - - for (let name of aLeafNames) { - let file = dir.clone(); - file.append(name); - recursiveRemove(file); - } - - if (this._stagingDirLock > 0) - return; - - let dirEntries = dir.directoryEntries.QueryInterface(Ci.nsIDirectoryEnumerator); - try { - if (dirEntries.nextFile) - return; - } - finally { - dirEntries.close(); - } - - try { - setFilePermissions(dir, FileUtils.PERMS_DIRECTORY); - dir.remove(false); - } - catch (e) { - logger.warn("Failed to remove staging dir", e); - // Failing to remove the staging directory is ignorable - } - }, /** - * Gets the staging directory to put add-ons that are pending install and - * uninstall into. + * Gets the ID of the add-on installed in the given nsIFile. * - * @return {nsIFile} - staging directory for system add-on upgrades. - */ - getStagingDir: function() { - this._addonSet = this._loadAddonSet(); - let dir = null; - if (this._addonSet.directory) { - this._directory = this._baseDir.clone(); - this._directory.append(this._addonSet.directory); - dir = this._directory.clone(); - dir.append(DIR_STAGE); - } - else { - logger.info("SystemAddonInstallLocation directory is missing"); - } - - return dir; - }, - - requestStagingDir: function() { - this._stagingDirLock++; - if (this._stagingDirPromise) - return this._stagingDirPromise; - - this._addonSet = this._loadAddonSet(); - if (this._addonSet.directory) { - this._directory = this._baseDir.clone(); - this._directory.append(this._addonSet.directory); - } - - OS.File.makeDir(this._directory.path); - let stagepath = OS.Path.join(this._directory.path, DIR_STAGE); - return this._stagingDirPromise = OS.File.makeDir(stagepath).then(null, (e) => { - if (e instanceof OS.File.Error && e.becauseExists) - return; - logger.error("Failed to create staging directory", e); - throw e; - }); - }, - - releaseStagingDir: function() { - this._stagingDirLock--; - - if (this._stagingDirLock == 0) { - this._stagingDirPromise = null; - this.cleanStagingDir(); - } - - return Promise.resolve(); - }, - - /** - * Reads the current set of system add-ons - */ - _loadAddonSet: function() { - try { - let setStr = Preferences.get(PREF_SYSTEM_ADDON_SET, null); - if (setStr) { - let addonSet = JSON.parse(setStr); - if ((typeof addonSet == "object") && addonSet.schema == 1) - return addonSet; - } - } - catch (e) { - logger.error("Malformed system add-on set, resetting."); - } - - return { schema: 1, addons: {} }; - }, - - /** - * Saves the current set of system add-ons - * - * @param {Object} aAddonSet - object containing schema, directory and set - * of system add-on IDs and versions. - */ - _saveAddonSet: function(aAddonSet) { - Preferences.set(PREF_SYSTEM_ADDON_SET, JSON.stringify(aAddonSet)); - }, - - getAddonLocations: function() { - // Updated system add-ons are ignored in safe mode - if (Services.appinfo.inSafeMode) - return new Map(); - - let addons = DirectoryInstallLocation.prototype.getAddonLocations.call(this); - - // Strip out any unexpected add-ons from the list - for (let id of addons.keys()) { - if (!(id in this._addonSet.addons)) - addons.delete(id); - } - - return addons; - }, - - /** - * Tests whether updated system add-ons are expected. - */ - isActive: function() { - return this._directory != null; - }, - - isValidAddon: function(aAddon) { - if (aAddon.appDisabled) { - logger.warn(`System add-on ${aAddon.id} isn't compatible with the application.`); - return false; - } - - if (aAddon.unpack) { - logger.warn(`System add-on ${aAddon.id} isn't a packed add-on.`); - return false; - } - - if (!aAddon.bootstrap) { - logger.warn(`System add-on ${aAddon.id} isn't restartless.`); - return false; - } - - if (!aAddon.multiprocessCompatible) { - logger.warn(`System add-on ${aAddon.id} isn't multiprocess compatible.`); - return false; - } - - return true; - }, - - /** - * Tests whether the loaded add-on information matches what is expected. - */ - isValid: function(aAddons) { - for (let id of Object.keys(this._addonSet.addons)) { - if (!aAddons.has(id)) { - logger.warn(`Expected add-on ${id} is missing from the system add-on location.`); - return false; - } - - let addon = aAddons.get(id); - if (addon.version != this._addonSet.addons[id].version) { - logger.warn(`Expected system add-on ${id} to be version ${this._addonSet.addons[id].version} but was ${addon.version}.`); - return false; - } - - if (!this.isValidAddon(addon)) - return false; - } - - return true; - }, - - /** - * Resets the add-on set so on the next startup the default set will be used. + * @param aFile + * The nsIFile to look in + * @return the ID + * @throws if the file does not represent an installed add-on */ - resetAddonSet: function() { - - if (this._addonSet) { - logger.info("Removing all system add-on upgrades."); - - // remove everything from the pref first, if uninstall - // fails then at least they will not be re-activated on - // next restart. - this._saveAddonSet({ schema: 1, addons: {} }); - - for (let id of Object.keys(this._addonSet.addons)) { - AddonManager.getAddonByID(id, addon => { - if (addon) { - addon.uninstall(); - } - }); - } - } + getIDForLocation: function DirInstallLocation_getIDForLocation(aFile) { + if (aFile.path in this._FileToIDMap) + return this._FileToIDMap[aFile.path]; + throw new Error("Unknown add-on location " + aFile.path); }, /** - * Removes any directories not currently in use or pending use after a - * restart. Any errors that happen here don't really matter as we'll attempt - * to cleanup again next time. - */ - cleanDirectories: Task.async(function*() { - - // System add-ons directory does not exist - if (!(yield OS.File.exists(this._baseDir.path))) { - return; - } - - let iterator; - try { - iterator = new OS.File.DirectoryIterator(this._baseDir.path); - } - catch (e) { - logger.error("Failed to clean updated system add-ons directories.", e); - return; - } - - try { - let entries = []; - - yield iterator.forEach(entry => { - // Skip the directory currently in use - if (this._directory && this._directory.path == entry.path) - return; - - // Skip the next directory - if (this._nextDir && this._nextDir.path == entry.path) - return; - - entries.push(entry); - }); - - for (let entry of entries) { - if (entry.isDir) { - yield OS.File.removeDir(entry.path, { - ignoreAbsent: true, - ignorePermissions: true, - }); - } - else { - yield OS.File.remove(entry.path, { - ignoreAbsent: true, - }); - } - } - } - catch (e) { - logger.error("Failed to clean updated system add-ons directories.", e); - } - finally { - iterator.close(); - } - }), - - /** - * Installs a new set of system add-ons into the location and updates the - * add-on set in prefs. - * - * @param {Array} aAddons - An array of addons to install. - */ - installAddonSet: Task.async(function*(aAddons) { - // Make sure the base dir exists - yield OS.File.makeDir(this._baseDir.path, { ignoreExisting: true }); - - let addonSet = this._loadAddonSet(); - - // Remove any add-ons that are no longer part of the set. - for (let addonID of Object.keys(addonSet.addons)) { - if (!aAddons.includes(addonID)) { - AddonManager.getAddonByID(addonID, a => a.uninstall()); - } - } - - let newDir = this._baseDir.clone(); - - let uuidGen = Cc["@mozilla.org/uuid-generator;1"]. - getService(Ci.nsIUUIDGenerator); - newDir.append("blank"); - - while (true) { - newDir.leafName = uuidGen.generateUUID().toString(); - - try { - yield OS.File.makeDir(newDir.path, { ignoreExisting: false }); - break; - } - catch (e) { - logger.debug("Could not create new system add-on updates dir, retrying", e); - } - } - - // Record the new upgrade directory. - let state = { schema: 1, directory: newDir.leafName, addons: {} }; - this._saveAddonSet(state); - - this._nextDir = newDir; - let location = this; - - let installs = []; - for (let addon of aAddons) { - let install = yield createLocalInstall(addon._sourceBundle, location); - installs.push(install); - } - - let installAddon = Task.async(function*(install) { - // Make the new install own its temporary file. - install.ownsTempFile = true; - install.install(); - }); - - let postponeAddon = Task.async(function*(install) { - let resumeFn; - if (AddonManagerPrivate.hasUpgradeListener(install.addon.id)) { - logger.info(`system add-on ${install.addon.id} has an upgrade listener, postponing upgrade set until restart`); - resumeFn = () => { - logger.info(`${install.addon.id} has resumed a previously postponed addon set`); - install.installLocation.resumeAddonSet(installs); - } - } - yield install.postpone(resumeFn); - }); - - let previousState; - - try { - // All add-ons in position, create the new state and store it in prefs - state = { schema: 1, directory: newDir.leafName, addons: {} }; - for (let addon of aAddons) { - state.addons[addon.id] = { - version: addon.version - } - } - - previousState = this._loadAddonSet(); - this._saveAddonSet(state); - - let blockers = aAddons.filter( - addon => AddonManagerPrivate.hasUpgradeListener(addon.id) - ); - - if (blockers.length > 0) { - yield waitForAllPromises(installs.map(postponeAddon)); - } else { - yield waitForAllPromises(installs.map(installAddon)); - } - } - catch (e) { - // Roll back to previous upgrade set (if present) on restart. - if (previousState) { - this._saveAddonSet(previousState); - } - // Otherwise, roll back to built-in set on restart. - // TODO try to do these restartlessly - this.resetAddonSet(); - - try { - yield OS.File.removeDir(newDir.path, { ignorePermissions: true }); - } - catch (e) { - logger.warn(`Failed to remove failed system add-on directory ${newDir.path}.`, e); - } - throw e; - } - }), - - /** - * Resumes upgrade of a previously-delayed add-on set. - */ - resumeAddonSet: Task.async(function*(installs) { - let resumeAddon = Task.async(function*(install) { - install.state = AddonManager.STATE_DOWNLOADED; - install.installLocation.releaseStagingDir(); - install.install(); - }); - - let addonSet = this._loadAddonSet(); - let addonIDs = Object.keys(addonSet.addons); - - let blockers = installs.filter( - install => AddonManagerPrivate.hasUpgradeListener(install.addon.id) - ); - - if (blockers.length > 1) { - logger.warn("Attempted to resume system add-on install but upgrade blockers are still present"); - } else { - yield waitForAllPromises(installs.map(resumeAddon)); - } - }), - - /** - * Returns a directory that is normally on the same filesystem as the rest of - * the install location and can be used for temporarily storing files during - * safe move operations. Calling this method will delete the existing trash - * directory and its contents. + * Gets the directory that the add-on with the given ID is installed in. * - * @return an nsIFile + * @param aId + * The ID of the add-on + * @return The nsIFile + * @throws if the ID does not match any of the add-ons installed */ - getTrashDir: function() { - let trashDir = this._directory.clone(); - trashDir.append(DIR_TRASH); - let trashDirExists = trashDir.exists(); - try { - if (trashDirExists) - recursiveRemove(trashDir); - trashDirExists = false; - } catch (e) { - logger.warn("Failed to remove trash directory", e); - } - if (!trashDirExists) - trashDir.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY); - - return trashDir; + getLocationForID: function DirInstallLocation_getLocationForID(aId) { + if (aId in this._IDToFileMap) + return this._IDToFileMap[aId].clone(); + throw new Error("Unknown add-on ID " + aId); }, /** - * Installs an add-on into the install location. + * Returns true if the given addon was installed in this location by a text + * file pointing to its real path. * - * @param id - * The ID of the add-on to install - * @param source - * The source nsIFile to install from - * @return an nsIFile indicating where the add-on was installed to + * @param aId + * The ID of the addon */ - installAddon: function({id, source}) { - let trashDir = this.getTrashDir(); - let transaction = new SafeInstallOperation(); - - // If any of these operations fails the finally block will clean up the - // temporary directory - try { - if (source.isFile()) { - flushJarCache(source); - } - - transaction.moveUnder(source, this._directory); - } - finally { - // It isn't ideal if this cleanup fails but it isn't worth rolling back - // the install because of it. - try { - recursiveRemove(trashDir); - } - catch (e) { - logger.warn("Failed to remove trash directory when installing " + id, e); - } - } - - let newFile = this._directory.clone(); - newFile.append(source.leafName); - - try { - newFile.lastModifiedTime = Date.now(); - } catch (e) { - logger.warn("failed to set lastModifiedTime on " + newFile.path, e); - } - this._IDToFileMap[id] = newFile; - XPIProvider._addURIMapping(id, newFile); - - return newFile; - }, - - // old system add-on upgrade dirs get automatically removed - uninstallAddon: (aAddon) => {}, -}); - -/** - * An object which identifies an install location for temporary add-ons. - */ -const TemporaryInstallLocation = { - locked: false, - name: KEY_APP_TEMPORARY, - scope: AddonManager.SCOPE_TEMPORARY, - getAddonLocations: () => [], - isLinkedAddon: () => false, - installAddon: () => {}, - uninstallAddon: (aAddon) => {}, - getStagingDir: () => {}, -} + isLinkedAddon: function DirInstallLocation__isLinkedAddon(aId) { + return this._linkedAddons.indexOf(aId) != -1; + } +}; +#ifdef XP_WIN /** * An object that identifies a registry install location for add-ons. The location * consists of a registry key which contains string values mapping ID to the @@ -9172,6 +7688,7 @@ function WinRegInstallLocation(aName, aRootKey, aScope) { this._rootKey = aRootKey; this._scope = aScope; this._IDToFileMap = {}; + this._FileToIDMap = {}; let path = this._appKeyPath + "\\Extensions"; let key = Cc["@mozilla.org/windows-registry-key;1"]. @@ -9195,6 +7712,7 @@ WinRegInstallLocation.prototype = { _rootKey : null, _scope : null, _IDToFileMap : null, // mapping from ID to nsIFile + _FileToIDMap : null, // mapping from path to ID /** * Retrieves the path of this Application's data key in the registry. @@ -9203,9 +7721,11 @@ WinRegInstallLocation.prototype = { let appVendor = Services.appinfo.vendor; let appName = Services.appinfo.name; +#ifdef MOZ_THUNDERBIRD // XXX Thunderbird doesn't specify a vendor string - if (AppConstants.MOZ_APP_NAME == "thunderbird" && appVendor == "") + if (appVendor == "") appVendor = "Mozilla"; +#endif // XULRunner-based apps may intentionally not specify a vendor if (appVendor != "") @@ -9221,12 +7741,14 @@ WinRegInstallLocation.prototype = { * @param key * The key that contains the ID to path mapping */ - _readAddons: function(aKey) { + _readAddons: function RegInstallLocation__readAddons(aKey) { let count = aKey.valueCount; for (let i = 0; i < count; ++i) { let id = aKey.getValueName(i); - let file = new nsIFile(aKey.readStringValue(id)); + let file = Cc["@mozilla.org/file/local;1"]. + createInstance(Ci.nsIFile); + file.initWithPath(aKey.readStringValue(id)); if (!file.exists()) { logger.warn("Ignoring missing add-on in " + file.path); @@ -9234,6 +7756,7 @@ WinRegInstallLocation.prototype = { } this._IDToFileMap[id] = file; + this._FileToIDMap[file.path] = id; XPIProvider._addURIMapping(id, file); } }, @@ -9255,21 +7778,49 @@ WinRegInstallLocation.prototype = { /** * Gets an array of nsIFiles for add-ons installed in this location. */ - getAddonLocations: function() { - let locations = new Map(); + get addonLocations() { + let locations = []; for (let id in this._IDToFileMap) { - locations.set(id, this._IDToFileMap[id].clone()); + locations.push(this._IDToFileMap[id].clone()); } return locations; }, /** + * Gets the ID of the add-on installed in the given nsIFile. + * + * @param aFile + * The nsIFile to look in + * @return the ID + * @throws if the file does not represent an installed add-on + */ + getIDForLocation: function RegInstallLocation_getIDForLocation(aFile) { + if (aFile.path in this._FileToIDMap) + return this._FileToIDMap[aFile.path]; + throw new Error("Unknown add-on location"); + }, + + /** + * Gets the nsIFile that the add-on with the given ID is installed in. + * + * @param aId + * The ID of the add-on + * @return the nsIFile + */ + getLocationForID: function RegInstallLocation_getLocationForID(aId) { + if (aId in this._IDToFileMap) + return this._IDToFileMap[aId].clone(); + throw new Error("Unknown add-on ID"); + }, + + /** * @see DirectoryInstallLocation */ - isLinkedAddon: function(aId) { + isLinkedAddon: function RegInstallLocation_isLinkedAddon(aId) { return true; } }; +#endif var addonTypes = [ new AddonManagerPrivate.AddonType("extension", URI_EXTENSION_STRINGS, diff --git a/toolkit/mozapps/extensions/internal/XPIProviderUtils.js b/toolkit/mozapps/extensions/internal/XPIProviderUtils.js index d04eb207c..d26029455 100644 --- a/toolkit/mozapps/extensions/internal/XPIProviderUtils.js +++ b/toolkit/mozapps/extensions/internal/XPIProviderUtils.js @@ -4,22 +4,14 @@ "use strict"; -// These are injected from XPIProvider.jsm -/* globals ADDON_SIGNING, SIGNED_TYPES, BOOTSTRAP_REASONS, DB_SCHEMA, - AddonInternal, XPIProvider, XPIStates, syncLoadManifestFromFile, - isUsableAddon, recordAddonTelemetry, applyBlocklistChanges, - flushChromeCaches, canRunInSafeMode*/ - -var Cc = Components.classes; -var Ci = Components.interfaces; -var Cr = Components.results; -var Cu = Components.utils; +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cr = Components.results; +const Cu = Components.utils; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/AddonManager.jsm"); -/* globals AddonManagerPrivate*/ -Cu.import("resource://gre/modules/Preferences.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "AddonRepository", "resource://gre/modules/addons/AddonRepository.jsm"); @@ -31,15 +23,10 @@ XPCOMUtils.defineLazyModuleGetter(this, "Promise", "resource://gre/modules/Promise.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "OS", "resource://gre/modules/osfile.jsm"); -XPCOMUtils.defineLazyServiceGetter(this, "Blocklist", - "@mozilla.org/extensions/blocklist;1", - Ci.nsIBlocklistService); Cu.import("resource://gre/modules/Log.jsm"); const LOGGER_ID = "addons.xpi-utils"; -const nsIFile = Components.Constructor("@mozilla.org/file/local;1", "nsIFile"); - // Create a new logger for use by the Addons XPI Provider Utils // (Requires AddonManager.jsm) var logger = Log.repository.getLogger(LOGGER_ID); @@ -50,20 +37,15 @@ const FILE_JSON_DB = "extensions.json"; const FILE_OLD_DATABASE = "extensions.rdf"; const FILE_XPI_ADDONS_LIST = "extensions.ini"; +// The value for this is in Makefile.in +#expand const DB_SCHEMA = __MOZ_EXTENSIONS_DB_SCHEMA__; + // The last version of DB_SCHEMA implemented in SQLITE const LAST_SQLITE_DB_SCHEMA = 14; const PREF_DB_SCHEMA = "extensions.databaseSchema"; const PREF_PENDING_OPERATIONS = "extensions.pendingOperations"; const PREF_EM_ENABLED_ADDONS = "extensions.enabledAddons"; const PREF_EM_DSS_ENABLED = "extensions.dss.enabled"; -const PREF_EM_AUTO_DISABLED_SCOPES = "extensions.autoDisableScopes"; -const PREF_E10S_BLOCKED_BY_ADDONS = "extensions.e10sBlockedByAddons"; -const PREF_E10S_HAS_NONEXEMPT_ADDON = "extensions.e10s.rollout.hasAddon"; - -const KEY_APP_PROFILE = "app-profile"; -const KEY_APP_SYSTEM_ADDONS = "app-system-addons"; -const KEY_APP_SYSTEM_DEFAULTS = "app-system-defaults"; -const KEY_APP_GLOBAL = "app-global"; // Properties that only exist in the database const DB_METADATA = ["syncGUID", @@ -81,22 +63,14 @@ const DB_BOOL_METADATA = ["visible", "active", "userDisabled", "appDisabled", // Properties to save in JSON file const PROP_JSON_FIELDS = ["id", "syncGUID", "location", "version", "type", "internalName", "updateURL", "updateKey", "optionsURL", - "optionsType", "aboutURL", "icons", "iconURL", "icon64URL", + "optionsType", "aboutURL", "iconURL", "icon64URL", "defaultLocale", "visible", "active", "userDisabled", "appDisabled", "pendingUninstall", "descriptor", "installDate", "updateDate", "applyBackgroundUpdates", "bootstrap", "skinnable", "size", "sourceURI", "releaseNotesURI", "softDisabled", "foreignInstall", "hasBinaryComponents", "strictCompatibility", "locales", "targetApplications", - "targetPlatforms", "multiprocessCompatible", "signedState", - "seen", "dependencies", "hasEmbeddedWebExtension", "mpcOptedOut"]; - -// Properties that should be migrated where possible from an old database. These -// shouldn't include properties that can be read directly from install.rdf files -// or calculated -const DB_MIGRATE_METADATA= ["installDate", "userDisabled", "softDisabled", - "sourceURI", "applyBackgroundUpdates", - "releaseNotesURI", "foreignInstall", "syncGUID"]; + "targetPlatforms", "multiprocessCompatible", "native"]; // Time to wait before async save of XPI JSON database, in milliseconds const ASYNC_SAVE_DELAY_MS = 20; @@ -170,7 +144,7 @@ function makeSafe(aCallback) { try { aCallback(...aArgs); } - catch (ex) { + catch(ex) { logger.warn("XPI Database callback failed", ex); } } @@ -187,7 +161,7 @@ function makeSafe(aCallback) { * @param aObjects * The array of objects to process asynchronously * @param aMethod - * Function with signature function(object, function(f_of_object)) + * Function with signature function(object, function aCallback(f_of_object)) * @param aCallback * Function with signature f([aMethod(object)]), called when all values * are available @@ -207,9 +181,9 @@ function asyncMap(aObjects, aMethod, aCallback) { } } - aObjects.map(function(aObject, aIndex, aArray) { + aObjects.map(function asyncMap_each(aObject, aIndex, aArray) { try { - aMethod(aObject, function(aResult) { + aMethod(aObject, function asyncMap_callback(aResult) { asyncMap_gotValue(aIndex, aResult); }); } @@ -226,7 +200,7 @@ function asyncMap(aObjects, aMethod, aCallback) { * @param aStatement * The statement to execute */ -function* resultRows(aStatement) { +function resultRows(aStatement) { try { while (stepStatement(aStatement)) yield aStatement.row; @@ -292,8 +266,7 @@ function copyProperties(aObject, aProperties, aTarget) { if (!aTarget) aTarget = {}; aProperties.forEach(function(aProp) { - if (aProp in aObject) - aTarget[aProp] = aObject[aProp]; + aTarget[aProp] = aObject[aProp]; }); return aTarget; } @@ -329,17 +302,11 @@ function copyRowProperties(aRow, aProperties, aTarget) { * Addon data fields loaded from JSON or the addon manifest. */ function DBAddonInternal(aLoaded) { - AddonInternal.call(this); - copyProperties(aLoaded, PROP_JSON_FIELDS, this); - if (!this.dependencies) - this.dependencies = []; - Object.freeze(this.dependencies); - if (aLoaded._installLocation) { this._installLocation = aLoaded._installLocation; - this.location = aLoaded._installLocation.name; + this.location = aLoaded._installLocation._name; } else if (aLoaded.location) { this._installLocation = XPIProvider.installLocationsByName[this.location]; @@ -347,13 +314,17 @@ function DBAddonInternal(aLoaded) { this._key = this.location + ":" + this.id; - if (!aLoaded._sourceBundle) { - throw new Error("Expected passed argument to contain a descriptor"); + try { + this._sourceBundle = this._installLocation.getLocationForID(this.id); + } + catch (e) { + // An exception will be thrown if the add-on appears in the database but + // not on disk. In general this should only happen during startup as + // this change is being detected. } - this._sourceBundle = aLoaded._sourceBundle; - - XPCOMUtils.defineLazyGetter(this, "pendingUpgrade", function() { + XPCOMUtils.defineLazyGetter(this, "pendingUpgrade", + function DBA_pendingUpgradeGetter() { for (let install of XPIProvider.installs) { if (install.state == AddonManager.STATE_INSTALLED && !(install.addon.inDatabase) && @@ -362,53 +333,46 @@ function DBAddonInternal(aLoaded) { delete this.pendingUpgrade; return this.pendingUpgrade = install.addon; } - } + }; return null; }); } -DBAddonInternal.prototype = Object.create(AddonInternal.prototype); -Object.assign(DBAddonInternal.prototype, { - applyCompatibilityUpdate: function(aUpdate, aSyncCompatibility) { - let wasCompatible = this.isCompatible; - - this.targetApplications.forEach(function(aTargetApp) { - aUpdate.targetApplications.forEach(function(aUpdateTarget) { - if (aTargetApp.id == aUpdateTarget.id && (aSyncCompatibility || - Services.vc.compare(aTargetApp.maxVersion, aUpdateTarget.maxVersion) < 0)) { - aTargetApp.minVersion = aUpdateTarget.minVersion; - aTargetApp.maxVersion = aUpdateTarget.maxVersion; - XPIDatabase.saveChanges(); - } +function DBAddonInternalPrototype() +{ + this.applyCompatibilityUpdate = + function(aUpdate, aSyncCompatibility) { + this.targetApplications.forEach(function(aTargetApp) { + aUpdate.targetApplications.forEach(function(aUpdateTarget) { + if (aTargetApp.id == aUpdateTarget.id && (aSyncCompatibility || + Services.vc.compare(aTargetApp.maxVersion, aUpdateTarget.maxVersion) < 0)) { + aTargetApp.minVersion = aUpdateTarget.minVersion; + aTargetApp.maxVersion = aUpdateTarget.maxVersion; + XPIDatabase.saveChanges(); + } + }); }); - }); - if (aUpdate.multiprocessCompatible !== undefined && - aUpdate.multiprocessCompatible != this.multiprocessCompatible) { - this.multiprocessCompatible = aUpdate.multiprocessCompatible; - XPIDatabase.saveChanges(); - } - - if (wasCompatible != this.isCompatible) + if (aUpdate.multiprocessCompatible !== undefined && + aUpdate.multiprocessCompatible != this.multiprocessCompatible) { + this.multiprocessCompatible = aUpdate.multiprocessCompatible; + XPIDatabase.saveChanges(); + } XPIProvider.updateAddonDisabledState(this); - }, - - toJSON: function() { - let jsonData = copyProperties(this, PROP_JSON_FIELDS); + }; - // Experiments are serialized as disabled so they aren't run on the next - // startup. - if (this.type == "experiment") { - jsonData.userDisabled = true; - jsonData.active = false; - } + this.toJSON = + function() { + return copyProperties(this, PROP_JSON_FIELDS); + }; - return jsonData; - }, + Object.defineProperty(this, "inDatabase", + { get: function() { return true; }, + enumerable: true, + configurable: true }); +} +DBAddonInternalPrototype.prototype = AddonInternal.prototype; - get inDatabase() { - return true; - } -}); +DBAddonInternal.prototype = new DBAddonInternalPrototype(); /** * Internal interface: find an addon from an already loaded addonDB @@ -426,7 +390,7 @@ function _findAddon(addonDB, aFilter) { * Internal interface to get a filtered list of addons from a loaded addonDB */ function _filterDB(addonDB, aFilter) { - return Array.from(addonDB.values()).filter(aFilter); + return [for (addon of addonDB.values()) if (aFilter(addon)) addon]; } this.XPIDatabase = { @@ -472,11 +436,10 @@ this.XPIDatabase = { ASYNC_SAVE_DELAY_MS); } - this.updateAddonsBlockingE10s(); let promise = this._deferredSave.saveChanges(); if (!this._schemaVersionSet) { this._schemaVersionSet = true; - promise = promise.then( + promise.then( count => { // Update the XPIDB schema version preference the first time we successfully // save the database. @@ -488,17 +451,12 @@ this.XPIDatabase = { error => { // Need to try setting the schema version again later this._schemaVersionSet = false; + logger.warn("Failed to save XPI database", error); // this._deferredSave.lastError has the most recent error so we don't // need this any more this._loadError = null; - - throw error; }); } - - promise.catch(error => { - logger.warn("Failed to save XPI database", error); - }); }, flush: function() { @@ -537,7 +495,7 @@ this.XPIDatabase = { * {location: {id1:{addon1}, id2:{addon2}}, location2:{...}, ...} * if there is useful information */ - getMigrateDataFromSQLITE: function() { + getMigrateDataFromSQLITE: function XPIDB_getMigrateDataFromSQLITE() { let connection = null; let dbfile = FileUtils.getFile(KEY_PROFILEDIR, [FILE_DATABASE], true); // Attempt to open the database @@ -572,7 +530,7 @@ this.XPIDatabase = { * from the install locations if the database needs to be rebuilt. * (if false, caller is XPIProvider.checkForChanges() which will rebuild) */ - syncLoadDB: function(aRebuildOnError) { + syncLoadDB: function XPIDB_syncLoadDB(aRebuildOnError) { this.migrateData = null; let fstream = null; let data = ""; @@ -598,7 +556,7 @@ this.XPIDatabase = { readTimer.done(); this.parseDB(data, aRebuildOnError); } - catch (e) { + catch(e) { logger.error("Failed to load XPI JSON data from profile", e); let rebuildTimer = AddonManagerPrivate.simpleTimer("XPIDB_rebuildReadFailed_MS"); this.rebuildDatabase(aRebuildOnError); @@ -668,25 +626,15 @@ this.XPIDatabase = { // Make AddonInternal instances from the loaded data and save them let addonDB = new Map(); for (let loadedAddon of inputAddons.addons) { - loadedAddon._sourceBundle = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); - try { - loadedAddon._sourceBundle.persistentDescriptor = loadedAddon.descriptor; - } - catch (e) { - // We can fail here when the descriptor is invalid, usually from the - // wrong OS - logger.warn("Could not find source bundle for add-on " + loadedAddon.id, e); - } - let newAddon = new DBAddonInternal(loadedAddon); addonDB.set(newAddon._key, newAddon); - } + }; parseTimer.done(); this.addonDB = addonDB; logger.debug("Successfully read XPI database"); this.initialized = true; } - catch (e) { + catch(e) { // If we catch and log a SyntaxError from the JSON // parser, the xpcshell test harness fails the test for us: bug 870828 parseTimer.done(); @@ -722,7 +670,7 @@ this.XPIDatabase = { AddonManagerPrivate.recordSimpleMeasure("XPIDB_startupError", "dbMissing"); } } - catch (e) { + catch(e) { // No schema version pref means either a really old upgrade (RDF) or // a new profile this.migrateData = this.getMigrateDataFromRDF(); @@ -756,7 +704,7 @@ this.XPIDatabase = { * @return Promise<Map> resolves to the Map of loaded JSON data stored * in this.addonDB; never rejects. */ - asyncLoadDB: function() { + asyncLoadDB: function XPIDB_asyncLoadDB() { // Already started (and possibly finished) loading if (this._dbPromise) { return this._dbPromise; @@ -810,7 +758,7 @@ this.XPIDatabase = { * from the install locations if the database needs to be rebuilt. * (if false, caller is XPIProvider.checkForChanges() which will rebuild) */ - rebuildDatabase: function(aRebuildOnError) { + rebuildDatabase: function XIPDB_rebuildDatabase(aRebuildOnError) { this.addonDB = new Map(); this.initialized = true; @@ -828,7 +776,7 @@ this.XPIDatabase = { if (aRebuildOnError) { logger.warn("Rebuilding add-ons database from installed extensions."); try { - XPIDatabaseReconcile.processFileChanges({}, false); + XPIProvider.processFileChanges({}, false); } catch (e) { logger.error("Failed to rebuild XPI database from installed extensions", e); @@ -846,7 +794,7 @@ this.XPIDatabase = { * * @return an array of persistent descriptors for the directories */ - getActiveBundles: function() { + getActiveBundles: function XPIDB_getActiveBundles() { let bundles = []; // non-bootstrapped extensions @@ -885,7 +833,7 @@ this.XPIDatabase = { * @return an object holding information about what add-ons were previously * userDisabled and any updated compatibility information */ - getMigrateDataFromRDF: function(aDbWasMissing) { + getMigrateDataFromRDF: function XPIDB_getMigrateDataFromRDF(aDbWasMissing) { // Migrate data from extensions.rdf let rdffile = FileUtils.getFile(KEY_PROFILEDIR, [FILE_OLD_DATABASE], true); @@ -957,7 +905,7 @@ this.XPIDatabase = { * @return an object holding information about what add-ons were previously * userDisabled and any updated compatibility information */ - getMigrateDataFromDatabase: function(aConnection) { + getMigrateDataFromDatabase: function XPIDB_getMigrateDataFromDatabase(aConnection) { let migrateData = {}; // Attempt to migrate data from a different (even future!) version of the @@ -970,7 +918,7 @@ this.XPIDatabase = { let reqCount = 0; let props = []; - for (let row of resultRows(stmt)) { + for (let row in resultRows(stmt)) { if (REQUIRED.indexOf(row.name) != -1) { reqCount++; props.push(row.name); @@ -990,7 +938,7 @@ this.XPIDatabase = { stmt.finalize(); stmt = aConnection.createStatement("SELECT " + props.join(",") + " FROM addon"); - for (let row of resultRows(stmt)) { + for (let row in resultRows(stmt)) { if (!(row.location in migrateData)) migrateData[row.location] = {}; let addonData = { @@ -1017,7 +965,7 @@ this.XPIDatabase = { for (let id in migrateData[location]) { taStmt.params.internal_id = migrateData[location][id].internal_id; delete migrateData[location][id].internal_id; - for (let row of resultRows(taStmt)) { + for (let row in resultRows(taStmt)) { migrateData[location][id].targetApplications.push({ id: row.id, minVersion: row.minVersion, @@ -1048,7 +996,7 @@ this.XPIDatabase = { * flush after the database is flushed and * all cleanup is done */ - shutdown: function() { + shutdown: function XPIDB_shutdown() { logger.debug("shutdown"); if (this.initialized) { // If our last database I/O had an error, try one last time to save. @@ -1127,7 +1075,7 @@ this.XPIDatabase = { }) .then(null, error => { - logger.error("getAddon failed", error); + logger.error("getAddon failed", e); makeSafe(aCallback)(null); }); }, @@ -1143,25 +1091,13 @@ this.XPIDatabase = { * @param aCallback * A callback to pass the DBAddonInternal to */ - getAddonInLocation: function(aId, aLocation, aCallback) { + getAddonInLocation: function XPIDB_getAddonInLocation(aId, aLocation, aCallback) { this.asyncLoadDB().then( addonDB => getRepositoryAddon(addonDB.get(aLocation + ":" + aId), makeSafe(aCallback))); }, /** - * Asynchronously get all the add-ons in a particular install location. - * - * @param aLocation - * The name of the install location - * @param aCallback - * A callback to pass the array of DBAddonInternals to - */ - getAddonsInLocation: function(aLocation, aCallback) { - this.getAddonList(aAddon => aAddon._installLocation.name == aLocation, aCallback); - }, - - /** * Asynchronously gets the add-on with the specified ID that is visible. * * @param aId @@ -1169,7 +1105,7 @@ this.XPIDatabase = { * @param aCallback * A callback to pass the DBAddonInternal to */ - getVisibleAddonForID: function(aId, aCallback) { + getVisibleAddonForID: function XPIDB_getVisibleAddonForID(aId, aCallback) { this.getAddon(aAddon => ((aAddon.id == aId) && aAddon.visible), aCallback); }, @@ -1182,7 +1118,7 @@ this.XPIDatabase = { * @param aCallback * A callback to pass the array of DBAddonInternals to */ - getVisibleAddons: function(aTypes, aCallback) { + getVisibleAddons: function XPIDB_getVisibleAddons(aTypes, aCallback) { this.getAddonList(aAddon => (aAddon.visible && (!aTypes || (aTypes.length == 0) || (aTypes.indexOf(aAddon.type) > -1))), @@ -1196,7 +1132,7 @@ this.XPIDatabase = { * The type of add-on to retrieve * @return an array of DBAddonInternals */ - getAddonsByType: function(aType) { + getAddonsByType: function XPIDB_getAddonsByType(aType) { if (!this.addonDB) { // jank-tastic! Must synchronously load DB if the theme switches from // an XPI theme to a lightweight theme before the DB has loaded, @@ -1215,7 +1151,7 @@ this.XPIDatabase = { * The internalName of the add-on to retrieve * @return a DBAddonInternal */ - getVisibleAddonForInternalName: function(aInternalName) { + getVisibleAddonForInternalName: function XPIDB_getVisibleAddonForInternalName(aInternalName) { if (!this.addonDB) { // This may be called when the DB hasn't otherwise been loaded logger.warn("Synchronous load of XPI database due to getVisibleAddonForInternalName"); @@ -1223,7 +1159,7 @@ this.XPIDatabase = { XPIProvider.runPhase); this.syncLoadDB(true); } - + return _findAddon(this.addonDB, aAddon => aAddon.visible && (aAddon.internalName == aInternalName)); @@ -1237,7 +1173,9 @@ this.XPIDatabase = { * @param aCallback * A callback to pass the array of DBAddonInternal to */ - getVisibleAddonsWithPendingOperations: function(aTypes, aCallback) { + getVisibleAddonsWithPendingOperations: + function XPIDB_getVisibleAddonsWithPendingOperations(aTypes, aCallback) { + this.getAddonList( aAddon => (aAddon.visible && (aAddon.pendingUninstall || @@ -1258,7 +1196,7 @@ this.XPIDatabase = { * if no add-on with that GUID is found. * */ - getAddonBySyncGUID: function(aGUID, aCallback) { + getAddonBySyncGUID: function XPIDB_getAddonBySyncGUID(aGUID, aCallback) { this.getAddon(aAddon => aAddon.syncGUID == aGUID, aCallback); }, @@ -1271,7 +1209,7 @@ this.XPIDatabase = { * * @return an array of DBAddonInternals */ - getAddons: function() { + getAddons: function XPIDB_getAddons() { if (!this.addonDB) { return []; } @@ -1287,7 +1225,7 @@ this.XPIDatabase = { * The file descriptor of the add-on * @return The DBAddonInternal that was added to the database */ - addAddonMetadata: function(aAddon, aDescriptor) { + addAddonMetadata: function XPIDB_addAddonMetadata(aAddon, aDescriptor) { if (!this.addonDB) { AddonManagerPrivate.recordSimpleMeasure("XPIDB_lateOpen_addMetadata", XPIProvider.runPhase); @@ -1317,13 +1255,13 @@ this.XPIDatabase = { * The file descriptor of the add-on * @return The DBAddonInternal that was added to the database */ - updateAddonMetadata: function(aOldAddon, aNewAddon, aDescriptor) { + updateAddonMetadata: function XPIDB_updateAddonMetadata(aOldAddon, aNewAddon, + aDescriptor) { this.removeAddonMetadata(aOldAddon); aNewAddon.syncGUID = aOldAddon.syncGUID; aNewAddon.installDate = aOldAddon.installDate; aNewAddon.applyBackgroundUpdates = aOldAddon.applyBackgroundUpdates; aNewAddon.foreignInstall = aOldAddon.foreignInstall; - aNewAddon.seen = aOldAddon.seen; aNewAddon.active = (aNewAddon.visible && !aNewAddon.disabled && !aNewAddon.pendingUninstall); // addAddonMetadata does a saveChanges() @@ -1336,7 +1274,7 @@ this.XPIDatabase = { * @param aAddon * The DBAddonInternal being removed */ - removeAddonMetadata: function(aAddon) { + removeAddonMetadata: function XPIDB_removeAddonMetadata(aAddon) { this.addonDB.delete(aAddon._key); this.saveChanges(); }, @@ -1348,13 +1286,12 @@ this.XPIDatabase = { * @param aAddon * The DBAddonInternal to make visible */ - makeAddonVisible: function(aAddon) { + makeAddonVisible: function XPIDB_makeAddonVisible(aAddon) { logger.debug("Make addon " + aAddon._key + " visible"); for (let [, otherAddon] of this.addonDB) { if ((otherAddon.id == aAddon.id) && (otherAddon._key != aAddon._key)) { logger.debug("Hide addon " + otherAddon._key); otherAddon.visible = false; - otherAddon.active = false; } } aAddon.visible = true; @@ -1369,7 +1306,7 @@ this.XPIDatabase = { * @param aProperties * A dictionary of properties to set */ - setAddonProperties: function(aAddon, aProperties) { + setAddonProperties: function XPIDB_setAddonProperties(aAddon, aProperties) { for (let key in aProperties) { aAddon[key] = aProperties[key]; } @@ -1386,7 +1323,7 @@ this.XPIDatabase = { * GUID string to set the value to * @throws if another addon already has the specified GUID */ - setAddonSyncGUID: function(aAddon, aGUID) { + setAddonSyncGUID: function XPIDB_setAddonSyncGUID(aAddon, aGUID) { // Need to make sure no other addon has this GUID function excludeSyncGUID(otherAddon) { return (otherAddon._key != aAddon._key) && (otherAddon.syncGUID == aGUID); @@ -1406,32 +1343,17 @@ this.XPIDatabase = { * @param aAddon * The DBAddonInternal to update */ - updateAddonActive: function(aAddon, aActive) { + updateAddonActive: function XPIDB_updateAddonActive(aAddon, aActive) { logger.debug("Updating active state for add-on " + aAddon.id + " to " + aActive); aAddon.active = aActive; this.saveChanges(); }, - updateAddonsBlockingE10s: function() { - let blockE10s = false; - - Preferences.set(PREF_E10S_HAS_NONEXEMPT_ADDON, false); - for (let [, addon] of this.addonDB) { - let active = (addon.visible && !addon.disabled && !addon.pendingUninstall); - - if (active && XPIProvider.isBlockingE10s(addon)) { - blockE10s = true; - break; - } - } - Preferences.set(PREF_E10S_BLOCKED_BY_ADDONS, blockE10s); - }, - /** * Synchronously calculates and updates all the active flags in the database. */ - updateActiveAddons: function() { + updateActiveAddons: function XPIDB_updateActiveAddons() { if (!this.addonDB) { logger.warn("updateActiveAddons called when DB isn't loaded"); // force the DB to load @@ -1453,7 +1375,7 @@ this.XPIDatabase = { * Writes out the XPI add-ons list for the platform to read. * @return true if the file was successfully updated, false otherwise */ - writeAddonsList: function() { + writeAddonsList: function XPIDB_writeAddonsList() { if (!this.addonDB) { // force the DB to load AddonManagerPrivate.recordSimpleMeasure("XPIDB_lateOpen_writeList", @@ -1557,699 +1479,3 @@ this.XPIDatabase = { return true; } }; - -this.XPIDatabaseReconcile = { - /** - * Returns a map of ID -> add-on. When the same add-on ID exists in multiple - * install locations the highest priority location is chosen. - */ - flattenByID(addonMap, hideLocation) { - let map = new Map(); - - for (let installLocation of XPIProvider.installLocations) { - if (installLocation.name == hideLocation) - continue; - - let locationMap = addonMap.get(installLocation.name); - if (!locationMap) - continue; - - for (let [id, addon] of locationMap) { - if (!map.has(id)) - map.set(id, addon); - } - } - - return map; - }, - - /** - * Finds the visible add-ons from the map. - */ - getVisibleAddons(addonMap) { - let map = new Map(); - - for (let [location, addons] of addonMap) { - for (let [id, addon] of addons) { - if (!addon.visible) - continue; - - if (map.has(id)) { - logger.warn("Previous database listed more than one visible add-on with id " + id); - continue; - } - - map.set(id, addon); - } - } - - return map; - }, - - /** - * Called to add the metadata for an add-on in one of the install locations - * to the database. This can be called in three different cases. Either an - * add-on has been dropped into the location from outside of Firefox, or - * an add-on has been installed through the application, or the database - * has been upgraded or become corrupt and add-on data has to be reloaded - * into it. - * - * @param aInstallLocation - * The install location containing the add-on - * @param aId - * The ID of the add-on - * @param aAddonState - * The new state of the add-on - * @param aNewAddon - * The manifest for the new add-on if it has already been loaded - * @param aOldAppVersion - * The version of the application last run with this profile or null - * if it is a new profile or the version is unknown - * @param aOldPlatformVersion - * The version of the platform last run with this profile or null - * if it is a new profile or the version is unknown - * @param aMigrateData - * If during startup the database had to be upgraded this will - * contain data that used to be held about this add-on - * @return a boolean indicating if flushing caches is required to complete - * changing this add-on - */ - addMetadata(aInstallLocation, aId, aAddonState, aNewAddon, aOldAppVersion, - aOldPlatformVersion, aMigrateData) { - logger.debug("New add-on " + aId + " installed in " + aInstallLocation.name); - - // If we had staged data for this add-on or we aren't recovering from a - // corrupt database and we don't have migration data for this add-on then - // this must be a new install. - let isNewInstall = (!!aNewAddon) || (!XPIDatabase.activeBundles && !aMigrateData); - - // If it's a new install and we haven't yet loaded the manifest then it - // must be something dropped directly into the install location - let isDetectedInstall = isNewInstall && !aNewAddon; - - // Load the manifest if necessary and sanity check the add-on ID - try { - if (!aNewAddon) { - // Load the manifest from the add-on. - let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); - file.persistentDescriptor = aAddonState.descriptor; - aNewAddon = syncLoadManifestFromFile(file, aInstallLocation); - } - // The add-on in the manifest should match the add-on ID. - if (aNewAddon.id != aId) { - throw new Error("Invalid addon ID: expected addon ID " + aId + - ", found " + aNewAddon.id + " in manifest"); - } - } - catch (e) { - logger.warn("addMetadata: Add-on " + aId + " is invalid", e); - - // Remove the invalid add-on from the install location if the install - // location isn't locked, no restart will be necessary - if (aInstallLocation.isLinkedAddon(aId)) - logger.warn("Not uninstalling invalid item because it is a proxy file"); - else if (aInstallLocation.locked) - logger.warn("Could not uninstall invalid item from locked install location"); - else - aInstallLocation.uninstallAddon(aId); - return null; - } - - // Update the AddonInternal properties. - aNewAddon.installDate = aAddonState.mtime; - aNewAddon.updateDate = aAddonState.mtime; - - // Assume that add-ons in the system add-ons install location aren't - // foreign and should default to enabled. - aNewAddon.foreignInstall = isDetectedInstall && - aInstallLocation.name != KEY_APP_SYSTEM_ADDONS && - aInstallLocation.name != KEY_APP_SYSTEM_DEFAULTS; - - // appDisabled depends on whether the add-on is a foreignInstall so update - aNewAddon.appDisabled = !isUsableAddon(aNewAddon); - - if (aMigrateData) { - // If there is migration data then apply it. - logger.debug("Migrating data from old database"); - - DB_MIGRATE_METADATA.forEach(function(aProp) { - // A theme's disabled state is determined by the selected theme - // preference which is read in loadManifestFromRDF - if (aProp == "userDisabled" && aNewAddon.type == "theme") - return; - - if (aProp in aMigrateData) - aNewAddon[aProp] = aMigrateData[aProp]; - }); - - // Force all non-profile add-ons to be foreignInstalls since they can't - // have been installed through the API - aNewAddon.foreignInstall |= aInstallLocation.name != KEY_APP_PROFILE; - - // Some properties should only be migrated if the add-on hasn't changed. - // The version property isn't a perfect check for this but covers the - // vast majority of cases. - if (aMigrateData.version == aNewAddon.version) { - logger.debug("Migrating compatibility info"); - if ("targetApplications" in aMigrateData) - aNewAddon.applyCompatibilityUpdate(aMigrateData, true); - } - - // Since the DB schema has changed make sure softDisabled is correct - applyBlocklistChanges(aNewAddon, aNewAddon, aOldAppVersion, - aOldPlatformVersion); - } - - // The default theme is never a foreign install - if (aNewAddon.type == "theme" && aNewAddon.internalName == XPIProvider.defaultSkin) - aNewAddon.foreignInstall = false; - - if (isDetectedInstall && aNewAddon.foreignInstall) { - // If the add-on is a foreign install and is in a scope where add-ons - // that were dropped in should default to disabled then disable it - let disablingScopes = Preferences.get(PREF_EM_AUTO_DISABLED_SCOPES, 0); - if (aInstallLocation.scope & disablingScopes) { - logger.warn("Disabling foreign installed add-on " + aNewAddon.id + " in " - + aInstallLocation.name); - aNewAddon.userDisabled = true; - - // If we don't have an old app version then this is a new profile in - // which case just mark any sideloaded add-ons as already seen. - aNewAddon.seen = !aOldAppVersion; - } - } - - return XPIDatabase.addAddonMetadata(aNewAddon, aAddonState.descriptor); - }, - - /** - * Called when an add-on has been removed. - * - * @param aOldAddon - * The AddonInternal as it appeared the last time the application - * ran - * @return a boolean indicating if flushing caches is required to complete - * changing this add-on - */ - removeMetadata(aOldAddon) { - // This add-on has disappeared - logger.debug("Add-on " + aOldAddon.id + " removed from " + aOldAddon.location); - XPIDatabase.removeAddonMetadata(aOldAddon); - }, - - /** - * Updates an add-on's metadata and determines if a restart of the - * application is necessary. This is called when either the add-on's - * install directory path or last modified time has changed. - * - * @param aInstallLocation - * The install location containing the add-on - * @param aOldAddon - * The AddonInternal as it appeared the last time the application - * ran - * @param aAddonState - * The new state of the add-on - * @param aNewAddon - * The manifest for the new add-on if it has already been loaded - * @return a boolean indicating if flushing caches is required to complete - * changing this add-on - */ - updateMetadata(aInstallLocation, aOldAddon, aAddonState, aNewAddon) { - logger.debug("Add-on " + aOldAddon.id + " modified in " + aInstallLocation.name); - - try { - // If there isn't an updated install manifest for this add-on then load it. - if (!aNewAddon) { - let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); - file.persistentDescriptor = aAddonState.descriptor; - aNewAddon = syncLoadManifestFromFile(file, aInstallLocation); - applyBlocklistChanges(aOldAddon, aNewAddon); - - // Carry over any pendingUninstall state to add-ons modified directly - // in the profile. This is important when the attempt to remove the - // add-on in processPendingFileChanges failed and caused an mtime - // change to the add-ons files. - aNewAddon.pendingUninstall = aOldAddon.pendingUninstall; - } - - // The ID in the manifest that was loaded must match the ID of the old - // add-on. - if (aNewAddon.id != aOldAddon.id) - throw new Error("Incorrect id in install manifest for existing add-on " + aOldAddon.id); - } - catch (e) { - logger.warn("updateMetadata: Add-on " + aOldAddon.id + " is invalid", e); - XPIDatabase.removeAddonMetadata(aOldAddon); - XPIStates.removeAddon(aOldAddon.location, aOldAddon.id); - if (!aInstallLocation.locked) - aInstallLocation.uninstallAddon(aOldAddon.id); - else - logger.warn("Could not uninstall invalid item from locked install location"); - - return null; - } - - // Set the additional properties on the new AddonInternal - aNewAddon.updateDate = aAddonState.mtime; - - // Update the database - return XPIDatabase.updateAddonMetadata(aOldAddon, aNewAddon, aAddonState.descriptor); - }, - - /** - * Updates an add-on's descriptor for when the add-on has moved in the - * filesystem but hasn't changed in any other way. - * - * @param aInstallLocation - * The install location containing the add-on - * @param aOldAddon - * The AddonInternal as it appeared the last time the application - * ran - * @param aAddonState - * The new state of the add-on - * @return a boolean indicating if flushing caches is required to complete - * changing this add-on - */ - updateDescriptor(aInstallLocation, aOldAddon, aAddonState) { - logger.debug("Add-on " + aOldAddon.id + " moved to " + aAddonState.descriptor); - aOldAddon.descriptor = aAddonState.descriptor; - aOldAddon._sourceBundle.persistentDescriptor = aAddonState.descriptor; - - return aOldAddon; - }, - - /** - * Called when no change has been detected for an add-on's metadata but the - * application has changed so compatibility may have changed. - * - * @param aInstallLocation - * The install location containing the add-on - * @param aOldAddon - * The AddonInternal as it appeared the last time the application - * ran - * @param aAddonState - * The new state of the add-on - * @param aOldAppVersion - * The version of the application last run with this profile or null - * if it is a new profile or the version is unknown - * @param aOldPlatformVersion - * The version of the platform last run with this profile or null - * if it is a new profile or the version is unknown - * @param aReloadMetadata - * A boolean which indicates whether metadata should be reloaded from - * the addon manifests. Default to false. - * @return the new addon. - */ - updateCompatibility(aInstallLocation, aOldAddon, aAddonState, aOldAppVersion, - aOldPlatformVersion, aReloadMetadata) { - logger.debug("Updating compatibility for add-on " + aOldAddon.id + " in " + aInstallLocation.name); - - // If updating from a version of the app that didn't support signedState - // then fetch that property now - if (aOldAddon.signedState === undefined && ADDON_SIGNING && - SIGNED_TYPES.has(aOldAddon.type)) { - let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); - file.persistentDescriptor = aAddonState.descriptor; - let manifest = syncLoadManifestFromFile(file, aInstallLocation); - aOldAddon.signedState = manifest.signedState; - } - - // May be updating from a version of the app that didn't support all the - // properties of the currently-installed add-ons. - if (aReloadMetadata) { - let file = new nsIFile() - file.persistentDescriptor = aAddonState.descriptor; - let manifest = syncLoadManifestFromFile(file, aInstallLocation); - - // Avoid re-reading these properties from manifest, - // use existing addon instead. - // TODO - consider re-scanning for targetApplications. - let remove = ["syncGUID", "foreignInstall", "visible", "active", - "userDisabled", "applyBackgroundUpdates", "sourceURI", - "releaseNotesURI", "targetApplications"]; - - let props = PROP_JSON_FIELDS.filter(a => !remove.includes(a)); - copyProperties(manifest, props, aOldAddon); - } - - // This updates the addon's JSON cached data in place - applyBlocklistChanges(aOldAddon, aOldAddon, aOldAppVersion, - aOldPlatformVersion); - aOldAddon.appDisabled = !isUsableAddon(aOldAddon); - - return aOldAddon; - }, - - /** - * Compares the add-ons that are currently installed to those that were - * known to be installed when the application last ran and applies any - * changes found to the database. Also sends "startupcache-invalidate" signal to - * observerservice if it detects that data may have changed. - * Always called after XPIProviderUtils.js and extensions.json have been loaded. - * - * @param aManifests - * A dictionary of cached AddonInstalls for add-ons that have been - * installed - * @param aUpdateCompatibility - * true to update add-ons appDisabled property when the application - * version has changed - * @param aOldAppVersion - * The version of the application last run with this profile or null - * if it is a new profile or the version is unknown - * @param aOldPlatformVersion - * The version of the platform last run with this profile or null - * if it is a new profile or the version is unknown - * @param aSchemaChange - * The schema has changed and all add-on manifests should be re-read. - * @return a boolean indicating if a change requiring flushing the caches was - * detected - */ - processFileChanges(aManifests, aUpdateCompatibility, aOldAppVersion, aOldPlatformVersion, - aSchemaChange) { - let loadedManifest = (aInstallLocation, aId) => { - if (!(aInstallLocation.name in aManifests)) - return null; - if (!(aId in aManifests[aInstallLocation.name])) - return null; - return aManifests[aInstallLocation.name][aId]; - }; - - // Add-ons loaded from the database can have an uninitialized _sourceBundle - // if the descriptor was invalid. Swallow that error and say they don't exist. - let exists = (aAddon) => { - try { - return aAddon._sourceBundle.exists(); - } - catch (e) { - if (e.result == Cr.NS_ERROR_NOT_INITIALIZED) - return false; - throw e; - } - }; - - // Get the previous add-ons from the database and put them into maps by location - let previousAddons = new Map(); - for (let a of XPIDatabase.getAddons()) { - let locationAddonMap = previousAddons.get(a.location); - if (!locationAddonMap) { - locationAddonMap = new Map(); - previousAddons.set(a.location, locationAddonMap); - } - locationAddonMap.set(a.id, a); - } - - // Build the list of current add-ons into similar maps. When add-ons are still - // present we re-use the add-on objects from the database and update their - // details directly - let currentAddons = new Map(); - for (let installLocation of XPIProvider.installLocations) { - let locationAddonMap = new Map(); - currentAddons.set(installLocation.name, locationAddonMap); - - // Get all the on-disk XPI states for this location, and keep track of which - // ones we see in the database. - let states = XPIStates.getLocation(installLocation.name); - - // Iterate through the add-ons installed the last time the application - // ran - let dbAddons = previousAddons.get(installLocation.name); - if (dbAddons) { - for (let [id, oldAddon] of dbAddons) { - // Check if the add-on is still installed - let xpiState = states && states.get(id); - if (xpiState) { - // Here the add-on was present in the database and on disk - recordAddonTelemetry(oldAddon); - - // Check if the add-on has been changed outside the XPI provider - if (oldAddon.updateDate != xpiState.mtime) { - // Did time change in the wrong direction? - if (xpiState.mtime < oldAddon.updateDate) { - XPIProvider.setTelemetry(oldAddon.id, "olderFile", { - name: XPIProvider._mostRecentlyModifiedFile[id], - mtime: xpiState.mtime, - oldtime: oldAddon.updateDate - }); - } else { - XPIProvider.setTelemetry(oldAddon.id, "modifiedFile", - XPIProvider._mostRecentlyModifiedFile[id]); - } - } - - // The add-on has changed if the modification time has changed, if - // we have an updated manifest for it, or if the schema version has - // changed. - // - // Also reload the metadata for add-ons in the application directory - // when the application version has changed. - let newAddon = loadedManifest(installLocation, id); - if (newAddon || oldAddon.updateDate != xpiState.mtime || - (aUpdateCompatibility && (installLocation.name == KEY_APP_GLOBAL || - installLocation.name == KEY_APP_SYSTEM_DEFAULTS))) { - newAddon = this.updateMetadata(installLocation, oldAddon, xpiState, newAddon); - } - else if (oldAddon.descriptor != xpiState.descriptor) { - newAddon = this.updateDescriptor(installLocation, oldAddon, xpiState); - } - // Check compatility when the application version and/or schema - // version has changed. A schema change also reloads metadata from - // the manifests. - else if (aUpdateCompatibility || aSchemaChange) { - newAddon = this.updateCompatibility(installLocation, oldAddon, xpiState, - aOldAppVersion, aOldPlatformVersion, - aSchemaChange); - } - else { - // No change - newAddon = oldAddon; - } - - if (newAddon) - locationAddonMap.set(newAddon.id, newAddon); - } - else { - // The add-on is in the DB, but not in xpiState (and thus not on disk). - this.removeMetadata(oldAddon); - } - } - } - - // Any add-on in our current location that we haven't seen needs to - // be added to the database. - // Get the migration data for this install location so we can include that as - // we add, in case this is a database upgrade or rebuild. - let locMigrateData = {}; - if (XPIDatabase.migrateData && installLocation.name in XPIDatabase.migrateData) - locMigrateData = XPIDatabase.migrateData[installLocation.name]; - - if (states) { - for (let [id, xpiState] of states) { - if (locationAddonMap.has(id)) - continue; - let migrateData = id in locMigrateData ? locMigrateData[id] : null; - let newAddon = loadedManifest(installLocation, id); - let addon = this.addMetadata(installLocation, id, xpiState, newAddon, - aOldAppVersion, aOldPlatformVersion, migrateData); - if (addon) - locationAddonMap.set(addon.id, addon); - } - } - } - - // previousAddons may contain locations where the database contains add-ons - // but the browser is no longer configured to use that location. The metadata - // for those add-ons must be removed from the database. - for (let [locationName, addons] of previousAddons) { - if (!currentAddons.has(locationName)) { - for (let [id, oldAddon] of addons) - this.removeMetadata(oldAddon); - } - } - - // Validate the updated system add-ons - let systemAddonLocation = XPIProvider.installLocationsByName[KEY_APP_SYSTEM_ADDONS]; - let addons = currentAddons.get(KEY_APP_SYSTEM_ADDONS) || new Map(); - - let hideLocation; - - if (!systemAddonLocation.isValid(addons)) { - // Hide the system add-on updates if any are invalid. - logger.info("One or more updated system add-ons invalid, falling back to defaults."); - hideLocation = KEY_APP_SYSTEM_ADDONS; - } - - let previousVisible = this.getVisibleAddons(previousAddons); - let currentVisible = this.flattenByID(currentAddons, hideLocation); - let sawActiveTheme = false; - XPIProvider.bootstrappedAddons = {}; - - // Pass over the new set of visible add-ons, record any changes that occured - // during startup and call bootstrap install/uninstall scripts as necessary - for (let [id, currentAddon] of currentVisible) { - let previousAddon = previousVisible.get(id); - - // Note if any visible add-on is not in the application install location - if (currentAddon._installLocation.name != KEY_APP_GLOBAL) - XPIProvider.allAppGlobal = false; - - let isActive = !currentAddon.disabled; - let wasActive = previousAddon ? previousAddon.active : currentAddon.active - - if (!previousAddon) { - // If we had a manifest for this add-on it was a staged install and - // so wasn't something recovered from a corrupt database - let wasStaged = !!loadedManifest(currentAddon._installLocation, id); - - // We might be recovering from a corrupt database, if so use the - // list of known active add-ons to update the new add-on - if (!wasStaged && XPIDatabase.activeBundles) { - // For themes we know which is active by the current skin setting - if (currentAddon.type == "theme") - isActive = currentAddon.internalName == XPIProvider.currentSkin; - else - isActive = XPIDatabase.activeBundles.indexOf(currentAddon.descriptor) != -1; - - // If the add-on wasn't active and it isn't already disabled in some way - // then it was probably either softDisabled or userDisabled - if (!isActive && !currentAddon.disabled) { - // If the add-on is softblocked then assume it is softDisabled - if (currentAddon.blocklistState == Blocklist.STATE_SOFTBLOCKED) - currentAddon.softDisabled = true; - else - currentAddon.userDisabled = true; - } - } - else { - // This is a new install - if (currentAddon.foreignInstall) - AddonManagerPrivate.addStartupChange(AddonManager.STARTUP_CHANGE_INSTALLED, id); - - if (currentAddon.bootstrap) { - AddonManagerPrivate.addStartupChange(AddonManager.STARTUP_CHANGE_INSTALLED, id); - // Visible bootstrapped add-ons need to have their install method called - XPIProvider.callBootstrapMethod(currentAddon, currentAddon._sourceBundle, - "install", BOOTSTRAP_REASONS.ADDON_INSTALL); - if (!isActive) - XPIProvider.unloadBootstrapScope(currentAddon.id); - } - } - } - else { - if (previousAddon !== currentAddon) { - // This is an add-on that has changed, either the metadata was reloaded - // or the version in a different location has become visible - AddonManagerPrivate.addStartupChange(AddonManager.STARTUP_CHANGE_CHANGED, id); - - let installReason = Services.vc.compare(previousAddon.version, currentAddon.version) < 0 ? - BOOTSTRAP_REASONS.ADDON_UPGRADE : - BOOTSTRAP_REASONS.ADDON_DOWNGRADE; - - // If the previous add-on was in a different path, bootstrapped - // and still exists then call its uninstall method. - if (previousAddon.bootstrap && previousAddon._installLocation && - exists(previousAddon) && - currentAddon._sourceBundle.path != previousAddon._sourceBundle.path) { - - XPIProvider.callBootstrapMethod(previousAddon, previousAddon._sourceBundle, - "uninstall", installReason, - { newVersion: currentAddon.version }); - XPIProvider.unloadBootstrapScope(previousAddon.id); - } - - // Make sure to flush the cache when an old add-on has gone away - flushChromeCaches(); - - if (currentAddon.bootstrap) { - // Visible bootstrapped add-ons need to have their install method called - let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); - file.persistentDescriptor = currentAddon._sourceBundle.persistentDescriptor; - XPIProvider.callBootstrapMethod(currentAddon, file, - "install", installReason, - { oldVersion: previousAddon.version }); - if (currentAddon.disabled) - XPIProvider.unloadBootstrapScope(currentAddon.id); - } - } - - if (isActive != wasActive) { - let change = isActive ? AddonManager.STARTUP_CHANGE_ENABLED - : AddonManager.STARTUP_CHANGE_DISABLED; - AddonManagerPrivate.addStartupChange(change, id); - } - } - - XPIDatabase.makeAddonVisible(currentAddon); - currentAddon.active = isActive; - - // Make sure the bootstrap information is up to date for this ID - if (currentAddon.bootstrap && currentAddon.active) { - XPIProvider.bootstrappedAddons[id] = { - version: currentAddon.version, - type: currentAddon.type, - descriptor: currentAddon._sourceBundle.persistentDescriptor, - multiprocessCompatible: currentAddon.multiprocessCompatible, - runInSafeMode: canRunInSafeMode(currentAddon), - dependencies: currentAddon.dependencies, - hasEmbeddedWebExtension: currentAddon.hasEmbeddedWebExtension, - }; - } - - if (currentAddon.active && currentAddon.internalName == XPIProvider.selectedSkin) - sawActiveTheme = true; - } - - // Pass over the set of previously visible add-ons that have now gone away - // and record the change. - for (let [id, previousAddon] of previousVisible) { - if (currentVisible.has(id)) - continue; - - // This add-on vanished - - // If the previous add-on was bootstrapped and still exists then call its - // uninstall method. - if (previousAddon.bootstrap && exists(previousAddon)) { - XPIProvider.callBootstrapMethod(previousAddon, previousAddon._sourceBundle, - "uninstall", BOOTSTRAP_REASONS.ADDON_UNINSTALL); - XPIProvider.unloadBootstrapScope(previousAddon.id); - } - AddonManagerPrivate.addStartupChange(AddonManager.STARTUP_CHANGE_UNINSTALLED, id); - - // Make sure to flush the cache when an old add-on has gone away - flushChromeCaches(); - } - - // Make sure add-ons from hidden locations are marked invisible and inactive - let locationAddonMap = currentAddons.get(hideLocation); - if (locationAddonMap) { - for (let addon of locationAddonMap.values()) { - addon.visible = false; - addon.active = false; - } - } - - // If a custom theme is selected and it wasn't seen in the new list of - // active add-ons then enable the default theme - if (XPIProvider.selectedSkin != XPIProvider.defaultSkin && !sawActiveTheme) { - logger.info("Didn't see selected skin " + XPIProvider.selectedSkin); - XPIProvider.enableDefaultTheme(); - } - - // Finally update XPIStates to match everything - for (let [locationName, locationAddonMap] of currentAddons) { - for (let [id, addon] of locationAddonMap) { - let xpiState = XPIStates.getAddon(locationName, id); - xpiState.syncWithDB(addon); - } - } - XPIStates.save(); - - XPIProvider.persistBootstrappedAddons(); - - // Clear out any cached migration data. - XPIDatabase.migrateData = null; - XPIDatabase.saveChanges(); - - return true; - }, -} diff --git a/toolkit/mozapps/extensions/internal/moz.build b/toolkit/mozapps/extensions/internal/moz.build index 28c34f8c9..efcd2af21 100644 --- a/toolkit/mozapps/extensions/internal/moz.build +++ b/toolkit/mozapps/extensions/internal/moz.build @@ -1,28 +1,17 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- # vim: set filetype=python: # 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/. EXTRA_JS_MODULES.addons += [ + '../../webextensions/internal/ProductAddonChecker.jsm', 'AddonLogging.jsm', - 'AddonRepository.jsm', 'AddonRepository_SQLiteMigrator.jsm', - 'AddonUpdateChecker.jsm', - 'APIExtensionBootstrap.js', 'Content.js', - 'E10SAddonsRollout.jsm', 'GMPProvider.jsm', 'LightweightThemeImageOptimizer.jsm', - 'ProductAddonChecker.jsm', 'SpellCheckDictionaryBootstrap.js', - 'WebExtensionBootstrap.js', - 'XPIProvider.jsm', - 'XPIProviderUtils.js', -] - -TESTING_JS_MODULES += [ - 'AddonTestUtils.jsm', ] # Don't ship unused providers on Android @@ -32,5 +21,20 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'android': ] EXTRA_PP_JS_MODULES.addons += [ - 'AddonConstants.jsm', + 'AddonRepository.jsm', + 'AddonUpdateChecker.jsm', + 'XPIProvider.jsm', + 'XPIProviderUtils.js', ] + +# This is used in multiple places, so is defined here to avoid it getting +# out of sync. +DEFINES['MOZ_EXTENSIONS_DB_SCHEMA'] = 16 + +# Additional debugging info is exposed in debug builds +if CONFIG['MOZ_EM_DEBUG']: + DEFINES['MOZ_EM_DEBUG'] = 1 + +# Apperently this needs to be defined because it isn't picked up automagically any more +if CONFIG['MOZ_PHOENIX_EXTENSIONS']: + DEFINES['MOZ_PHOENIX_EXTENSIONS'] = 1
\ No newline at end of file diff --git a/toolkit/mozapps/extensions/jar.mn b/toolkit/mozapps/extensions/jar.mn index ecf64b7ef..e95d93ca0 100644 --- a/toolkit/mozapps/extensions/jar.mn +++ b/toolkit/mozapps/extensions/jar.mn @@ -3,11 +3,10 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. toolkit.jar: -#ifndef MOZ_FENNEC % content mozapps %content/mozapps/ * content/mozapps/extensions/extensions.xul (content/extensions.xul) content/mozapps/extensions/extensions.css (content/extensions.css) - content/mozapps/extensions/extensions.js (content/extensions.js) +* content/mozapps/extensions/extensions.js (content/extensions.js) * content/mozapps/extensions/extensions.xml (content/extensions.xml) content/mozapps/extensions/updateinfo.xsl (content/updateinfo.xsl) content/mozapps/extensions/about.xul (content/about.xul) @@ -18,17 +17,20 @@ toolkit.jar: content/mozapps/extensions/blocklist.js (content/blocklist.js) content/mozapps/extensions/blocklist.css (content/blocklist.css) content/mozapps/extensions/blocklist.xml (content/blocklist.xml) + content/mozapps/extensions/selectAddons.xul (content/selectAddons.xul) + content/mozapps/extensions/selectAddons.xml (content/selectAddons.xml) + content/mozapps/extensions/selectAddons.js (content/selectAddons.js) + content/mozapps/extensions/selectAddons.css (content/selectAddons.css) * content/mozapps/extensions/update.xul (content/update.xul) content/mozapps/extensions/update.js (content/update.js) content/mozapps/extensions/eula.xul (content/eula.xul) content/mozapps/extensions/eula.js (content/eula.js) content/mozapps/extensions/newaddon.xul (content/newaddon.xul) content/mozapps/extensions/newaddon.js (content/newaddon.js) + content/mozapps/extensions/setting.xml (content/setting.xml) content/mozapps/extensions/pluginPrefs.xul (content/pluginPrefs.xul) content/mozapps/extensions/gmpPrefs.xul (content/gmpPrefs.xul) content/mozapps/extensions/OpenH264-license.txt (content/OpenH264-license.txt) -#endif - content/mozapps/extensions/setting.xml (content/setting.xml) content/mozapps/xpinstall/xpinstallConfirm.xul (content/xpinstallConfirm.xul) content/mozapps/xpinstall/xpinstallConfirm.js (content/xpinstallConfirm.js) content/mozapps/xpinstall/xpinstallConfirm.css (content/xpinstallConfirm.css) diff --git a/toolkit/mozapps/extensions/moz.build b/toolkit/mozapps/extensions/moz.build index 12640e115..19f449210 100644 --- a/toolkit/mozapps/extensions/moz.build +++ b/toolkit/mozapps/extensions/moz.build @@ -1,14 +1,9 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- # vim: set filetype=python: # 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/. -SPHINX_TREES['addon-manager'] = 'docs' - -if CONFIG['MOZ_BUILD_APP'] == 'mobile/android': - DEFINES['MOZ_FENNEC'] = True - DIRS += ['internal'] TEST_DIRS += ['test'] @@ -25,42 +20,36 @@ EXTRA_COMPONENTS += [ 'addonManager.js', 'amContentHandler.js', 'amInstallTrigger.js', - 'amWebAPI.js', 'amWebInstallListener.js', - 'nsBlocklistService.js', - 'nsBlocklistServiceContent.js', ] EXTRA_PP_COMPONENTS += [ 'extensions.manifest', + 'nsBlocklistService.js', ] EXTRA_JS_MODULES += [ - 'AddonManager.jsm', 'ChromeManifestParser.jsm', 'DeferredSave.jsm', 'LightweightThemeManager.jsm', ] +EXTRA_PP_JS_MODULES += [ + 'AddonManager.jsm' +] + +# Additional debugging info is exposed in debug builds +if CONFIG['MOZ_EM_DEBUG']: + DEFINES['MOZ_EM_DEBUG'] = 1 + JAR_MANIFESTS += ['jar.mn'] EXPORTS.mozilla += [ - 'AddonContentPolicy.h', - 'AddonManagerWebAPI.h', 'AddonPathService.h', ] UNIFIED_SOURCES += [ - 'AddonContentPolicy.cpp', - 'AddonManagerWebAPI.cpp', - 'AddonPathService.cpp', -] - -LOCAL_INCLUDES += [ - '/dom/base', + 'AddonPathService.cpp' ] FINAL_LIBRARY = 'xul' - -with Files('**'): - BUG_COMPONENT = ('Toolkit', 'Add-ons Manager') diff --git a/toolkit/mozapps/extensions/nsBlocklistService.js b/toolkit/mozapps/extensions/nsBlocklistService.js index 0af90430c..487dae8e5 100644 --- a/toolkit/mozapps/extensions/nsBlocklistService.js +++ b/toolkit/mozapps/extensions/nsBlocklistService.js @@ -12,29 +12,25 @@ const Cr = Components.results; Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); Components.utils.import("resource://gre/modules/Services.jsm"); -Components.utils.import("resource://gre/modules/AppConstants.jsm"); try { // AddonManager.jsm doesn't allow itself to be imported in the child // process. We're used in the child process (for now), so guard against // this. Components.utils.import("resource://gre/modules/AddonManager.jsm"); - /* globals AddonManagerPrivate*/ } catch (e) { } XPCOMUtils.defineLazyModuleGetter(this, "FileUtils", "resource://gre/modules/FileUtils.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "UpdateUtils", - "resource://gre/modules/UpdateUtils.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "UpdateChannel", + "resource://gre/modules/UpdateChannel.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "OS", "resource://gre/modules/osfile.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "ServiceRequest", - "resource://gre/modules/ServiceRequest.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "Task", "resource://gre/modules/Task.jsm"); -const TOOLKIT_ID = "toolkit@mozilla.org"; +const TOOLKIT_ID = "toolkit@mozilla.org" const KEY_PROFILEDIR = "ProfD"; const KEY_APPDIR = "XCurProcD"; const FILE_BLOCKLIST = "blocklist.xml"; @@ -47,8 +43,7 @@ const PREF_BLOCKLIST_LEVEL = "extensions.blocklist.level"; const PREF_BLOCKLIST_PINGCOUNTTOTAL = "extensions.blocklist.pingCountTotal"; const PREF_BLOCKLIST_PINGCOUNTVERSION = "extensions.blocklist.pingCountVersion"; const PREF_BLOCKLIST_SUPPRESSUI = "extensions.blocklist.suppressUI"; -const PREF_ONECRL_VIA_AMO = "security.onecrl.via.amo"; -const PREF_BLOCKLIST_UPDATE_ENABLED = "services.blocklist.update_enabled"; +const PREF_PLUGINS_NOTIFYUSER = "plugins.update.notifyUser"; const PREF_GENERAL_USERAGENT_LOCALE = "general.useragent.locale"; const PREF_APP_DISTRIBUTION = "distribution.id"; const PREF_APP_DISTRIBUTION_VERSION = "distribution.version"; @@ -83,30 +78,17 @@ XPCOMUtils.defineLazyServiceGetter(this, "gCertBlocklistService", "@mozilla.org/security/certblocklist;1", "nsICertBlocklist"); -XPCOMUtils.defineLazyGetter(this, "gPref", function() { +XPCOMUtils.defineLazyGetter(this, "gPref", function bls_gPref() { return Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService). QueryInterface(Ci.nsIPrefBranch); }); -// From appinfo in Services.jsm. It is not possible to use the one in -// Services.jsm since it will not successfully QueryInterface nsIXULAppInfo in -// xpcshell tests due to other code calling Services.appinfo before the -// nsIXULAppInfo is created by the tests. -XPCOMUtils.defineLazyGetter(this, "gApp", function() { - let appinfo = Cc["@mozilla.org/xre/app-info;1"] - .getService(Ci.nsIXULRuntime); - try { - appinfo.QueryInterface(Ci.nsIXULAppInfo); - } catch (ex) { - // Not all applications implement nsIXULAppInfo (e.g. xpcshell doesn't). - if (!(ex instanceof Components.Exception) || - ex.result != Cr.NS_NOINTERFACE) - throw ex; - } - return appinfo; +XPCOMUtils.defineLazyGetter(this, "gApp", function bls_gApp() { + return Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo). + QueryInterface(Ci.nsIXULRuntime); }); -XPCOMUtils.defineLazyGetter(this, "gABI", function() { +XPCOMUtils.defineLazyGetter(this, "gABI", function bls_gABI() { let abi = null; try { abi = gApp.XPCOMABI; @@ -114,20 +96,19 @@ XPCOMUtils.defineLazyGetter(this, "gABI", function() { catch (e) { LOG("BlockList Global gABI: XPCOM ABI unknown."); } - - if (AppConstants.platform == "macosx") { - // Mac universal build should report a different ABI than either macppc - // or mactel. - let macutils = Cc["@mozilla.org/xpcom/mac-utils;1"]. - getService(Ci.nsIMacUtils); - - if (macutils.isUniversalBinary) - abi += "-u-" + macutils.architecturesInBinary; - } +#ifdef XP_MACOSX + // Mac universal build should report a different ABI than either macppc + // or mactel. + let macutils = Cc["@mozilla.org/xpcom/mac-utils;1"]. + getService(Ci.nsIMacUtils); + + if (macutils.isUniversalBinary) + abi += "-u-" + macutils.architecturesInBinary; +#endif return abi; }); -XPCOMUtils.defineLazyGetter(this, "gOSVersion", function() { +XPCOMUtils.defineLazyGetter(this, "gOSVersion", function bls_gOSVersion() { let osVersion; let sysInfo = Cc["@mozilla.org/system-info;1"]. getService(Ci.nsIPropertyBag2); @@ -151,7 +132,7 @@ XPCOMUtils.defineLazyGetter(this, "gOSVersion", function() { }); // shared code for suppressing bad cert dialogs -XPCOMUtils.defineLazyGetter(this, "gCertUtils", function() { +XPCOMUtils.defineLazyGetter(this, "gCertUtils", function bls_gCertUtils() { let temp = { }; Components.utils.import("resource://gre/modules/CertUtils.jsm", temp); return temp; @@ -289,6 +270,26 @@ function parseRegExp(aStr) { } /** + * Helper function to test if the blockEntry matches with the plugin. + * + * @param blockEntry + * The plugin blocklist entries to compare against. + * @param plugin + * The nsIPluginTag to get the blocklist state for. + * @returns True if the blockEntry matches the plugin, false otherwise. + */ +function matchesAllPluginNames(blockEntry, plugin) { + for (let name in blockEntry.matches) { + if (!(name in plugin) || + typeof(plugin[name]) != "string" || + !blockEntry.matches[name].test(plugin[name])) { + return false; + } + } + return true; +} + +/** * Manages the Blocklist. The Blocklist is a representation of the contents of * blocklist.xml and allows us to remotely disable / re-enable blocklisted * items managed by the Extension Manager with an item's appDisabled property. @@ -305,9 +306,6 @@ function Blocklist() { gPref.addObserver("extensions.blocklist.", this, false); gPref.addObserver(PREF_EM_LOGGING_ENABLED, this, false); this.wrappedJSObject = this; - // requests from child processes come in here, see receiveMessage. - Services.ppmm.addMessageListener("Blocklist:getPluginBlocklistState", this); - Services.ppmm.addMessageListener("Blocklist:content-blocklist-updated", this); } Blocklist.prototype = { @@ -327,21 +325,14 @@ Blocklist.prototype = { * (default = *) */ _addonEntries: null, - _gfxEntries: null, _pluginEntries: null, - shutdown: function() { - Services.obs.removeObserver(this, "xpcom-shutdown"); - Services.ppmm.removeMessageListener("Blocklist:getPluginBlocklistState", this); - Services.ppmm.removeMessageListener("Blocklist:content-blocklist-updated", this); - gPref.removeObserver("extensions.blocklist.", this); - gPref.removeObserver(PREF_EM_LOGGING_ENABLED, this); - }, - - observe: function(aSubject, aTopic, aData) { + observe: function Blocklist_observe(aSubject, aTopic, aData) { switch (aTopic) { case "xpcom-shutdown": - this.shutdown(); + Services.obs.removeObserver(this, "xpcom-shutdown"); + gPref.removeObserver("extensions.blocklist.", this); + gPref.removeObserver(PREF_EM_LOGGING_ENABLED, this); break; case "nsPref:changed": switch (aData) { @@ -367,30 +358,14 @@ Blocklist.prototype = { } }, - // Message manager message handlers - receiveMessage: function(aMsg) { - switch (aMsg.name) { - case "Blocklist:getPluginBlocklistState": - return this.getPluginBlocklistState(aMsg.data.addonData, - aMsg.data.appVersion, - aMsg.data.toolkitVersion); - case "Blocklist:content-blocklist-updated": - Services.obs.notifyObservers(null, "content-blocklist-updated", null); - break; - default: - throw new Error("Unknown blocklist message received from content: " + aMsg.name); - } - return undefined; - }, - /* See nsIBlocklistService */ - isAddonBlocklisted: function(addon, appVersion, toolkitVersion) { + isAddonBlocklisted: function Blocklist_isAddonBlocklisted(addon, appVersion, toolkitVersion) { return this.getAddonBlocklistState(addon, appVersion, toolkitVersion) == Ci.nsIBlocklistService.STATE_BLOCKED; }, /* See nsIBlocklistService */ - getAddonBlocklistState: function(addon, appVersion, toolkitVersion) { + getAddonBlocklistState: function Blocklist_getAddonBlocklistState(addon, appVersion, toolkitVersion) { if (!this._isBlocklistLoaded()) this._loadBlocklist(); return this._getAddonBlocklistState(addon, this._addonEntries, @@ -416,14 +391,11 @@ Blocklist.prototype = { * @returns The blocklist state for the item, one of the STATE constants as * defined in nsIBlocklistService. */ - _getAddonBlocklistState: function(addon, addonEntries, appVersion, toolkitVersion) { + _getAddonBlocklistState: function Blocklist_getAddonBlocklistStateCall(addon, + addonEntries, appVersion, toolkitVersion) { if (!gBlocklistEnabled) return Ci.nsIBlocklistService.STATE_NOT_BLOCKED; - // Not all applications implement nsIXULAppInfo (e.g. xpcshell doesn't). - if (!appVersion && !gApp.version) - return Ci.nsIBlocklistService.STATE_NOT_BLOCKED; - if (!appVersion) appVersion = gApp.version; if (!toolkitVersion) @@ -447,12 +419,13 @@ Blocklist.prototype = { * @param addon * The add-on whose to-be-reset prefs are to be found. */ - _getAddonPrefs: function(addon) { + _getAddonPrefs: function Blocklist_getAddonPrefs(addon) { let entry = this._findMatchingAddonEntry(this._addonEntries, addon); return entry.prefs.slice(0); }, - _findMatchingAddonEntry: function(aAddonEntries, aAddon) { + _findMatchingAddonEntry: function Blocklist_findMatchingAddonEntry(aAddonEntries, + aAddon) { if (!aAddon) return null; // Returns true if the params object passes the constraints set by entry. @@ -492,7 +465,7 @@ Blocklist.prototype = { }, /* See nsIBlocklistService */ - getAddonBlocklistURL: function(addon, appVersion, toolkitVersion) { + getAddonBlocklistURL: function Blocklist_getAddonBlocklistURL(addon, appVersion, toolkitVersion) { if (!gBlocklistEnabled) return ""; @@ -506,14 +479,14 @@ Blocklist.prototype = { return this._createBlocklistURL(blItem.blockID); }, - _createBlocklistURL: function(id) { + _createBlocklistURL: function Blocklist_createBlocklistURL(id) { let url = Services.urlFormatter.formatURLPref(PREF_BLOCKLIST_ITEM_URL); url = url.replace(/%blockID%/g, id); return url; }, - notify: function(aTimer) { + notify: function Blocklist_notify(aTimer) { if (!gBlocklistEnabled) return; @@ -556,18 +529,14 @@ Blocklist.prototype = { pingCountTotal = 1; dsURI = dsURI.replace(/%APP_ID%/g, gApp.ID); - // Not all applications implement nsIXULAppInfo (e.g. xpcshell doesn't). - if (gApp.version) - dsURI = dsURI.replace(/%APP_VERSION%/g, gApp.version); + dsURI = dsURI.replace(/%APP_VERSION%/g, gApp.version); dsURI = dsURI.replace(/%PRODUCT%/g, gApp.name); - // Not all applications implement nsIXULAppInfo (e.g. xpcshell doesn't). - if (gApp.version) - dsURI = dsURI.replace(/%VERSION%/g, gApp.version); + dsURI = dsURI.replace(/%VERSION%/g, gApp.version); dsURI = dsURI.replace(/%BUILD_ID%/g, gApp.appBuildID); dsURI = dsURI.replace(/%BUILD_TARGET%/g, gApp.OS + "_" + gABI); dsURI = dsURI.replace(/%OS_VERSION%/g, gOSVersion); dsURI = dsURI.replace(/%LOCALE%/g, getLocale()); - dsURI = dsURI.replace(/%CHANNEL%/g, UpdateUtils.UpdateChannel); + dsURI = dsURI.replace(/%CHANNEL%/g, UpdateChannel.get()); dsURI = dsURI.replace(/%PLATFORM_VERSION%/g, gApp.platformVersion); dsURI = dsURI.replace(/%DISTRIBUTION%/g, getDistributionPrefValue(PREF_APP_DISTRIBUTION)); @@ -612,15 +581,19 @@ Blocklist.prototype = { } LOG("Blocklist::notify: Requesting " + uri.spec); - let request = new ServiceRequest(); + var request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]. + createInstance(Ci.nsIXMLHttpRequest); request.open("GET", uri.spec, true); request.channel.notificationCallbacks = new gCertUtils.BadCertHandler(); request.overrideMimeType("text/xml"); request.setRequestHeader("Cache-Control", "no-cache"); request.QueryInterface(Components.interfaces.nsIJSXMLHttpRequest); - request.addEventListener("error", event => this.onXMLError(event), false); - request.addEventListener("load", event => this.onXMLLoad(event), false); + var self = this; + request.addEventListener("error", function errorEventListener(event) { + self.onXMLError(event); }, false); + request.addEventListener("load", function loadEventListener(event) { + self.onXMLLoad(event); }, false); request.send(null); // When the blocklist loads we need to compare it to the current copy so @@ -629,7 +602,7 @@ Blocklist.prototype = { this._loadBlocklist(); }, - onXMLLoad: Task.async(function*(aEvent) { + onXMLLoad: Task.async(function* (aEvent) { let request = aEvent.target; try { gCertUtils.checkCert(request.channel); @@ -648,12 +621,9 @@ Blocklist.prototype = { var oldAddonEntries = this._addonEntries; var oldPluginEntries = this._pluginEntries; this._addonEntries = []; - this._gfxEntries = []; this._pluginEntries = []; this._loadBlocklistFromString(request.responseText); - // We don't inform the users when the graphics blocklist changed at runtime. - // However addons and plugins blocking status is refreshed. this._blocklistUpdated(oldAddonEntries, oldPluginEntries); try { @@ -664,7 +634,7 @@ Blocklist.prototype = { } }), - onXMLError: function(aEvent) { + onXMLError: function Blocklist_onXMLError(aEvent) { try { var request = aEvent.target; // the following may throw (e.g. a local file or timeout) @@ -690,9 +660,8 @@ Blocklist.prototype = { * Finds the newest blocklist file from the application and the profile and * load it or does nothing if neither exist. */ - _loadBlocklist: function() { + _loadBlocklist: function Blocklist_loadBlocklist() { this._addonEntries = []; - this._gfxEntries = []; this._pluginEntries = []; var profFile = FileUtils.getFile(KEY_PROFILEDIR, [FILE_BLOCKLIST]); if (profFile.exists()) { @@ -718,7 +687,7 @@ Blocklist.prototype = { # <pref>accessibility.blockautorefresh</pref> # </prefs> # <versionRange minVersion="1.0" maxVersion="2.0.*"> -# <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> +# <targetApplication id="{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}"> # <versionRange minVersion="1.5" maxVersion="1.5.*"/> # <versionRange minVersion="1.7" maxVersion="1.7.*"/> # </targetApplication> @@ -727,7 +696,7 @@ Blocklist.prototype = { # </targetApplication> # </versionRange> # <versionRange minVersion="3.0" maxVersion="3.0.*"> -# <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> +# <targetApplication id="{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}"> # <versionRange minVersion="1.5" maxVersion="1.5.*"/> # </targetApplication> # <targetApplication id="toolkit@mozilla.org"> @@ -740,7 +709,7 @@ Blocklist.prototype = { # </emItem> # <emItem id="item_3@domain"> # <versionRange> -# <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> +# <targetApplication id="{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}"> # <versionRange minVersion="1.5" maxVersion="1.5.*"/> # </targetApplication> # </versionRange> @@ -766,14 +735,11 @@ Blocklist.prototype = { # <!-- ... as is the serial number DER data --> # <serialNumber>AkHVNA==</serialNumber> # </certItem> -# <!-- subject is the DER subject name data base64 encoded... --> -# <certItem subject="MA0xCzAJBgNVBAMMAmNh" pubKeyHash="/xeHA5s+i9/z9d8qy6JEuE1xGoRYIwgJuTE/lmaGJ7M="> -# </certItem> # </certItems> # </blocklist> */ - _loadBlocklistFromFile: function(file) { + _loadBlocklistFromFile: function Blocklist_loadBlocklistFromFile(file) { if (!gBlocklistEnabled) { LOG("Blocklist::_loadBlocklistFromFile: blocklist is disabled"); return; @@ -829,7 +795,7 @@ Blocklist.prototype = { }, _isBlocklistLoaded: function() { - return this._addonEntries != null && this._gfxEntries != null && this._pluginEntries != null; + return this._addonEntries != null && this._pluginEntries != null; }, _isBlocklistPreloaded: function() { @@ -839,7 +805,6 @@ Blocklist.prototype = { /* Used for testing */ _clear: function() { this._addonEntries = null; - this._gfxEntries = null; this._pluginEntries = null; this._preloadedBlocklistContent = null; }, @@ -854,7 +819,7 @@ Blocklist.prototype = { } var appFile = FileUtils.getFile(KEY_APPDIR, [FILE_BLOCKLIST]); - try { + try{ yield this._preloadBlocklistFile(appFile.path); return; } catch (e) { @@ -864,7 +829,7 @@ Blocklist.prototype = { LOG("Blocklist::_preloadBlocklist: no XML File found"); }), - _preloadBlocklistFile: Task.async(function*(path) { + _preloadBlocklistFile: Task.async(function* (path){ if (this._addonEntries) { // The file has been already loaded. return; @@ -883,7 +848,7 @@ Blocklist.prototype = { } }), - _loadBlocklistFromString : function(text) { + _loadBlocklistFromString : function Blocklist_loadBlocklistFromString(text) { try { var parser = Cc["@mozilla.org/xmlextras/domparser;1"]. createInstance(Ci.nsIDOMParser); @@ -895,46 +860,30 @@ Blocklist.prototype = { return; } - var populateCertBlocklist = getPref("getBoolPref", PREF_ONECRL_VIA_AMO, true); - var childNodes = doc.documentElement.childNodes; for (let element of childNodes) { if (!(element instanceof Ci.nsIDOMElement)) continue; switch (element.localName) { case "emItems": - this._addonEntries = this._processItemNodes(element.childNodes, "emItem", + this._addonEntries = this._processItemNodes(element.childNodes, "em", this._handleEmItemNode); break; case "pluginItems": - // We don't support plugins on b2g. - if (AppConstants.MOZ_B2G) { - return; - } - this._pluginEntries = this._processItemNodes(element.childNodes, "pluginItem", + this._pluginEntries = this._processItemNodes(element.childNodes, "plugin", this._handlePluginItemNode); break; case "certItems": - if (populateCertBlocklist) { - this._processItemNodes(element.childNodes, "certItem", - this._handleCertItemNode.bind(this)); - } - break; - case "gfxItems": - // Parse as simple list of objects. - this._gfxEntries = this._processItemNodes(element.childNodes, "gfxBlacklistEntry", - this._handleGfxBlacklistNode); + this._processItemNodes(element.childNodes, "cert", + this._handleCertItemNode.bind(this)); break; default: - LOG("Blocklist::_loadBlocklistFromString: ignored entries " + element.localName); + Services.obs.notifyObservers(element, + "blocklist-data-" + element.localName, + null); } } - if (populateCertBlocklist) { - gCertBlocklistService.saveEntries(); - } - if (this._gfxEntries.length > 0) { - this._notifyObserversBlocklistGFX(); - } + gCertBlocklistService.saveEntries(); } catch (e) { LOG("Blocklist::_loadBlocklistFromFile: Error constructing blocklist " + e); @@ -942,8 +891,9 @@ Blocklist.prototype = { } }, - _processItemNodes: function(itemNodes, itemName, handler) { + _processItemNodes: function Blocklist_processItemNodes(itemNodes, prefix, handler) { var result = []; + var itemName = prefix + "Item"; for (var i = 0; i < itemNodes.length; ++i) { var blocklistElement = itemNodes.item(i); if (!(blocklistElement instanceof Ci.nsIDOMElement) || @@ -955,34 +905,21 @@ Blocklist.prototype = { return result; }, - _handleCertItemNode: function(blocklistElement, result) { + _handleCertItemNode: function Blocklist_handleCertItemNode(blocklistElement, + result) { let issuer = blocklistElement.getAttribute("issuerName"); - if (issuer) { - for (let snElement of blocklistElement.children) { - try { - gCertBlocklistService.revokeCertByIssuerAndSerial(issuer, snElement.textContent); - } catch (e) { - // we want to keep trying other elements since missing all items - // is worse than missing one - LOG("Blocklist::_handleCertItemNode: Error adding revoked cert by Issuer and Serial" + e); - } - } - return; - } - - let pubKeyHash = blocklistElement.getAttribute("pubKeyHash"); - let subject = blocklistElement.getAttribute("subject"); - - if (pubKeyHash && subject) { + for (let snElement of blocklistElement.children) { try { - gCertBlocklistService.revokeCertBySubjectAndPubKey(subject, pubKeyHash); + gCertBlocklistService.revokeCertByIssuerAndSerial(issuer, snElement.textContent); } catch (e) { - LOG("Blocklist::_handleCertItemNode: Error adding revoked cert by Subject and PubKey" + e); + // we want to keep trying other elements since missing all items + // is worse than missing one + LOG("Blocklist::_handleCertItemNode: Error adding revoked cert " + e); } } }, - _handleEmItemNode: function(blocklistElement, result) { + _handleEmItemNode: function Blocklist_handleEmItemNode(blocklistElement, result) { if (!matchesOSABI(blocklistElement)) return; @@ -1035,7 +972,7 @@ Blocklist.prototype = { result.push(blockEntry); }, - _handlePluginItemNode: function(blocklistElement, result) { + _handlePluginItemNode: function Blocklist_handlePluginItemNode(blocklistElement, result) { if (!matchesOSABI(blocklistElement)) return; @@ -1080,81 +1017,9 @@ Blocklist.prototype = { result.push(blockEntry); }, - // <gfxBlacklistEntry blockID="g60"> - // <os>WINNT 6.0</os> - // <osversion>14</osversion> currently only used for Android - // <versionRange minVersion="42.0" maxVersion="13.0b2"/> - // <vendor>0x8086</vendor> - // <devices> - // <device>0x2582</device> - // <device>0x2782</device> - // </devices> - // <feature> DIRECT3D_10_LAYERS </feature> - // <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - // <driverVersion> 8.52.322.2202 </driverVersion> - // <driverVersionMax> 8.52.322.2202 </driverVersionMax> - // <driverVersionComparator> LESS_THAN_OR_EQUAL </driverVersionComparator> - // <model>foo</model> - // <product>foo</product> - // <manufacturer>foo</manufacturer> - // <hardware>foo</hardware> - // </gfxBlacklistEntry> - _handleGfxBlacklistNode: function (blocklistElement, result) { - const blockEntry = {}; - - // The blockID attribute is always present in the actual data produced on server - // (see https://github.com/mozilla/addons-server/blob/2016.05.05/src/olympia/blocklist/templates/blocklist/blocklist.xml#L74) - // But it is sometimes missing in test fixtures. - if (blocklistElement.hasAttribute("blockID")) { - blockEntry.blockID = blocklistElement.getAttribute("blockID"); - } - - // Trim helper (spaces, tabs, no-break spaces..) - const trim = (s) => (s || '').replace(/(^[\s\uFEFF\xA0]+)|([\s\uFEFF\xA0]+$)/g, ""); - - for (let i = 0; i < blocklistElement.childNodes.length; ++i) { - var matchElement = blocklistElement.childNodes.item(i); - if (!(matchElement instanceof Ci.nsIDOMElement)) - continue; - - let value; - if (matchElement.localName == "devices") { - value = []; - for (let j = 0; j < matchElement.childNodes.length; j++) { - const childElement = matchElement.childNodes.item(j); - const childValue = trim(childElement.textContent); - // Make sure no empty value is added. - if (childValue) { - if (/,/.test(childValue)) { - // Devices can't contain comma. - // (c.f serialization in _notifyObserversBlocklistGFX) - const e = new Error(`Unsupported device name ${childValue}`); - Components.utils.reportError(e); - } - else { - value.push(childValue); - } - } - } - } else if (matchElement.localName == "versionRange") { - value = {minVersion: trim(matchElement.getAttribute("minVersion")) || "0", - maxVersion: trim(matchElement.getAttribute("maxVersion")) || "*"}; - } else { - value = trim(matchElement.textContent); - } - if (value) { - blockEntry[matchElement.localName] = value; - } - } - result.push(blockEntry); - }, - /* See nsIBlocklistService */ - getPluginBlocklistState: function(plugin, appVersion, toolkitVersion) { - if (AppConstants.platform == "android" || - AppConstants.MOZ_B2G) { - return Ci.nsIBlocklistService.STATE_NOT_BLOCKED; - } + getPluginBlocklistState: function Blocklist_getPluginBlocklistState(plugin, + appVersion, toolkitVersion) { if (!this._isBlocklistLoaded()) this._loadBlocklist(); return this._getPluginBlocklistState(plugin, this._pluginEntries, @@ -1162,8 +1027,8 @@ Blocklist.prototype = { }, /** - * Private helper to get the blocklist entry for a plugin given a set of - * blocklist entries and versions. + * Private version of getPluginBlocklistState that allows the caller to pass in + * the plugin blocklist entries. * * @param plugin * The nsIPluginTag to get the blocklist state for. @@ -1175,15 +1040,12 @@ Blocklist.prototype = { * @param toolkitVersion * The toolkit version to compare to, will use the current version if * null. - * @returns {entry: blocklistEntry, version: blocklistEntryVersion}, - * or null if there is no matching entry. + * @returns The blocklist state for the item, one of the STATE constants as + * defined in nsIBlocklistService. */ - _getPluginBlocklistEntry: function(plugin, pluginEntries, appVersion, toolkitVersion) { + _getPluginBlocklistState: function Blocklist_getPluginBlocklistState(plugin, + pluginEntries, appVersion, toolkitVersion) { if (!gBlocklistEnabled) - return null; - - // Not all applications implement nsIXULAppInfo (e.g. xpcshell doesn't). - if (!appVersion && !gApp.version) return Ci.nsIBlocklistService.STATE_NOT_BLOCKED; if (!appVersion) @@ -1191,7 +1053,7 @@ Blocklist.prototype = { if (!toolkitVersion) toolkitVersion = gApp.platformVersion; - for (var blockEntry of pluginEntries) { + for each (var blockEntry in pluginEntries) { var matchFailed = false; for (var name in blockEntry.matches) { if (!(name in plugin) || @@ -1207,66 +1069,52 @@ Blocklist.prototype = { for (let blockEntryVersion of blockEntry.versions) { if (blockEntryVersion.includesItem(plugin.version, appVersion, - toolkitVersion)) { - return {entry: blockEntry, version: blockEntryVersion}; + toolkitVersion)) { + if (blockEntryVersion.severity >= gBlocklistLevel) + return Ci.nsIBlocklistService.STATE_BLOCKED; + if (blockEntryVersion.severity == SEVERITY_OUTDATED) { + let vulnerabilityStatus = blockEntryVersion.vulnerabilityStatus; + if (vulnerabilityStatus == VULNERABILITYSTATUS_UPDATE_AVAILABLE) + return Ci.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE; + if (vulnerabilityStatus == VULNERABILITYSTATUS_NO_UPDATE) + return Ci.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE; + return Ci.nsIBlocklistService.STATE_OUTDATED; + } + return Ci.nsIBlocklistService.STATE_SOFTBLOCKED; } } } - return null; + return Ci.nsIBlocklistService.STATE_NOT_BLOCKED; }, /** - * Private version of getPluginBlocklistState that allows the caller to pass in - * the plugin blocklist entries. - * - * @param plugin - * The nsIPluginTag to get the blocklist state for. - * @param pluginEntries - * The plugin blocklist entries to compare against. - * @param appVersion - * The application version to compare to, will use the current - * version if null. - * @param toolkitVersion - * The toolkit version to compare to, will use the current version if - * null. - * @returns The blocklist state for the item, one of the STATE constants as - * defined in nsIBlocklistService. + * Get the matching blocklist entry for the passed plugin, if + * available. + * @param plugin The plugin to find the block entry for. + * @returns The block entry which matches the passed plugin, null + * otherwise. */ - _getPluginBlocklistState: function(plugin, pluginEntries, appVersion, toolkitVersion) { + _getPluginBlockEntry: function (plugin) { + if (!gBlocklistEnabled) + return null; - let r = this._getPluginBlocklistEntry(plugin, pluginEntries, - appVersion, toolkitVersion); - if (!r) { - return Ci.nsIBlocklistService.STATE_NOT_BLOCKED; - } + if (!this._isBlocklistLoaded()) + this._loadBlocklist(); - let {entry: blockEntry, version: blockEntryVersion} = r; - - if (blockEntryVersion.severity >= gBlocklistLevel) - return Ci.nsIBlocklistService.STATE_BLOCKED; - if (blockEntryVersion.severity == SEVERITY_OUTDATED) { - let vulnerabilityStatus = blockEntryVersion.vulnerabilityStatus; - if (vulnerabilityStatus == VULNERABILITYSTATUS_UPDATE_AVAILABLE) - return Ci.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE; - if (vulnerabilityStatus == VULNERABILITYSTATUS_NO_UPDATE) - return Ci.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE; - return Ci.nsIBlocklistService.STATE_OUTDATED; + for each (let blockEntry in this._pluginEntries) { + if (matchesAllPluginNames(blockEntry, plugin)) { + return blockEntry; + } } - return Ci.nsIBlocklistService.STATE_SOFTBLOCKED; + + return null; }, /* See nsIBlocklistService */ - getPluginBlocklistURL: function(plugin) { - if (!this._isBlocklistLoaded()) - this._loadBlocklist(); - - let r = this._getPluginBlocklistEntry(plugin, this._pluginEntries); - if (!r) { - return null; - } - let {entry: blockEntry, version: blockEntryVersion} = r; - if (!blockEntry.blockID) { + getPluginBlocklistURL: function Blocklist_getPluginBlocklistURL(plugin) { + let blockEntry = this._getPluginBlockEntry(plugin); + if (!blockEntry || !blockEntry.blockID) { return null; } @@ -1274,50 +1122,16 @@ Blocklist.prototype = { }, /* See nsIBlocklistService */ - getPluginInfoURL: function(plugin) { - if (!this._isBlocklistLoaded()) - this._loadBlocklist(); - - let r = this._getPluginBlocklistEntry(plugin, this._pluginEntries); - if (!r) { - return null; - } - let {entry: blockEntry, version: blockEntryVersion} = r; - if (!blockEntry.blockID) { + getPluginInfoURL: function (plugin) { + let blockEntry = this._getPluginBlockEntry(plugin); + if (!blockEntry || !blockEntry.blockID) { return null; } return blockEntry.infoURL; }, - _notifyObserversBlocklistGFX: function () { - // Notify `GfxInfoBase`, by passing a string serialization. - // This way we avoid spreading XML structure logics there. - const payload = this._gfxEntries.map((r) => { - return Object.keys(r).sort().filter((k) => !/id|last_modified/.test(k)).map((key) => { - let value = r[key]; - if (Array.isArray(value)) { - value = value.join(","); - } else if (value.hasOwnProperty("minVersion")) { - // When XML is parsed, both minVersion and maxVersion are set. - value = `${value.minVersion},${value.maxVersion}`; - } - return `${key}:${value}`; - }).join("\t"); - }).join("\n"); - Services.obs.notifyObservers(null, "blocklist-data-gfxItems", payload); - }, - - _notifyObserversBlocklistUpdated: function() { - Services.obs.notifyObservers(this, "blocklist-updated", ""); - Services.ppmm.broadcastAsyncMessage("Blocklist:blocklistInvalidated", {}); - }, - - _blocklistUpdated: function(oldAddonEntries, oldPluginEntries) { - if (AppConstants.MOZ_B2G) { - return; - } - + _blocklistUpdated: function Blocklist_blocklistUpdated(oldAddonEntries, oldPluginEntries) { var addonList = []; // A helper function that reverts the prefs passed to default values. @@ -1325,13 +1139,15 @@ Blocklist.prototype = { for (let pref of prefs) gPref.clearUserPref(pref); } + var self = this; const types = ["extension", "theme", "locale", "dictionary", "service"]; - AddonManager.getAddonsByTypes(types, addons => { + AddonManager.getAddonsByTypes(types, function blocklistUpdated_getAddonsByTypes(addons) { + for (let addon of addons) { let oldState = Ci.nsIBlocklistService.STATE_NOTBLOCKED; if (oldAddonEntries) - oldState = this._getAddonBlocklistState(addon, oldAddonEntries); - let state = this.getAddonBlocklistState(addon); + oldState = self._getAddonBlocklistState(addon, oldAddonEntries); + let state = self.getAddonBlocklistState(addon); LOG("Blocklist state for " + addon.id + " changed from " + oldState + " to " + state); @@ -1342,7 +1158,7 @@ Blocklist.prototype = { if (state === Ci.nsIBlocklistService.STATE_BLOCKED) { // It's a hard block. We must reset certain preferences. - let prefs = this._getAddonPrefs(addon); + let prefs = self._getAddonPrefs(addon); resetPrefs(prefs); } @@ -1364,15 +1180,8 @@ Blocklist.prototype = { // If the add-on is already disabled for some reason then don't warn // about it - if (!addon.isActive) { - // But mark it as softblocked if necessary. Note that we avoid setting - // softDisabled at the same time as userDisabled to make it clear - // which was the original cause of the add-on becoming disabled in a - // way that the user can change. - if (state == Ci.nsIBlocklistService.STATE_SOFTBLOCKED && !addon.userDisabled) - addon.softDisabled = true; + if (!addon.isActive) continue; - } addonList.push({ name: addon.name, @@ -1381,7 +1190,7 @@ Blocklist.prototype = { disable: false, blocked: state == Ci.nsIBlocklistService.STATE_BLOCKED, item: addon, - url: this.getAddonBlocklistURL(addon), + url: self.getAddonBlocklistURL(addon), }); } @@ -1394,8 +1203,8 @@ Blocklist.prototype = { for (let plugin of plugins) { let oldState = -1; if (oldPluginEntries) - oldState = this._getPluginBlocklistState(plugin, oldPluginEntries); - let state = this.getPluginBlocklistState(plugin); + oldState = self._getPluginBlocklistState(plugin, oldPluginEntries); + let state = self.getPluginBlocklistState(plugin); LOG("Blocklist state for " + plugin.name + " changed from " + oldState + " to " + state); // We don't want to re-warn about items @@ -1407,9 +1216,11 @@ Blocklist.prototype = { plugin.enabledState = Ci.nsIPluginTag.STATE_DISABLED; } else if (!plugin.disabled && state != Ci.nsIBlocklistService.STATE_NOT_BLOCKED) { - if (state != Ci.nsIBlocklistService.STATE_OUTDATED && - state != Ci.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE && - state != Ci.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE) { + if (state == Ci.nsIBlocklistService.STATE_OUTDATED) { + gPref.setBoolPref(PREF_PLUGINS_NOTIFYUSER, true); + } + else if (state != Ci.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE && + state != Ci.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE) { addonList.push({ name: plugin.name, version: plugin.version, @@ -1417,14 +1228,14 @@ Blocklist.prototype = { disable: false, blocked: state == Ci.nsIBlocklistService.STATE_BLOCKED, item: plugin, - url: this.getPluginBlocklistURL(plugin), + url: self.getPluginBlocklistURL(plugin), }); } } } if (addonList.length == 0) { - this._notifyObserversBlocklistUpdated(); + Services.obs.notifyObservers(self, "blocklist-updated", ""); return; } @@ -1436,7 +1247,7 @@ Blocklist.prototype = { } catch (e) { LOG(e); } - this._notifyObserversBlocklistUpdated(); + Services.obs.notifyObservers(self, "blocklist-updated", ""); return; } @@ -1451,7 +1262,7 @@ Blocklist.prototype = { Some tests run without UI, so the async code listens to a message that can be sent programatically */ - let applyBlocklistChanges = () => { + let applyBlocklistChanges = function blocklistUpdated_applyBlocklistChanges() { for (let addon of addonList) { if (!addon.disable) continue; @@ -1462,7 +1273,7 @@ Blocklist.prototype = { // This add-on is softblocked. addon.item.softDisabled = true; // We must revert certain prefs. - let prefs = this._getAddonPrefs(addon.item); + let prefs = self._getAddonPrefs(addon.item); resetPrefs(prefs); } } @@ -1470,7 +1281,7 @@ Blocklist.prototype = { if (args.restart) restartApp(); - this._notifyObserversBlocklistUpdated(); + Services.obs.notifyObservers(self, "blocklist-updated", ""); Services.obs.removeObserver(applyBlocklistChanges, "addon-blocklist-closed"); } @@ -1552,7 +1363,7 @@ BlocklistItemData.prototype = { * @returns True if the version range covers the item version and application * or toolkit version. */ - includesItem: function(version, appVersion, toolkitVersion) { + includesItem: function BlocklistItemData_includesItem(version, appVersion, toolkitVersion) { // Some platforms have no version for plugins, these don't match if there // was a min/maxVersion provided if (!version && (this.minVersion || this.maxVersion)) @@ -1582,7 +1393,7 @@ BlocklistItemData.prototype = { * The maximum version. If null it is assumed that version is always * smaller. */ - matchesRange: function(version, minVersion, maxVersion) { + matchesRange: function BlocklistItemData_matchesRange(version, minVersion, maxVersion) { if (minVersion && gVersionChecker.compare(version, minVersion) < 0) return false; if (maxVersion && gVersionChecker.compare(version, maxVersion) > 0) @@ -1599,7 +1410,7 @@ BlocklistItemData.prototype = { * The version of the application to test for. * @returns True if this version range covers the application version given. */ - matchesTargetRange: function(appID, appVersion) { + matchesTargetRange: function BlocklistItemData_matchesTargetRange(appID, appVersion) { var blTargetApp = this.targetApps[appID]; if (!blTargetApp) return false; @@ -1621,7 +1432,7 @@ BlocklistItemData.prototype = { * "minVersion" The minimum version in a version range (default = null). * "maxVersion" The maximum version in a version range (default = null). */ - getBlocklistAppVersions: function(targetAppElement) { + getBlocklistAppVersions: function BlocklistItemData_getBlocklistAppVersions(targetAppElement) { var appVersions = [ ]; if (targetAppElement) { @@ -1649,7 +1460,7 @@ BlocklistItemData.prototype = { * "minVersion" The minimum version in a version range (default = null). * "maxVersion" The maximum version in a version range (default = null). */ - getBlocklistVersionRange: function(versionRangeElement) { + getBlocklistVersionRange: function BlocklistItemData_getBlocklistVersionRange(versionRangeElement) { var minVersion = null; var maxVersion = null; if (!versionRangeElement) diff --git a/toolkit/mozapps/extensions/nsBlocklistServiceContent.js b/toolkit/mozapps/extensions/nsBlocklistServiceContent.js deleted file mode 100644 index 1752924b5..000000000 --- a/toolkit/mozapps/extensions/nsBlocklistServiceContent.js +++ /dev/null @@ -1,113 +0,0 @@ -/* 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/. */ - -"use strict"; - -const Cc = Components.classes; -const Ci = Components.interfaces; -const Cr = Components.results; - -Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); -Components.utils.import("resource://gre/modules/Services.jsm"); - -const kMissingAPIMessage = "Unsupported blocklist call in the child process." - -/* - * A lightweight blocklist proxy for the content process that traps plugin - * related blocklist checks and forwards them to the parent. This interface is - * primarily designed to insure overlays work.. it does not control plugin - * or addon loading. - */ - -function Blocklist() { - this.init(); -} - -Blocklist.prototype = { - classID: Components.ID("{e0a106ed-6ad4-47a4-b6af-2f1c8aa4712d}"), - - QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, - Ci.nsIBlocklistService]), - - init: function() { - Services.cpmm.addMessageListener("Blocklist:blocklistInvalidated", this); - Services.obs.addObserver(this, "xpcom-shutdown", false); - }, - - uninit: function() { - Services.cpmm.removeMessageListener("Blocklist:blocklistInvalidated", this); - Services.obs.removeObserver(this, "xpcom-shutdown", false); - }, - - observe: function(aSubject, aTopic, aData) { - switch (aTopic) { - case "xpcom-shutdown": - this.uninit(); - break; - } - }, - - // Message manager message handlers - receiveMessage: function(aMsg) { - switch (aMsg.name) { - case "Blocklist:blocklistInvalidated": - Services.obs.notifyObservers(null, "blocklist-updated", null); - Services.cpmm.sendAsyncMessage("Blocklist:content-blocklist-updated"); - break; - default: - throw new Error("Unknown blocklist message received from content: " + aMsg.name); - } - }, - - /* - * A helper that queries key data from a plugin or addon object - * and generates a simple data wrapper suitable for ipc. We hand - * these directly to the nsBlockListService in the parent which - * doesn't query for much.. allowing us to get away with this. - */ - flattenObject: function(aTag) { - // Based on debugging the nsBlocklistService, these are the props the - // parent side will check on our objects. - let props = ["name", "description", "filename", "version"]; - let dataWrapper = {}; - for (let prop of props) { - dataWrapper[prop] = aTag[prop]; - } - return dataWrapper; - }, - - // We support the addon methods here for completeness, but content currently - // only calls getPluginBlocklistState. - - isAddonBlocklisted: function(aAddon, aAppVersion, aToolkitVersion) { - return true; - }, - - getAddonBlocklistState: function(aAddon, aAppVersion, aToolkitVersion) { - return Components.interfaces.nsIBlocklistService.STATE_BLOCKED; - }, - - // There are a few callers in layout that rely on this. - getPluginBlocklistState: function(aPluginTag, aAppVersion, aToolkitVersion) { - return Services.cpmm.sendSyncMessage("Blocklist:getPluginBlocklistState", { - addonData: this.flattenObject(aPluginTag), - appVersion: aAppVersion, - toolkitVersion: aToolkitVersion - })[0]; - }, - - getAddonBlocklistURL: function(aAddon, aAppVersion, aToolkitVersion) { - throw new Error(kMissingAPIMessage); - }, - - getPluginBlocklistURL: function(aPluginTag) { - throw new Error(kMissingAPIMessage); - }, - - getPluginInfoURL: function(aPluginTag) { - throw new Error(kMissingAPIMessage); - } -}; - -this.NSGetFactory = XPCOMUtils.generateNSGetFactory([Blocklist]); diff --git a/toolkit/mozapps/extensions/test/AddonManagerTesting.jsm b/toolkit/mozapps/extensions/test/AddonManagerTesting.jsm index eb9a92195..52c954b1a 100644 --- a/toolkit/mozapps/extensions/test/AddonManagerTesting.jsm +++ b/toolkit/mozapps/extensions/test/AddonManagerTesting.jsm @@ -8,7 +8,7 @@ "use strict"; this.EXPORTED_SYMBOLS = [ - "AddonManagerTesting", + "AddonTestUtils", ]; const {utils: Cu} = Components; @@ -19,17 +19,7 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "AddonManager", "resource://gre/modules/AddonManager.jsm"); -this.AddonManagerTesting = { - /** - * Get the add-on that is specified by its ID. - * - * @return {Promise<Object>} A promise that resolves returning the found addon or null - * if it is not found. - */ - getAddonById: function (id) { - return new Promise(resolve => AddonManager.getAddonByID(id, addon => resolve(addon))); - }, - +this.AddonTestUtils = { /** * Uninstall an add-on that is specified by its ID. * diff --git a/toolkit/mozapps/extensions/test/addons/bootstrap_globals/bootstrap.js b/toolkit/mozapps/extensions/test/addons/bootstrap_globals/bootstrap.js index a5d5beb34..f8a62bcaa 100644 --- a/toolkit/mozapps/extensions/test/addons/bootstrap_globals/bootstrap.js +++ b/toolkit/mozapps/extensions/test/addons/bootstrap_globals/bootstrap.js @@ -1,13 +1,13 @@ Components.utils.import("resource://gre/modules/Services.jsm"); -var seenGlobals = new Set(); -var scope = this; +let seenGlobals = new Set(); +let scope = this; function checkGlobal(name, type) { if (scope[name] && typeof(scope[name]) == type) seenGlobals.add(name); } -var wrapped = {}; +let wrapped = {}; Services.obs.notifyObservers({ wrappedJSObject: wrapped }, "bootstrap-request-globals", null); for (let [name, type] of wrapped.expectedGlobals) { checkGlobal(name, type); diff --git a/toolkit/mozapps/extensions/test/addons/test_bootstrap1_1/bootstrap.js b/toolkit/mozapps/extensions/test/addons/test_bootstrap1_1/bootstrap.js index 1666f2972..eba6762c8 100644 --- a/toolkit/mozapps/extensions/test/addons/test_bootstrap1_1/bootstrap.js +++ b/toolkit/mozapps/extensions/test/addons/test_bootstrap1_1/bootstrap.js @@ -1 +1,32 @@ -Components.utils.import("resource://xpcshell-data/BootstrapMonitor.jsm").monitor(this); +Components.utils.import("resource://gre/modules/Services.jsm"); + +// Test steps chain from pref observers on *_reason, +// so always set that last +function install(data, reason) { + Components.utils.import(data.resourceURI.spec + "version.jsm"); + Services.prefs.setIntPref("bootstraptest.installed_version", VERSION); + Services.prefs.setIntPref("bootstraptest.install_oldversion", data.oldVersion); + Components.utils.unload(data.resourceURI.spec + "version.jsm"); + Services.prefs.setIntPref("bootstraptest.install_reason", reason); +} + +function startup(data, reason) { + Components.utils.reportError("bootstrap startup"); + Components.utils.import(data.resourceURI.spec + "version.jsm"); + Services.prefs.setIntPref("bootstraptest.active_version", VERSION); + Services.prefs.setIntPref("bootstraptest.startup_oldversion", data.oldVersion); + Components.utils.unload(data.resourceURI.spec + "version.jsm"); + Services.prefs.setIntPref("bootstraptest.startup_reason", reason); +} + +function shutdown(data, reason) { + Services.prefs.setIntPref("bootstraptest.active_version", 0); + Services.prefs.setIntPref("bootstraptest.shutdown_newversion", data.newVersion); + Services.prefs.setIntPref("bootstraptest.shutdown_reason", reason); +} + +function uninstall(data, reason) { + Services.prefs.setIntPref("bootstraptest.installed_version", 0); + Services.prefs.setIntPref("bootstraptest.uninstall_newversion", data.newVersion); + Services.prefs.setIntPref("bootstraptest.uninstall_reason", reason); +} diff --git a/toolkit/mozapps/extensions/test/addons/test_bootstrap1_2/bootstrap.js b/toolkit/mozapps/extensions/test/addons/test_bootstrap1_2/bootstrap.js index 1666f2972..8839bfb7d 100644 --- a/toolkit/mozapps/extensions/test/addons/test_bootstrap1_2/bootstrap.js +++ b/toolkit/mozapps/extensions/test/addons/test_bootstrap1_2/bootstrap.js @@ -1 +1,31 @@ -Components.utils.import("resource://xpcshell-data/BootstrapMonitor.jsm").monitor(this); +Components.utils.import("resource://gre/modules/Services.jsm"); + +// Test steps chain from pref observers on *_reason, +// so always set that last +function install(data, reason) { + Components.utils.import(data.resourceURI.spec + "version.jsm"); + Services.prefs.setIntPref("bootstraptest.installed_version", VERSION); + Services.prefs.setIntPref("bootstraptest.install_oldversion", data.oldVersion); + Components.utils.unload(data.resourceURI.spec + "version.jsm"); + Services.prefs.setIntPref("bootstraptest.install_reason", reason); +} + +function startup(data, reason) { + Components.utils.import(data.resourceURI.spec + "version.jsm"); + Services.prefs.setIntPref("bootstraptest.active_version", VERSION); + Services.prefs.setIntPref("bootstraptest.startup_oldversion", data.oldVersion); + Components.utils.unload(data.resourceURI.spec + "version.jsm"); + Services.prefs.setIntPref("bootstraptest.startup_reason", reason); +} + +function shutdown(data, reason) { + Services.prefs.setIntPref("bootstraptest.active_version", 0); + Services.prefs.setIntPref("bootstraptest.shutdown_newversion", data.newVersion); + Services.prefs.setIntPref("bootstraptest.shutdown_reason", reason); +} + +function uninstall(data, reason) { + Services.prefs.setIntPref("bootstraptest.installed_version", 0); + Services.prefs.setIntPref("bootstraptest.uninstall_newversion", data.newVersion); + Services.prefs.setIntPref("bootstraptest.uninstall_reason", reason); +} diff --git a/toolkit/mozapps/extensions/test/addons/test_bootstrap1_3/bootstrap.js b/toolkit/mozapps/extensions/test/addons/test_bootstrap1_3/bootstrap.js index 1666f2972..8839bfb7d 100644 --- a/toolkit/mozapps/extensions/test/addons/test_bootstrap1_3/bootstrap.js +++ b/toolkit/mozapps/extensions/test/addons/test_bootstrap1_3/bootstrap.js @@ -1 +1,31 @@ -Components.utils.import("resource://xpcshell-data/BootstrapMonitor.jsm").monitor(this); +Components.utils.import("resource://gre/modules/Services.jsm"); + +// Test steps chain from pref observers on *_reason, +// so always set that last +function install(data, reason) { + Components.utils.import(data.resourceURI.spec + "version.jsm"); + Services.prefs.setIntPref("bootstraptest.installed_version", VERSION); + Services.prefs.setIntPref("bootstraptest.install_oldversion", data.oldVersion); + Components.utils.unload(data.resourceURI.spec + "version.jsm"); + Services.prefs.setIntPref("bootstraptest.install_reason", reason); +} + +function startup(data, reason) { + Components.utils.import(data.resourceURI.spec + "version.jsm"); + Services.prefs.setIntPref("bootstraptest.active_version", VERSION); + Services.prefs.setIntPref("bootstraptest.startup_oldversion", data.oldVersion); + Components.utils.unload(data.resourceURI.spec + "version.jsm"); + Services.prefs.setIntPref("bootstraptest.startup_reason", reason); +} + +function shutdown(data, reason) { + Services.prefs.setIntPref("bootstraptest.active_version", 0); + Services.prefs.setIntPref("bootstraptest.shutdown_newversion", data.newVersion); + Services.prefs.setIntPref("bootstraptest.shutdown_reason", reason); +} + +function uninstall(data, reason) { + Services.prefs.setIntPref("bootstraptest.installed_version", 0); + Services.prefs.setIntPref("bootstraptest.uninstall_newversion", data.newVersion); + Services.prefs.setIntPref("bootstraptest.uninstall_reason", reason); +} diff --git a/toolkit/mozapps/extensions/test/addons/test_bootstrap2_1/bootstrap.js b/toolkit/mozapps/extensions/test/addons/test_bootstrap2_1/bootstrap.js index 1666f2972..476edfeee 100644 --- a/toolkit/mozapps/extensions/test/addons/test_bootstrap2_1/bootstrap.js +++ b/toolkit/mozapps/extensions/test/addons/test_bootstrap2_1/bootstrap.js @@ -1 +1,17 @@ -Components.utils.import("resource://xpcshell-data/BootstrapMonitor.jsm").monitor(this); +Components.utils.import("resource://gre/modules/Services.jsm"); + +function install(data, reason) { + Services.prefs.setIntPref("bootstraptest2.installed_version", 1); +} + +function startup(data, reason) { + Services.prefs.setIntPref("bootstraptest2.active_version", 1); +} + +function shutdown(data, reason) { + Services.prefs.setIntPref("bootstraptest2.active_version", 0); +} + +function uninstall(data, reason) { + Services.prefs.setIntPref("bootstraptest2.installed_version", 0); +} diff --git a/toolkit/mozapps/extensions/test/addons/test_bootstrap_const/bootstrap.js b/toolkit/mozapps/extensions/test/addons/test_bootstrap_const/bootstrap.js index 0e45caec4..498b76526 100644 --- a/toolkit/mozapps/extensions/test/addons/test_bootstrap_const/bootstrap.js +++ b/toolkit/mozapps/extensions/test/addons/test_bootstrap_const/bootstrap.js @@ -1,5 +1,5 @@ -Components.utils.import("resource://gre/modules/Services.jsm"); - -const install = function() { - Services.obs.notifyObservers(null, "addon-install", ""); -} +Components.utils.import("resource://gre/modules/Services.jsm");
+
+const install = function() {
+ Services.obs.notifyObservers(null, "addon-install", "");
+}
\ No newline at end of file diff --git a/toolkit/mozapps/extensions/test/addons/test_bootstrap_const/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bootstrap_const/install.rdf index 898282991..af3a749ce 100644 --- a/toolkit/mozapps/extensions/test/addons/test_bootstrap_const/install.rdf +++ b/toolkit/mozapps/extensions/test/addons/test_bootstrap_const/install.rdf @@ -1,24 +1,24 @@ -<?xml version="1.0"?> - -<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:em="http://www.mozilla.org/2004/em-rdf#"> - - <Description about="urn:mozilla:install-manifest"> - <em:id>bootstrap@tests.mozilla.org</em:id> - <em:version>1.0</em:version> - <em:bootstrap>true</em:bootstrap> - - <!-- Front End MetaData --> - <em:name>Test Bootstrap</em:name> - <em:description>Test Description</em:description> - - <em:targetApplication> - <Description> - <em:id>xpcshell@tests.mozilla.org</em:id> - <em:minVersion>1</em:minVersion> - <em:maxVersion>1</em:maxVersion> - </Description> - </em:targetApplication> - - </Description> -</RDF> +<?xml version="1.0"?>
+
+<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:em="http://www.mozilla.org/2004/em-rdf#">
+
+ <Description about="urn:mozilla:install-manifest">
+ <em:id>bootstrap@tests.mozilla.org</em:id>
+ <em:version>1.0</em:version>
+ <em:bootstrap>true</em:bootstrap>
+
+ <!-- Front End MetaData -->
+ <em:name>Test Bootstrap</em:name>
+ <em:description>Test Description</em:description>
+
+ <em:targetApplication>
+ <Description>
+ <em:id>xpcshell@tests.mozilla.org</em:id>
+ <em:minVersion>1</em:minVersion>
+ <em:maxVersion>1</em:maxVersion>
+ </Description>
+ </em:targetApplication>
+
+ </Description>
+</RDF>
\ No newline at end of file diff --git a/toolkit/mozapps/extensions/test/addons/test_bug675371/test.js b/toolkit/mozapps/extensions/test/addons/test_bug675371/test.js index b942a8064..ae74c174d 100644 --- a/toolkit/mozapps/extensions/test/addons/test_bug675371/test.js +++ b/toolkit/mozapps/extensions/test/addons/test_bug675371/test.js @@ -1 +1 @@ -var active = true; +active = true; diff --git a/toolkit/mozapps/extensions/test/addons/test_delay_update_complete_v2/bootstrap.js b/toolkit/mozapps/extensions/test/addons/test_delay_update_complete_v2/bootstrap.js deleted file mode 100644 index c5a80c7b9..000000000 --- a/toolkit/mozapps/extensions/test/addons/test_delay_update_complete_v2/bootstrap.js +++ /dev/null @@ -1,10 +0,0 @@ -Components.utils.import("resource://gre/modules/Services.jsm"); -Components.utils.import("resource://gre/modules/AddonManager.jsm"); - -const ADDON_ID = "test_delay_update_complete@tests.mozilla.org"; - -function install(data, reason) {} - -function startup(data, reason) {} - -function shutdown(data, reason) {} diff --git a/toolkit/mozapps/extensions/test/addons/test_delay_update_complete_v2/install.rdf b/toolkit/mozapps/extensions/test/addons/test_delay_update_complete_v2/install.rdf deleted file mode 100644 index 3ebbe16b0..000000000 --- a/toolkit/mozapps/extensions/test/addons/test_delay_update_complete_v2/install.rdf +++ /dev/null @@ -1,27 +0,0 @@ -<?xml version="1.0"?> - -<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:em="http://www.mozilla.org/2004/em-rdf#"> - - <Description about="urn:mozilla:install-manifest"> - <em:id>test_delay_update_complete@tests.mozilla.org</em:id> - <em:version>2.0</em:version> - <em:bootstrap>true</em:bootstrap> - - <!-- Front End MetaData --> - <em:name>Test Delay Update Complete</em:name> - <em:description>Test Description</em:description> - - <em:iconURL>chrome://foo/skin/icon.png</em:iconURL> - <em:aboutURL>chrome://foo/content/about.xul</em:aboutURL> - <em:optionsURL>chrome://foo/content/options.xul</em:optionsURL> - - <em:targetApplication> - <Description> - <em:id>xpcshell@tests.mozilla.org</em:id> - <em:minVersion>1</em:minVersion> - <em:maxVersion>1</em:maxVersion> - </Description> - </em:targetApplication> - - </Description> diff --git a/toolkit/mozapps/extensions/test/addons/test_delay_update_complete_webextension_v2/manifest.json b/toolkit/mozapps/extensions/test/addons/test_delay_update_complete_webextension_v2/manifest.json deleted file mode 100644 index 1a98f4660..000000000 --- a/toolkit/mozapps/extensions/test/addons/test_delay_update_complete_webextension_v2/manifest.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "manifest_version": 2, - "name": "Delay Upgrade", - "version": "2.0", - "applications": { - "gecko": { - "id": "test_delay_update_complete_webext@tests.mozilla.org" - } - } -} diff --git a/toolkit/mozapps/extensions/test/addons/test_delay_update_defer_v2/bootstrap.js b/toolkit/mozapps/extensions/test/addons/test_delay_update_defer_v2/bootstrap.js deleted file mode 100644 index dea028488..000000000 --- a/toolkit/mozapps/extensions/test/addons/test_delay_update_defer_v2/bootstrap.js +++ /dev/null @@ -1,10 +0,0 @@ -Components.utils.import("resource://gre/modules/Services.jsm"); -Components.utils.import("resource://gre/modules/AddonManager.jsm"); - -const ADDON_ID = "test_delay_update_defer@tests.mozilla.org"; - -function install(data, reason) {} - -function startup(data, reason) {} - -function shutdown(data, reason) {} diff --git a/toolkit/mozapps/extensions/test/addons/test_delay_update_defer_v2/install.rdf b/toolkit/mozapps/extensions/test/addons/test_delay_update_defer_v2/install.rdf deleted file mode 100644 index 75c7666bb..000000000 --- a/toolkit/mozapps/extensions/test/addons/test_delay_update_defer_v2/install.rdf +++ /dev/null @@ -1,27 +0,0 @@ -<?xml version="1.0"?> - -<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:em="http://www.mozilla.org/2004/em-rdf#"> - - <Description about="urn:mozilla:install-manifest"> - <em:id>test_delay_update_defer@tests.mozilla.org</em:id> - <em:version>2.0</em:version> - <em:bootstrap>true</em:bootstrap> - - <!-- Front End MetaData --> - <em:name>Test Delay Update Defer</em:name> - <em:description>Test Description</em:description> - - <em:iconURL>chrome://foo/skin/icon.png</em:iconURL> - <em:aboutURL>chrome://foo/content/about.xul</em:aboutURL> - <em:optionsURL>chrome://foo/content/options.xul</em:optionsURL> - - <em:targetApplication> - <Description> - <em:id>xpcshell@tests.mozilla.org</em:id> - <em:minVersion>1</em:minVersion> - <em:maxVersion>1</em:maxVersion> - </Description> - </em:targetApplication> - - </Description> diff --git a/toolkit/mozapps/extensions/test/addons/test_delay_update_defer_webextension_v2/manifest.json b/toolkit/mozapps/extensions/test/addons/test_delay_update_defer_webextension_v2/manifest.json deleted file mode 100644 index 9561979dc..000000000 --- a/toolkit/mozapps/extensions/test/addons/test_delay_update_defer_webextension_v2/manifest.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "manifest_version": 2, - "name": "Delay Upgrade", - "version": "2.0", - "applications": { - "gecko": { - "id": "test_delay_update_defer_webext@tests.mozilla.org" - } - } -} diff --git a/toolkit/mozapps/extensions/test/addons/test_delay_update_ignore_v2/bootstrap.js b/toolkit/mozapps/extensions/test/addons/test_delay_update_ignore_v2/bootstrap.js deleted file mode 100644 index fb8fc9540..000000000 --- a/toolkit/mozapps/extensions/test/addons/test_delay_update_ignore_v2/bootstrap.js +++ /dev/null @@ -1,8 +0,0 @@ -Components.utils.import("resource://gre/modules/Services.jsm"); -Components.utils.import("resource://gre/modules/AddonManager.jsm"); - -function install(data, reason) {} - -function startup(data, reason) {} - -function shutdown(data, reason) {} diff --git a/toolkit/mozapps/extensions/test/addons/test_delay_update_ignore_v2/install.rdf b/toolkit/mozapps/extensions/test/addons/test_delay_update_ignore_v2/install.rdf deleted file mode 100644 index aec4b202e..000000000 --- a/toolkit/mozapps/extensions/test/addons/test_delay_update_ignore_v2/install.rdf +++ /dev/null @@ -1,28 +0,0 @@ -<?xml version="1.0"?> - -<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:em="http://www.mozilla.org/2004/em-rdf#"> - - <Description about="urn:mozilla:install-manifest"> - <em:id>test_delay_update_ignore@tests.mozilla.org</em:id> - <em:version>2.0</em:version> - <em:bootstrap>true</em:bootstrap> - - <!-- Front End MetaData --> - <em:name>Test Delay Update Ignore</em:name> - <em:description>Test Description</em:description> - - <em:iconURL>chrome://foo/skin/icon.png</em:iconURL> - <em:aboutURL>chrome://foo/content/about.xul</em:aboutURL> - <em:optionsURL>chrome://foo/content/options.xul</em:optionsURL> - <em:updateURL>http://localhost:4444/data/test_delay_updates_ignore.rdf</em:updateURL> - - <em:targetApplication> - <Description> - <em:id>xpcshell@tests.mozilla.org</em:id> - <em:minVersion>1</em:minVersion> - <em:maxVersion>1</em:maxVersion> - </Description> - </em:targetApplication> - - </Description> diff --git a/toolkit/mozapps/extensions/test/addons/test_delay_update_ignore_webextension_v2/manifest.json b/toolkit/mozapps/extensions/test/addons/test_delay_update_ignore_webextension_v2/manifest.json deleted file mode 100644 index d9200ec11..000000000 --- a/toolkit/mozapps/extensions/test/addons/test_delay_update_ignore_webextension_v2/manifest.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "manifest_version": 2, - "name": "Delay Upgrade", - "version": "2.0", - "applications": { - "gecko": { - "id": "test_delay_update_ignore_webext@tests.mozilla.org" - } - } -} diff --git a/toolkit/mozapps/extensions/test/addons/test_dictionary/chrome.manifest b/toolkit/mozapps/extensions/test/addons/test_dictionary/chrome.manifest deleted file mode 100644 index c945c928c..000000000 --- a/toolkit/mozapps/extensions/test/addons/test_dictionary/chrome.manifest +++ /dev/null @@ -1 +0,0 @@ -content dict ./ diff --git a/toolkit/mozapps/extensions/test/addons/test_experiment1/bootstrap.js b/toolkit/mozapps/extensions/test/addons/test_experiment1/bootstrap.js deleted file mode 100644 index 1666f2972..000000000 --- a/toolkit/mozapps/extensions/test/addons/test_experiment1/bootstrap.js +++ /dev/null @@ -1 +0,0 @@ -Components.utils.import("resource://xpcshell-data/BootstrapMonitor.jsm").monitor(this); diff --git a/toolkit/mozapps/extensions/test/addons/test_install7/addon1.xpi b/toolkit/mozapps/extensions/test/addons/test_install7/addon1.xpi deleted file mode 100644 index 9c283d1d4..000000000 --- a/toolkit/mozapps/extensions/test/addons/test_install7/addon1.xpi +++ /dev/null @@ -1 +0,0 @@ -This isn't a valid zip file.
\ No newline at end of file diff --git a/toolkit/mozapps/extensions/test/addons/test_install7/addon2.xpi b/toolkit/mozapps/extensions/test/addons/test_install7/addon2.xpi deleted file mode 100644 index 9c283d1d4..000000000 --- a/toolkit/mozapps/extensions/test/addons/test_install7/addon2.xpi +++ /dev/null @@ -1 +0,0 @@ -This isn't a valid zip file.
\ No newline at end of file diff --git a/toolkit/mozapps/extensions/test/addons/test_install7/install.rdf b/toolkit/mozapps/extensions/test/addons/test_install7/install.rdf deleted file mode 100644 index 5e99ae29a..000000000 --- a/toolkit/mozapps/extensions/test/addons/test_install7/install.rdf +++ /dev/null @@ -1,10 +0,0 @@ -<?xml version="1.0"?> - -<!-- A multi-package XPI --> -<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:em="http://www.mozilla.org/2004/em-rdf#"> - - <Description about="urn:mozilla:install-manifest"> - <em:type>32</em:type> - </Description> -</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_install8/install.rdf b/toolkit/mozapps/extensions/test/addons/test_install8/install.rdf deleted file mode 100644 index 5e99ae29a..000000000 --- a/toolkit/mozapps/extensions/test/addons/test_install8/install.rdf +++ /dev/null @@ -1,10 +0,0 @@ -<?xml version="1.0"?> - -<!-- A multi-package XPI --> -<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:em="http://www.mozilla.org/2004/em-rdf#"> - - <Description about="urn:mozilla:install-manifest"> - <em:type>32</em:type> - </Description> -</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_symbol/bootstrap.js b/toolkit/mozapps/extensions/test/addons/test_symbol/bootstrap.js deleted file mode 100644 index 4eb8b4875..000000000 --- a/toolkit/mozapps/extensions/test/addons/test_symbol/bootstrap.js +++ /dev/null @@ -1,62 +0,0 @@ -Components.utils.import("resource://gre/modules/Services.jsm"); -Components.utils.import("resource://gre/modules/AddonManager.jsm"); - -const PASS_PREF = "symboltest.instanceid.pass"; -const FAIL_BOGUS_PREF = "symboltest.instanceid.fail_bogus"; -const FAIL_ID_PREF = "symboltest.instanceid.fail_bogus"; -const ADDON_ID = "test_symbol@tests.mozilla.org"; - -function install(data, reason) {} - -// normally we would use BootstrapMonitor here, but we need a reference to -// the symbol inside `XPIProvider.jsm`. -function startup(data, reason) { - Services.prefs.setBoolPref(PASS_PREF, false); - Services.prefs.setBoolPref(FAIL_BOGUS_PREF, false); - Services.prefs.setBoolPref(FAIL_ID_PREF, false); - - // test with the correct symbol - if (data.hasOwnProperty("instanceID") && data.instanceID) { - AddonManager.getAddonByInstanceID(data.instanceID) - .then(addon => { - if (addon.id == ADDON_ID) { - Services.prefs.setBoolPref(PASS_PREF, true); - } - }).catch(err => { - throw Error("no addon found for symbol"); - }); - - } - - // test with a totally bogus symbol - AddonManager.getAddonByInstanceID(Symbol("bad symbol")) - .then(addon => { - // there is no symbol by this name, so null should be returned - if (addon == null) { - Services.prefs.setBoolPref(FAIL_BOGUS_PREF, true); - } else { - throw Error("bad symbol should not match:", addon); - } - }).catch(err => { - throw Error("promise should not have rejected: " + err); - }); - - // try to make a matching symbol - this should fail because it's not a - // reference to the same symbol stored inside the addons manager. - AddonManager.getAddonByInstanceID(Symbol(ADDON_ID)) - .then(addon => { - // there is no symbol by this name, so null should be returned - if (addon == null) { - Services.prefs.setBoolPref(FAIL_ID_PREF, true); - } else { - throw Error("bad symbol should not match:", addon); - } - }).catch(err => { - throw Error("promise should not have rejected: " + err); - }); - -} - -function shutdown(data, reason) {} - -function uninstall(data, reason) {} diff --git a/toolkit/mozapps/extensions/test/addons/test_update_multi1/bootstrap.js b/toolkit/mozapps/extensions/test/addons/test_update_multi1/bootstrap.js deleted file mode 100644 index 24c778c09..000000000 --- a/toolkit/mozapps/extensions/test/addons/test_update_multi1/bootstrap.js +++ /dev/null @@ -1,5 +0,0 @@ - -function install(data, reason) {} -function startup(data, reason) {} -function shutdown(data, reason) {} -function uninstall(data, reason) {} diff --git a/toolkit/mozapps/extensions/test/addons/test_update_multi1/install.rdf b/toolkit/mozapps/extensions/test/addons/test_update_multi1/install.rdf deleted file mode 100644 index 9f955562c..000000000 --- a/toolkit/mozapps/extensions/test/addons/test_update_multi1/install.rdf +++ /dev/null @@ -1,16 +0,0 @@ -<?xml version="1.0"?> -<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:em="http://www.mozilla.org/2004/em-rdf#"> -<Description about="urn:mozilla:install-manifest"> - <em:id>updatemulti@tests.mozilla.org</em:id> - <em:version>1.0</em:version> - <em:updateURL>http://localhost:4444/data/test_update_multi.rdf</em:updateURL> - <em:bootstrap>true</em:bootstrap> - <em:name>Test Addon 1</em:name> -<em:targetApplication><Description> - <em:id>xpcshell@tests.mozilla.org</em:id> - <em:minVersion>1</em:minVersion> - <em:maxVersion>1</em:maxVersion> -</Description></em:targetApplication> -</Description> -</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_update_multi2/addon.xpi b/toolkit/mozapps/extensions/test/addons/test_update_multi2/addon.xpi Binary files differdeleted file mode 100644 index febff06fa..000000000 --- a/toolkit/mozapps/extensions/test/addons/test_update_multi2/addon.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/addons/test_update_multi2/install.rdf b/toolkit/mozapps/extensions/test/addons/test_update_multi2/install.rdf deleted file mode 100644 index 44bdb05ba..000000000 --- a/toolkit/mozapps/extensions/test/addons/test_update_multi2/install.rdf +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0"?> -<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:em="http://www.mozilla.org/2004/em-rdf#"> -<Description about="urn:mozilla:install-manifest"> - <em:id>updatemulti@tests.mozilla.org</em:id> - <em:type>32</em:type> - <em:version>2.0</em:version> -</Description> -</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_updateid1/bootstrap.js b/toolkit/mozapps/extensions/test/addons/test_updateid1/bootstrap.js deleted file mode 100644 index 24c778c09..000000000 --- a/toolkit/mozapps/extensions/test/addons/test_updateid1/bootstrap.js +++ /dev/null @@ -1,5 +0,0 @@ - -function install(data, reason) {} -function startup(data, reason) {} -function shutdown(data, reason) {} -function uninstall(data, reason) {} diff --git a/toolkit/mozapps/extensions/test/addons/test_updateid1/install.rdf b/toolkit/mozapps/extensions/test/addons/test_updateid1/install.rdf deleted file mode 100644 index 803b64e5f..000000000 --- a/toolkit/mozapps/extensions/test/addons/test_updateid1/install.rdf +++ /dev/null @@ -1,16 +0,0 @@ -<?xml version="1.0"?> -<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:em="http://www.mozilla.org/2004/em-rdf#"> -<Description about="urn:mozilla:install-manifest"> - <em:id>addon1@tests.mozilla.org</em:id> - <em:version>1.0</em:version> - <em:updateURL>http://localhost:4444/data/test_updateid.rdf</em:updateURL> - <em:bootstrap>true</em:bootstrap> - <em:name>Test Addon 1</em:name> -<em:targetApplication><Description> - <em:id>xpcshell@tests.mozilla.org</em:id> - <em:minVersion>1</em:minVersion> - <em:maxVersion>1</em:maxVersion> -</Description></em:targetApplication> -</Description> -</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_updateid2/bootstrap.js b/toolkit/mozapps/extensions/test/addons/test_updateid2/bootstrap.js deleted file mode 100644 index 24c778c09..000000000 --- a/toolkit/mozapps/extensions/test/addons/test_updateid2/bootstrap.js +++ /dev/null @@ -1,5 +0,0 @@ - -function install(data, reason) {} -function startup(data, reason) {} -function shutdown(data, reason) {} -function uninstall(data, reason) {} diff --git a/toolkit/mozapps/extensions/test/addons/test_updateid2/install.rdf b/toolkit/mozapps/extensions/test/addons/test_updateid2/install.rdf deleted file mode 100644 index 041af57f0..000000000 --- a/toolkit/mozapps/extensions/test/addons/test_updateid2/install.rdf +++ /dev/null @@ -1,16 +0,0 @@ -<?xml version="1.0"?> -<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:em="http://www.mozilla.org/2004/em-rdf#"> -<Description about="urn:mozilla:install-manifest"> - <em:id>addon1.changed@tests.mozilla.org</em:id> - <em:version>2.0</em:version> - <em:updateURL>http://localhost:4444/data/test_updateid.rdf</em:updateURL> - <em:bootstrap>true</em:bootstrap> - <em:name>Test Addon 1</em:name> -<em:targetApplication><Description> - <em:id>xpcshell@tests.mozilla.org</em:id> - <em:minVersion>1</em:minVersion> - <em:maxVersion>1</em:maxVersion> -</Description></em:targetApplication> -</Description> -</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_hotfix_2/install.rdf b/toolkit/mozapps/extensions/test/addons/test_updateid2_2/install.rdf index fd843dbe9..5982b9868 100644 --- a/toolkit/mozapps/extensions/test/addons/test_hotfix_2/install.rdf +++ b/toolkit/mozapps/extensions/test/addons/test_updateid2_2/install.rdf @@ -4,11 +4,12 @@ xmlns:em="http://www.mozilla.org/2004/em-rdf#"> <Description about="urn:mozilla:install-manifest"> - <em:id>hotfix@tests.mozilla.org</em:id> + <em:id>addon2@tests.mozilla.org</em:id> <em:version>2.0</em:version> + <em:updateURL>http://localhost:4444/data/test_updateid.rdf</em:updateURL> <!-- Front End MetaData --> - <em:name>Test 1</em:name> + <em:name>Test 2</em:name> <em:description>Test Description</em:description> <em:targetApplication> diff --git a/toolkit/mozapps/extensions/test/addons/test_hotfix_1/install.rdf b/toolkit/mozapps/extensions/test/addons/test_updateid2_5/install.rdf index 7fcc1a09e..e923a5289 100644 --- a/toolkit/mozapps/extensions/test/addons/test_hotfix_1/install.rdf +++ b/toolkit/mozapps/extensions/test/addons/test_updateid2_5/install.rdf @@ -4,11 +4,12 @@ xmlns:em="http://www.mozilla.org/2004/em-rdf#"> <Description about="urn:mozilla:install-manifest"> - <em:id>hotfix@tests.mozilla.org</em:id> - <em:version>1.0</em:version> + <em:id>addon2@tests.mozilla.org</em:id> + <em:version>5.0</em:version> + <em:updateURL>http://localhost:4444/data/test_updateid.rdf</em:updateURL> <!-- Front End MetaData --> - <em:name>Test 1</em:name> + <em:name>Test 2</em:name> <em:description>Test Description</em:description> <em:targetApplication> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/bootstrap_1/bootstrap.js b/toolkit/mozapps/extensions/test/addons/test_updateid3_3/bootstrap.js index 0cf01d319..c28d75925 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/bootstrap_1/bootstrap.js +++ b/toolkit/mozapps/extensions/test/addons/test_updateid3_3/bootstrap.js @@ -1,29 +1,21 @@ Components.utils.import("resource://gre/modules/Services.jsm"); -const VERSION = 1; - -// Test steps chain from pref observers on *_reason, -// so always set that last function install(data, reason) { - Services.prefs.setIntPref("bootstraptest.installed_version", VERSION); - Services.prefs.setIntPref("bootstraptest.install_oldversion", data.oldVersion); + Services.prefs.setIntPref("bootstraptest.installed_version", 3); Services.prefs.setIntPref("bootstraptest.install_reason", reason); } function startup(data, reason) { - Services.prefs.setIntPref("bootstraptest.active_version", VERSION); - Services.prefs.setIntPref("bootstraptest.startup_oldversion", data.oldVersion); + Services.prefs.setIntPref("bootstraptest.active_version", 3); Services.prefs.setIntPref("bootstraptest.startup_reason", reason); } function shutdown(data, reason) { Services.prefs.setIntPref("bootstraptest.active_version", 0); - Services.prefs.setIntPref("bootstraptest.shutdown_newversion", data.newVersion); Services.prefs.setIntPref("bootstraptest.shutdown_reason", reason); } function uninstall(data, reason) { Services.prefs.setIntPref("bootstraptest.installed_version", 0); - Services.prefs.setIntPref("bootstraptest.uninstall_newversion", data.newVersion); Services.prefs.setIntPref("bootstraptest.uninstall_reason", reason); } diff --git a/toolkit/mozapps/extensions/test/addons/test_symbol/install.rdf b/toolkit/mozapps/extensions/test/addons/test_updateid3_3/install.rdf index adccda552..ffed064cf 100644 --- a/toolkit/mozapps/extensions/test/addons/test_symbol/install.rdf +++ b/toolkit/mozapps/extensions/test/addons/test_updateid3_3/install.rdf @@ -4,18 +4,15 @@ xmlns:em="http://www.mozilla.org/2004/em-rdf#"> <Description about="urn:mozilla:install-manifest"> - <em:id>test_symbol@tests.mozilla.org</em:id> - <em:version>1.0</em:version> + <em:id>addon3@tests.mozilla.org</em:id> + <em:version>3.0</em:version> + <em:updateURL>http://localhost:4444/data/test_updateid.rdf</em:updateURL> <em:bootstrap>true</em:bootstrap> <!-- Front End MetaData --> - <em:name>Test Symbol</em:name> + <em:name>Test 3</em:name> <em:description>Test Description</em:description> - <em:iconURL>chrome://foo/skin/icon.png</em:iconURL> - <em:aboutURL>chrome://foo/content/about.xul</em:aboutURL> - <em:optionsURL>chrome://foo/content/options.xul</em:optionsURL> - <em:targetApplication> <Description> <em:id>xpcshell@tests.mozilla.org</em:id> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/bootstrap_2/bootstrap.js b/toolkit/mozapps/extensions/test/addons/test_updateid4_4/bootstrap.js index 718c82be4..6b1753cb2 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/bootstrap_2/bootstrap.js +++ b/toolkit/mozapps/extensions/test/addons/test_updateid4_4/bootstrap.js @@ -1,29 +1,21 @@ Components.utils.import("resource://gre/modules/Services.jsm"); -const VERSION = 2; - -// Test steps chain from pref observers on *_reason, -// so always set that last function install(data, reason) { - Services.prefs.setIntPref("bootstraptest.installed_version", VERSION); - Services.prefs.setIntPref("bootstraptest.install_oldversion", data.oldVersion); + Services.prefs.setIntPref("bootstraptest.installed_version", 4); Services.prefs.setIntPref("bootstraptest.install_reason", reason); } function startup(data, reason) { - Services.prefs.setIntPref("bootstraptest.active_version", VERSION); - Services.prefs.setIntPref("bootstraptest.startup_oldversion", data.oldVersion); + Services.prefs.setIntPref("bootstraptest.active_version", 4); Services.prefs.setIntPref("bootstraptest.startup_reason", reason); } function shutdown(data, reason) { Services.prefs.setIntPref("bootstraptest.active_version", 0); - Services.prefs.setIntPref("bootstraptest.shutdown_newversion", data.newVersion); Services.prefs.setIntPref("bootstraptest.shutdown_reason", reason); } function uninstall(data, reason) { Services.prefs.setIntPref("bootstraptest.installed_version", 0); - Services.prefs.setIntPref("bootstraptest.uninstall_newversion", data.newVersion); Services.prefs.setIntPref("bootstraptest.uninstall_reason", reason); } diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/from_sources/install.rdf b/toolkit/mozapps/extensions/test/addons/test_updateid4_4/install.rdf index f02a3869c..b354ac5c1 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/data/from_sources/install.rdf +++ b/toolkit/mozapps/extensions/test/addons/test_updateid4_4/install.rdf @@ -4,18 +4,15 @@ xmlns:em="http://www.mozilla.org/2004/em-rdf#"> <Description about="urn:mozilla:install-manifest"> - <em:id>bootstrap1@tests.mozilla.org</em:id> - <em:version>1.0</em:version> + <em:id>addon4@tests.mozilla.org</em:id> + <em:version>4.0</em:version> + <em:updateURL>http://localhost:4444/data/test_updateid.rdf</em:updateURL> <em:bootstrap>true</em:bootstrap> <!-- Front End MetaData --> - <em:name>Test Bootstrap 1</em:name> + <em:name>Test 4</em:name> <em:description>Test Description</em:description> - <em:iconURL>chrome://foo/skin/icon.png</em:iconURL> - <em:aboutURL>chrome://foo/content/about.xul</em:aboutURL> - <em:optionsURL>chrome://foo/content/options.xul</em:optionsURL> - <em:targetApplication> <Description> <em:id>xpcshell@tests.mozilla.org</em:id> diff --git a/toolkit/mozapps/extensions/test/addons/webextension_1/chrome.manifest b/toolkit/mozapps/extensions/test/addons/webextension_1/chrome.manifest deleted file mode 100644 index 16108ce18..000000000 --- a/toolkit/mozapps/extensions/test/addons/webextension_1/chrome.manifest +++ /dev/null @@ -1 +0,0 @@ -content webex ./ diff --git a/toolkit/mozapps/extensions/test/addons/webextension_1/manifest.json b/toolkit/mozapps/extensions/test/addons/webextension_1/manifest.json deleted file mode 100644 index 2ca5f40f7..000000000 --- a/toolkit/mozapps/extensions/test/addons/webextension_1/manifest.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "Web Extension Name", - "version": "1.0", - "manifest_version": 2, - "applications": { - "gecko": { - "id": "webextension1@tests.mozilla.org" - } - }, - "icons": { - "48": "icon48.png", - "64": "icon64.png" - } -} diff --git a/toolkit/mozapps/extensions/test/addons/webextension_2/install.rdf b/toolkit/mozapps/extensions/test/addons/webextension_2/install.rdf deleted file mode 100644 index 653481ed0..000000000 --- a/toolkit/mozapps/extensions/test/addons/webextension_2/install.rdf +++ /dev/null @@ -1,30 +0,0 @@ -<?xml version="1.0"?> - -<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:em="http://www.mozilla.org/2004/em-rdf#"> - - <Description about="urn:mozilla:install-manifest"> - <em:id>first-webextension2@tests.mozilla.org</em:id> - <em:version>2.0</em:version> - - <em:targetApplication> - <Description> - <em:id>xpcshell@tests.mozilla.org</em:id> - <em:minVersion>1</em:minVersion> - <em:maxVersion>1</em:maxVersion> - </Description> - </em:targetApplication> - - <!-- Front End MetaData --> - <em:name>XPI Add-on 1</em:name> - <em:description>XPI Add-on 1 - Description</em:description> - <em:creator>XPI Add-on 1 - Creator</em:creator> - <em:developer>XPI Add-on 1 - First Developer</em:developer> - <em:translator>XPI Add-on 1 - First Translator</em:translator> - <em:contributor>XPI Add-on 1 - First Contributor</em:contributor> - <em:homepageURL>http://localhost/xpi/1/homepage.html</em:homepageURL> - <em:optionsURL>http://localhost/xpi/1/options.html</em:optionsURL> - <em:aboutURL>http://localhost/xpi/1/about.html</em:aboutURL> - <em:iconURL>http://localhost/xpi/1/icon.png</em:iconURL> - </Description> -</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/webextension_2/manifest.json b/toolkit/mozapps/extensions/test/addons/webextension_2/manifest.json deleted file mode 100644 index 5b470d430..000000000 --- a/toolkit/mozapps/extensions/test/addons/webextension_2/manifest.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "Web Extension Name", - "version": "1.0", - "manifest_version": 2, - "applications": { - "gecko": { - "id": "last-webextension2@tests.mozilla.org" - } - } -} diff --git a/toolkit/mozapps/extensions/test/addons/webextension_3/_locales/en/messages.json b/toolkit/mozapps/extensions/test/addons/webextension_3/_locales/en/messages.json deleted file mode 100644 index 36868d414..000000000 --- a/toolkit/mozapps/extensions/test/addons/webextension_3/_locales/en/messages.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": { - "message": "foo ☹", - "description": "foo" - }, - "desc": { - "message": "bar ☹", - "description": "bar" - } -} diff --git a/toolkit/mozapps/extensions/test/addons/webextension_3/_locales/fr/messages.json b/toolkit/mozapps/extensions/test/addons/webextension_3/_locales/fr/messages.json deleted file mode 100644 index c3d02ffde..000000000 --- a/toolkit/mozapps/extensions/test/addons/webextension_3/_locales/fr/messages.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": { - "message": "le foo ☺", - "description": "foo" - }, - "desc": { - "message": "le bar ☺", - "description": "bar" - } -} diff --git a/toolkit/mozapps/extensions/test/addons/webextension_3/manifest.json b/toolkit/mozapps/extensions/test/addons/webextension_3/manifest.json deleted file mode 100644 index b6ae6f10f..000000000 --- a/toolkit/mozapps/extensions/test/addons/webextension_3/manifest.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "name": "Web Extensiøn __MSG_name__", - "description": "Descriptïon __MSG_desc__ of add-on", - "version": "1.0", - "manifest_version": 2, - "default_locale": "en", - "applications": { - "gecko": { - "id": "webextension3@tests.mozilla.org" - } - } -} diff --git a/toolkit/mozapps/extensions/test/browser/.eslintrc.js b/toolkit/mozapps/extensions/test/browser/.eslintrc.js deleted file mode 100644 index 2852eb81d..000000000 --- a/toolkit/mozapps/extensions/test/browser/.eslintrc.js +++ /dev/null @@ -1,7 +0,0 @@ -"use strict"; - -module.exports = { // eslint-disable-line no-undef - "extends": [ - "../../../../../testing/mochitest/browser.eslintrc.js" - ] -}; diff --git a/toolkit/mozapps/extensions/test/browser/Makefile.in b/toolkit/mozapps/extensions/test/browser/Makefile.in new file mode 100644 index 000000000..6bd692d9b --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/Makefile.in @@ -0,0 +1,19 @@ +# 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/. + +ADDONSRC = $(srcdir)/addons +TESTXPI = $(CURDIR)/$(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)/addons + +include $(topsrcdir)/config/rules.mk + +libs:: + rm -rf $(TESTXPI) + $(NSINSTALL) -D $(TESTXPI) + if [ -d $(ADDONSRC) ]; then \ + $(EXIT_ON_ERROR) \ + for dir in $(ADDONSRC)/*; do \ + base=`basename $$dir` ; \ + (cd $$dir && zip -q $(TESTXPI)/$$base.xpi *) \ + done \ + fi diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_1.xpi b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_1.xpi Binary files differdeleted file mode 100644 index d13e5d66e..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_1.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_1/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_1/install.rdf index 5199c2f3f..5c164ec07 100644 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_1/install.rdf +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_1/install.rdf @@ -4,19 +4,11 @@ xmlns:em="http://www.mozilla.org/2004/em-rdf#"> <Description about="urn:mozilla:install-manifest"> - <em:id>bug557956-1@tests.mozilla.org</em:id> + <em:id>addon1@tests.mozilla.org</em:id> <em:version>1.0</em:version> <em:targetApplication> <Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>0.3</em:minVersion> - <em:maxVersion>*</em:maxVersion> - </Description> - </em:targetApplication> - - <em:targetApplication> - <Description> <em:id>toolkit@mozilla.org</em:id> <em:minVersion>0</em:minVersion> <em:maxVersion>*</em:maxVersion> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_10.xpi b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_10.xpi Binary files differdeleted file mode 100644 index e1d6ac586..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_10.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_10/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_10/install.rdf index c061814b6..95b6488dd 100644 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_10/install.rdf +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_10/install.rdf @@ -4,19 +4,11 @@ xmlns:em="http://www.mozilla.org/2004/em-rdf#"> <Description about="urn:mozilla:install-manifest"> - <em:id>bug557956-10@tests.mozilla.org</em:id> + <em:id>addon10@tests.mozilla.org</em:id> <em:version>1.0</em:version> <em:targetApplication> <Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>0.3</em:minVersion> - <em:maxVersion>0.3</em:maxVersion> - </Description> - </em:targetApplication> - - <em:targetApplication> - <Description> <em:id>toolkit@mozilla.org</em:id> <em:minVersion>0</em:minVersion> <em:maxVersion>0</em:maxVersion> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_2.xpi b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_2.xpi Binary files differdeleted file mode 100644 index 1380e7b5b..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_2.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_2/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_2/install.rdf index 1be5422b2..d02cefac2 100644 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_2/install.rdf +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_2/install.rdf @@ -4,19 +4,11 @@ xmlns:em="http://www.mozilla.org/2004/em-rdf#"> <Description about="urn:mozilla:install-manifest"> - <em:id>bug557956-2@tests.mozilla.org</em:id> + <em:id>addon2@tests.mozilla.org</em:id> <em:version>1.0</em:version> <em:targetApplication> <Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>0.3</em:minVersion> - <em:maxVersion>0.3</em:maxVersion> - </Description> - </em:targetApplication> - - <em:targetApplication> - <Description> <em:id>toolkit@mozilla.org</em:id> <em:minVersion>0</em:minVersion> <em:maxVersion>0</em:maxVersion> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_3.xpi b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_3.xpi Binary files differdeleted file mode 100644 index 46326b04c..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_3.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_3/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_3/install.rdf index 54887a30e..23b4813c6 100644 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_3/install.rdf +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_3/install.rdf @@ -4,19 +4,11 @@ xmlns:em="http://www.mozilla.org/2004/em-rdf#"> <Description about="urn:mozilla:install-manifest"> - <em:id>bug557956-3@tests.mozilla.org</em:id> + <em:id>addon3@tests.mozilla.org</em:id> <em:version>1.0</em:version> <em:targetApplication> <Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>0.3</em:minVersion> - <em:maxVersion>0.3</em:maxVersion> - </Description> - </em:targetApplication> - - <em:targetApplication> - <Description> <em:id>toolkit@mozilla.org</em:id> <em:minVersion>0</em:minVersion> <em:maxVersion>0</em:maxVersion> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_4.xpi b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_4.xpi Binary files differdeleted file mode 100644 index 95de79b79..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_4.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_4/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_4/install.rdf index 79946b0f0..0150fc3c0 100644 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_4/install.rdf +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_4/install.rdf @@ -4,19 +4,11 @@ xmlns:em="http://www.mozilla.org/2004/em-rdf#"> <Description about="urn:mozilla:install-manifest"> - <em:id>bug557956-4@tests.mozilla.org</em:id> + <em:id>addon4@tests.mozilla.org</em:id> <em:version>1.0</em:version> <em:targetApplication> <Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>1.0</em:minVersion> - <em:maxVersion>*</em:maxVersion> - </Description> - </em:targetApplication> - - <em:targetApplication> - <Description> <em:id>toolkit@mozilla.org</em:id> <em:minVersion>1</em:minVersion> <em:maxVersion>*</em:maxVersion> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_5.xpi b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_5.xpi Binary files differdeleted file mode 100644 index 005d7ef21..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_5.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_5/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_5/install.rdf index 067af1ba1..dfcbf0384 100644 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_5/install.rdf +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_5/install.rdf @@ -4,19 +4,11 @@ xmlns:em="http://www.mozilla.org/2004/em-rdf#"> <Description about="urn:mozilla:install-manifest"> - <em:id>bug557956-5@tests.mozilla.org</em:id> + <em:id>addon5@tests.mozilla.org</em:id> <em:version>1.0</em:version> <em:targetApplication> <Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>0.3</em:minVersion> - <em:maxVersion>0.3</em:maxVersion> - </Description> - </em:targetApplication> - - <em:targetApplication> - <Description> <em:id>toolkit@mozilla.org</em:id> <em:minVersion>0</em:minVersion> <em:maxVersion>0</em:maxVersion> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_6.xpi b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_6.xpi Binary files differdeleted file mode 100644 index 89f751a03..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_6.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_6/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_6/install.rdf index 37d7e6a7c..8e1027923 100644 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_6/install.rdf +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_6/install.rdf @@ -4,19 +4,11 @@ xmlns:em="http://www.mozilla.org/2004/em-rdf#"> <Description about="urn:mozilla:install-manifest"> - <em:id>bug557956-6@tests.mozilla.org</em:id> + <em:id>addon6@tests.mozilla.org</em:id> <em:version>1.0</em:version> <em:targetApplication> <Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>0.3</em:minVersion> - <em:maxVersion>0.3</em:maxVersion> - </Description> - </em:targetApplication> - - <em:targetApplication> - <Description> <em:id>toolkit@mozilla.org</em:id> <em:minVersion>0</em:minVersion> <em:maxVersion>0</em:maxVersion> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_7.xpi b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_7.xpi Binary files differdeleted file mode 100644 index 77de37c2a..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_7.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_7/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_7/install.rdf index 461facbb2..023f9f05f 100644 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_7/install.rdf +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_7/install.rdf @@ -4,19 +4,11 @@ xmlns:em="http://www.mozilla.org/2004/em-rdf#"> <Description about="urn:mozilla:install-manifest"> - <em:id>bug557956-7@tests.mozilla.org</em:id> + <em:id>addon7@tests.mozilla.org</em:id> <em:version>1.0</em:version> <em:targetApplication> <Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>0.3</em:minVersion> - <em:maxVersion>0.3</em:maxVersion> - </Description> - </em:targetApplication> - - <em:targetApplication> - <Description> <em:id>toolkit@mozilla.org</em:id> <em:minVersion>0</em:minVersion> <em:maxVersion>0</em:maxVersion> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_8_1.xpi b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_8_1.xpi Binary files differdeleted file mode 100644 index 666ae0910..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_8_1.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_8_1/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_8_1/install.rdf index 2111b9c64..57855e094 100644 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_8_1/install.rdf +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_8_1/install.rdf @@ -4,19 +4,11 @@ xmlns:em="http://www.mozilla.org/2004/em-rdf#"> <Description about="urn:mozilla:install-manifest"> - <em:id>bug557956-8@tests.mozilla.org</em:id> + <em:id>addon8@tests.mozilla.org</em:id> <em:version>1.0</em:version> <em:targetApplication> <Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>0.3</em:minVersion> - <em:maxVersion>0.3</em:maxVersion> - </Description> - </em:targetApplication> - - <em:targetApplication> - <Description> <em:id>toolkit@mozilla.org</em:id> <em:minVersion>0</em:minVersion> <em:maxVersion>0</em:maxVersion> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_9_1.xpi b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_9_1.xpi Binary files differdeleted file mode 100644 index ad9367dc1..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_9_1.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_9_1/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_9_1/install.rdf index 032e9adaf..e1d6554f3 100644 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_9_1/install.rdf +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_9_1/install.rdf @@ -4,19 +4,11 @@ xmlns:em="http://www.mozilla.org/2004/em-rdf#"> <Description about="urn:mozilla:install-manifest"> - <em:id>bug557956-9@tests.mozilla.org</em:id> + <em:id>addon9@tests.mozilla.org</em:id> <em:version>1.0</em:version> <em:targetApplication> <Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>0.3</em:minVersion> - <em:maxVersion>0.3</em:maxVersion> - </Description> - </em:targetApplication> - - <em:targetApplication> - <Description> <em:id>toolkit@mozilla.org</em:id> <em:minVersion>0</em:minVersion> <em:maxVersion>0</em:maxVersion> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug567127_1.xpi b/toolkit/mozapps/extensions/test/browser/addons/browser_bug567127_1.xpi Binary files differdeleted file mode 100644 index 20ae35539..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_bug567127_1.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug567127_1/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_bug567127_1/install.rdf index d9f0ca745..f5780d5d3 100644 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_bug567127_1/install.rdf +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_bug567127_1/install.rdf @@ -9,14 +9,6 @@ <em:targetApplication> <Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>0.3</em:minVersion> - <em:maxVersion>*</em:maxVersion> - </Description> - </em:targetApplication> - - <em:targetApplication> - <Description> <em:id>toolkit@mozilla.org</em:id> <em:minVersion>0</em:minVersion> <em:maxVersion>*</em:maxVersion> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug567127_2.xpi b/toolkit/mozapps/extensions/test/browser/addons/browser_bug567127_2.xpi Binary files differdeleted file mode 100644 index 3c99022cf..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_bug567127_2.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug567127_2/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_bug567127_2/install.rdf index 8809ffb58..84c542cf9 100644 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_bug567127_2/install.rdf +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_bug567127_2/install.rdf @@ -9,14 +9,6 @@ <em:targetApplication> <Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>0.3</em:minVersion> - <em:maxVersion>*</em:maxVersion> - </Description> - </em:targetApplication> - - <em:targetApplication> - <Description> <em:id>toolkit@mozilla.org</em:id> <em:minVersion>0</em:minVersion> <em:maxVersion>*</em:maxVersion> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug596336_1.xpi b/toolkit/mozapps/extensions/test/browser/addons/browser_bug596336_1.xpi Binary files differdeleted file mode 100644 index c438cbd0b..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_bug596336_1.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug596336_1/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_bug596336_1/install.rdf index c768d7881..726ffee8b 100644 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_bug596336_1/install.rdf +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_bug596336_1/install.rdf @@ -4,20 +4,12 @@ xmlns:em="http://www.mozilla.org/2004/em-rdf#"> <Description about="urn:mozilla:install-manifest"> - <em:id>bug596336-1@tests.mozilla.org</em:id> + <em:id>addon1@tests.mozilla.org</em:id> <em:version>1.0</em:version> <em:bootstrap>true</em:bootstrap> <em:targetApplication> <Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>0.3</em:minVersion> - <em:maxVersion>*</em:maxVersion> - </Description> - </em:targetApplication> - - <em:targetApplication> - <Description> <em:id>toolkit@mozilla.org</em:id> <em:minVersion>0</em:minVersion> <em:maxVersion>*</em:maxVersion> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug596336_2.xpi b/toolkit/mozapps/extensions/test/browser/addons/browser_bug596336_2.xpi Binary files differdeleted file mode 100644 index a87191efe..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_bug596336_2.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug596336_2/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_bug596336_2/install.rdf index bed489c3e..16e4fd0cd 100644 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_bug596336_2/install.rdf +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_bug596336_2/install.rdf @@ -4,20 +4,12 @@ xmlns:em="http://www.mozilla.org/2004/em-rdf#"> <Description about="urn:mozilla:install-manifest"> - <em:id>bug596336-1@tests.mozilla.org</em:id> + <em:id>addon1@tests.mozilla.org</em:id> <em:version>2.0</em:version> <em:bootstrap>true</em:bootstrap> <em:targetApplication> <Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>0.3</em:minVersion> - <em:maxVersion>*</em:maxVersion> - </Description> - </em:targetApplication> - - <em:targetApplication> - <Description> <em:id>toolkit@mozilla.org</em:id> <em:minVersion>0</em:minVersion> <em:maxVersion>*</em:maxVersion> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_dragdrop1.xpi b/toolkit/mozapps/extensions/test/browser/addons/browser_dragdrop1.xpi Binary files differdeleted file mode 100644 index d8b4d083c..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_dragdrop1.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_dragdrop1/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_dragdrop1/install.rdf index 9bcd43e87..0a845ed31 100644 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_dragdrop1/install.rdf +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_dragdrop1/install.rdf @@ -9,14 +9,6 @@ <em:targetApplication> <Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>0.3</em:minVersion> - <em:maxVersion>*</em:maxVersion> - </Description> - </em:targetApplication> - - <em:targetApplication> - <Description> <em:id>toolkit@mozilla.org</em:id> <em:minVersion>0</em:minVersion> <em:maxVersion>*</em:maxVersion> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_dragdrop2.xpi b/toolkit/mozapps/extensions/test/browser/addons/browser_dragdrop2.xpi Binary files differdeleted file mode 100644 index e4441cb19..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_dragdrop2.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_dragdrop2/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_dragdrop2/install.rdf index 4789abfaf..03072fdf4 100644 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_dragdrop2/install.rdf +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_dragdrop2/install.rdf @@ -9,14 +9,6 @@ <em:targetApplication> <Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>0.3</em:minVersion> - <em:maxVersion>*</em:maxVersion> - </Description> - </em:targetApplication> - - <em:targetApplication> - <Description> <em:id>toolkit@mozilla.org</em:id> <em:minVersion>0</em:minVersion> <em:maxVersion>*</em:maxVersion> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_experiment1.xpi b/toolkit/mozapps/extensions/test/browser/addons/browser_experiment1.xpi Binary files differdeleted file mode 100644 index 1c2b793f1..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_experiment1.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1.xpi b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1.xpi Binary files differdeleted file mode 100644 index be453ce9c..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1/chrome.manifest b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1/chrome.manifest deleted file mode 100644 index 8884e3974..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1/chrome.manifest +++ /dev/null @@ -1 +0,0 @@ -locale inlinesettings en-US ./ diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1/install.rdf index 18fcec167..2bf7c6e2e 100644 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1/install.rdf +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1/install.rdf @@ -9,14 +9,6 @@ <em:targetApplication> <Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>0.3</em:minVersion> - <em:maxVersion>*</em:maxVersion> - </Description> - </em:targetApplication> - - <em:targetApplication> - <Description> <em:id>toolkit@mozilla.org</em:id> <em:minVersion>0</em:minVersion> <em:maxVersion>*</em:maxVersion> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1/options.xul b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1/options.xul index cd4f72387..c271c35da 100644 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1/options.xul +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1/options.xul @@ -1,9 +1,6 @@ <?xml version="1.0" ?> - -<!DOCTYPE vbox SYSTEM "chrome://inlinesettings/locale/settings.dtd"> - <vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> - <setting pref="extensions.inlinesettings1.bool" type="bool" title="Bool" checkboxlabel="&checkbox;"/> + <setting pref="extensions.inlinesettings1.bool" type="bool" title="Bool" checkboxlabel="Check box label"/> <setting pref="extensions.inlinesettings1.boolint" type="boolint" on="1" off="2" title="BoolInt"/> <setting pref="extensions.inlinesettings1.integer" type="integer" title="Integer"/> <setting pref="extensions.inlinesettings1.string" type="string" title="String"/> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1/settings.dtd b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1/settings.dtd deleted file mode 100644 index 6864a3d5a..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1/settings.dtd +++ /dev/null @@ -1 +0,0 @@ -<!ENTITY checkbox "Check box label"> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_custom.xpi b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_custom.xpi Binary files differdeleted file mode 100644 index 6e937c5cc..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_custom.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_custom/chrome.manifest b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_custom/chrome.manifest index f1eaef1d0..f7132fc46 100644 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_custom/chrome.manifest +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_custom/chrome.manifest @@ -1,2 +1,2 @@ -content inlinesettings ./ contentaccessible=yes +content inlinesettings ./ locale inlinesettings en-US ./ diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_custom/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_custom/install.rdf index a04046a74..2bf7c6e2e 100644 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_custom/install.rdf +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_custom/install.rdf @@ -4,19 +4,11 @@ <Description about="urn:mozilla:install-manifest"> <em:id>inlinesettings1@tests.mozilla.org</em:id> <em:name>Inline Settings (Bootstrap)</em:name> - <em:version>2</em:version> + <em:version>1</em:version> <em:bootstrap>true</em:bootstrap> <em:targetApplication> <Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>0.3</em:minVersion> - <em:maxVersion>*</em:maxVersion> - </Description> - </em:targetApplication> - - <em:targetApplication> - <Description> <em:id>toolkit@mozilla.org</em:id> <em:minVersion>0</em:minVersion> <em:maxVersion>*</em:maxVersion> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_info.xpi b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_info.xpi Binary files differdeleted file mode 100644 index 4c939c05b..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_info.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_info/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_info/install.rdf index ba90bd57b..e3a054890 100644 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_info/install.rdf +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_info/install.rdf @@ -4,20 +4,12 @@ <Description about="urn:mozilla:install-manifest"> <em:id>inlinesettings1@tests.mozilla.org</em:id> <em:name>Inline Settings (Bootstrap)</em:name> - <em:version>3</em:version> + <em:version>1</em:version> <em:bootstrap>true</em:bootstrap> <em:optionsType>4</em:optionsType> <em:targetApplication> <Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>0.3</em:minVersion> - <em:maxVersion>*</em:maxVersion> - </Description> - </em:targetApplication> - - <em:targetApplication> - <Description> <em:id>toolkit@mozilla.org</em:id> <em:minVersion>0</em:minVersion> <em:maxVersion>*</em:maxVersion> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_install1_1.xpi b/toolkit/mozapps/extensions/test/browser/addons/browser_install1_1.xpi Binary files differdeleted file mode 100644 index d6df8f9d0..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_install1_1.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_install1_1/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_install1_1/install.rdf index b11b6d7e4..ba71f4c95 100644 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_install1_1/install.rdf +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_install1_1/install.rdf @@ -4,21 +4,13 @@ xmlns:em="http://www.mozilla.org/2004/em-rdf#"> <Description about="urn:mozilla:install-manifest"> - <em:id>install1@tests.mozilla.org</em:id> + <em:id>addon1@tests.mozilla.org</em:id> <em:version>1.0</em:version> <em:bootstrap>true</em:bootstrap> <em:updateURL>http://example.com/browser/toolkit/mozapps/extensions/test/browser/browser_install.rdf</em:updateURL> <em:targetApplication> <Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>0.3</em:minVersion> - <em:maxVersion>*</em:maxVersion> - </Description> - </em:targetApplication> - - <em:targetApplication> - <Description> <em:id>toolkit@mozilla.org</em:id> <em:minVersion>0</em:minVersion> <em:maxVersion>*</em:maxVersion> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_install1_2.xpi b/toolkit/mozapps/extensions/test/browser/addons/browser_install1_2.xpi Binary files differdeleted file mode 100644 index 5468e6cb0..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_install1_2.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_install1_2/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_install1_2/install.rdf index 81898b24d..4497c31e2 100644 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_install1_2/install.rdf +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_install1_2/install.rdf @@ -4,19 +4,11 @@ xmlns:em="http://www.mozilla.org/2004/em-rdf#"> <Description about="urn:mozilla:install-manifest"> - <em:id>install1@tests.mozilla.org</em:id> + <em:id>addon1@tests.mozilla.org</em:id> <em:version>2.0</em:version> <em:targetApplication> <Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>0.3</em:minVersion> - <em:maxVersion>*</em:maxVersion> - </Description> - </em:targetApplication> - - <em:targetApplication> - <Description> <em:id>toolkit@mozilla.org</em:id> <em:minVersion>0</em:minVersion> <em:maxVersion>*</em:maxVersion> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_installssl.xpi b/toolkit/mozapps/extensions/test/browser/addons/browser_installssl.xpi Binary files differdeleted file mode 100644 index 999535a97..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_installssl.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_installssl/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_installssl/install.rdf index 7ce6cd09a..0906bbe91 100644 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_installssl/install.rdf +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_installssl/install.rdf @@ -9,14 +9,6 @@ <em:targetApplication> <Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>0.3</em:minVersion> - <em:maxVersion>*</em:maxVersion> - </Description> - </em:targetApplication> - - <em:targetApplication> - <Description> <em:id>toolkit@mozilla.org</em:id> <em:minVersion>0</em:minVersion> <em:maxVersion>*</em:maxVersion> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_searching.xpi b/toolkit/mozapps/extensions/test/browser/addons/browser_searching.xpi Binary files differdeleted file mode 100644 index efef815aa..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_searching.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_searching/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_searching/install.rdf index 02cc935ea..f26f9ad80 100644 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_searching/install.rdf +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_searching/install.rdf @@ -11,8 +11,8 @@ <em:targetApplication> <Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>0.3</em:minVersion> + <em:id>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</em:id> + <em:minVersion>0</em:minVersion> <em:maxVersion>*</em:maxVersion> </Description> </em:targetApplication> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/bootstrap_1/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_select_compatoverrides_1/install.rdf index 9d08c357c..47a0e373a 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/bootstrap_1/install.rdf +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_select_compatoverrides_1/install.rdf @@ -4,21 +4,20 @@ xmlns:em="http://www.mozilla.org/2004/em-rdf#"> <Description about="urn:mozilla:install-manifest"> - <em:id>test@tests.mozilla.org</em:id> + <em:id>addon1@tests.mozilla.org</em:id> <em:version>1.0</em:version> - <em:bootstrap>true</em:bootstrap> - - <!-- Front End MetaData --> - <em:name>Test Add-on</em:name> - <em:updateURL>http://localhost:4444/update.rdf</em:updateURL> <em:targetApplication> <Description> - <em:id>xpcshell@tests.mozilla.org</em:id> - <em:minVersion>2</em:minVersion> - <em:maxVersion>5</em:maxVersion> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>0.1</em:maxVersion> </Description> </em:targetApplication> + <!-- Front End MetaData --> + <em:name>Addon1</em:name> + <em:bootstrap>true</em:bootstrap> + </Description> </RDF> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_update1_1.xpi b/toolkit/mozapps/extensions/test/browser/addons/browser_update1_1.xpi Binary files differdeleted file mode 100644 index 956812aaa..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_update1_1.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_update1_1/bootstrap.js b/toolkit/mozapps/extensions/test/browser/addons/browser_update1_1/bootstrap.js deleted file mode 100644 index ff5b80ae8..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_update1_1/bootstrap.js +++ /dev/null @@ -1,12 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -function install(data, reason) {} -function startup(data, reason) { - Components.utils.import("resource://gre/modules/Services.jsm"); - Services.ppmm.loadProcessScript( - "resource://my-addon/frame-script.js", false); -} -function shutdown(data, reason) {} -function uninstall(data, reason) {} diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_update1_1/chrome.manifest b/toolkit/mozapps/extensions/test/browser/addons/browser_update1_1/chrome.manifest deleted file mode 100644 index f1a7ccee1..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_update1_1/chrome.manifest +++ /dev/null @@ -1 +0,0 @@ -resource my-addon . diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_update1_1/frame-script.js b/toolkit/mozapps/extensions/test/browser/addons/browser_update1_1/frame-script.js deleted file mode 100644 index f4674b840..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_update1_1/frame-script.js +++ /dev/null @@ -1,6 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -Components.utils.import("resource://gre/modules/Services.jsm"); -Services.cpmm.sendAsyncMessage("my-addon-1"); diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_update1_1/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_update1_1/install.rdf deleted file mode 100644 index c52307b4a..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_update1_1/install.rdf +++ /dev/null @@ -1,31 +0,0 @@ -<?xml version="1.0"?> - -<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:em="http://www.mozilla.org/2004/em-rdf#"> - - <Description about="urn:mozilla:install-manifest"> - <em:id>update1@tests.mozilla.org</em:id> - <em:version>1.0</em:version> - <em:bootstrap>true</em:bootstrap> - - <em:targetApplication> - <Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>0.3</em:minVersion> - <em:maxVersion>*</em:maxVersion> - </Description> - </em:targetApplication> - - <em:targetApplication> - <Description> - <em:id>toolkit@mozilla.org</em:id> - <em:minVersion>0</em:minVersion> - <em:maxVersion>*</em:maxVersion> - </Description> - </em:targetApplication> - - <!-- Front End MetaData --> - <em:name>Update Tests</em:name> - - </Description> -</RDF> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_update1_2.xpi b/toolkit/mozapps/extensions/test/browser/addons/browser_update1_2.xpi Binary files differdeleted file mode 100644 index 7ef3db940..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_update1_2.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_update1_2/bootstrap.js b/toolkit/mozapps/extensions/test/browser/addons/browser_update1_2/bootstrap.js deleted file mode 100644 index ff5b80ae8..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_update1_2/bootstrap.js +++ /dev/null @@ -1,12 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -function install(data, reason) {} -function startup(data, reason) { - Components.utils.import("resource://gre/modules/Services.jsm"); - Services.ppmm.loadProcessScript( - "resource://my-addon/frame-script.js", false); -} -function shutdown(data, reason) {} -function uninstall(data, reason) {} diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_update1_2/chrome.manifest b/toolkit/mozapps/extensions/test/browser/addons/browser_update1_2/chrome.manifest deleted file mode 100644 index f1a7ccee1..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_update1_2/chrome.manifest +++ /dev/null @@ -1 +0,0 @@ -resource my-addon . diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_update1_2/frame-script.js b/toolkit/mozapps/extensions/test/browser/addons/browser_update1_2/frame-script.js deleted file mode 100644 index e35092a55..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_update1_2/frame-script.js +++ /dev/null @@ -1,6 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -Components.utils.import("resource://gre/modules/Services.jsm"); -Services.cpmm.sendAsyncMessage("my-addon-2"); diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_update1_2/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_update1_2/install.rdf deleted file mode 100644 index 2fae190b4..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_update1_2/install.rdf +++ /dev/null @@ -1,31 +0,0 @@ -<?xml version="1.0"?> - -<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:em="http://www.mozilla.org/2004/em-rdf#"> - - <Description about="urn:mozilla:install-manifest"> - <em:id>update1@tests.mozilla.org</em:id> - <em:version>2.0</em:version> - <em:bootstrap>true</em:bootstrap> - - <em:targetApplication> - <Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>0.3</em:minVersion> - <em:maxVersion>*</em:maxVersion> - </Description> - </em:targetApplication> - - <em:targetApplication> - <Description> - <em:id>toolkit@mozilla.org</em:id> - <em:minVersion>0</em:minVersion> - <em:maxVersion>*</em:maxVersion> - </Description> - </em:targetApplication> - - <!-- Front End MetaData --> - <em:name>Update Tests</em:name> - - </Description> -</RDF> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_webapi_install.xpi b/toolkit/mozapps/extensions/test/browser/addons/browser_webapi_install.xpi Binary files differdeleted file mode 100644 index 4fa7b8bfa..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_webapi_install.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_webapi_install/bootstrap.js b/toolkit/mozapps/extensions/test/browser/addons/browser_webapi_install/bootstrap.js deleted file mode 100644 index bd11077c2..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_webapi_install/bootstrap.js +++ /dev/null @@ -1,9 +0,0 @@ -Components.utils.import("resource://gre/modules/Services.jsm"); - -function startup(data, reason) { - Services.prefs.setIntPref("webapitest.active_version", 1); -} - -function shutdown(data, reason) { - Services.prefs.setIntPref("webapitest.active_version", 0); -} diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_webapi_install/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_webapi_install/install.rdf deleted file mode 100644 index 2cae124e1..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/browser_webapi_install/install.rdf +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0"?> - -<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:em="http://www.mozilla.org/2004/em-rdf#"> - - <Description about="urn:mozilla:install-manifest"> - <em:id>webapi_install@tests.mozilla.org</em:id> - <em:version>1.1</em:version> - <em:name>AddonManger web API test</em:name> - <em:bootstrap>true</em:bootstrap> - - <em:targetApplication> - <Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>0.3</em:minVersion> - <em:maxVersion>*</em:maxVersion> - </Description> - </em:targetApplication> - - <em:targetApplication> - <Description> - <em:id>toolkit@mozilla.org</em:id> - <em:minVersion>0</em:minVersion> - <em:maxVersion>*</em:maxVersion> - </Description> - </em:targetApplication> - - </Description> -</RDF> diff --git a/toolkit/mozapps/extensions/test/browser/addons/options_signed.xpi b/toolkit/mozapps/extensions/test/browser/addons/options_signed.xpi Binary files differdeleted file mode 100644 index a063fd1c4..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/options_signed.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/browser/addons/options_signed/manifest.json b/toolkit/mozapps/extensions/test/browser/addons/options_signed/manifest.json deleted file mode 100644 index e808cd5ab..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/options_signed/manifest.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "manifest_version": 2, - - "name": "Test options_ui", - "description": "Test add-ons manager handling options_ui with no id in manifest.json", - "version": "1.2", - - "options_ui": { - "page": "options.html" - } -} diff --git a/toolkit/mozapps/extensions/test/browser/addons/options_signed/options.html b/toolkit/mozapps/extensions/test/browser/addons/options_signed/options.html deleted file mode 100644 index ea804601b..000000000 --- a/toolkit/mozapps/extensions/test/browser/addons/options_signed/options.html +++ /dev/null @@ -1,9 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <meta charset="utf-8" /> - </head> - <body> - <div id="options-test-panel" /> - </body> -</html> diff --git a/toolkit/mozapps/extensions/test/browser/browser-common.ini b/toolkit/mozapps/extensions/test/browser/browser-common.ini index eda266e2f..3e88833ef 100644 --- a/toolkit/mozapps/extensions/test/browser/browser-common.ini +++ b/toolkit/mozapps/extensions/test/browser/browser-common.ini @@ -1,19 +1,23 @@ +[DEFAULT] +support-files = + head.js + [browser_about.js] skip-if = os == 'linux' || os == 'win' # bug 632290 [browser_bug523784.js] [browser_bug557943.js] [browser_bug562797.js] +skip-if = e10s # Bug 933103 - mochitest's EventUtils.synthesizeMouse functions not e10s friendly [browser_bug562854.js] [browser_bug562890.js] -skip-if = os == 'win' && !debug # Disabled on Windows opt/PGO builds due to intermittent failures (bug 1135866) [browser_bug562899.js] skip-if = buildapp == 'mulet' [browser_bug562992.js] [browser_bug567127.js] [browser_bug567137.js] [browser_bug570760.js] +skip-if = e10s # Bug ?????? - EventUtils.synthesizeKey not e10s friendly [browser_bug572561.js] -[browser_bug573062.js] [browser_bug577990.js] [browser_bug580298.js] [browser_bug581076.js] @@ -30,38 +34,43 @@ skip-if = true # Bug 1093190 - Disabled due to leak [browser_bug679604.js] [browser_bug714593.js] [browser_bug590347.js] +[browser_debug_button.js] [browser_details.js] [browser_discovery.js] +skip-if = e10s # Bug ?????? - test times out on try on all platforms, but works locally for markh! [browser_dragdrop.js] -skip-if = buildapp == 'mulet' -[browser_experiments.js] +skip-if = e10s [browser_list.js] [browser_metadataTimeout.js] [browser_searching.js] [browser_sorting.js] [browser_sorting_plugins.js] [browser_plugin_enabled_state_locked.js] +skip-if = e10s # Bug ?????? - leaked until shutdown [nsGlobalWindow #1760 about:blank] [browser_uninstalling.js] +skip-if = e10s # Bug ?????? - leaked until shutdown [nsGlobalWindow #1760 about:blank] [browser_install.js] [browser_recentupdates.js] [browser_manualupdates.js] [browser_globalwarnings.js] +[browser_globalinformations.js] +skip-if = e10s # Bug 933103 - mochitest's EventUtils.synthesizeMouse functions not e10s friendly [browser_eula.js] skip-if = buildapp == 'mulet' [browser_updateid.js] +skip-if = e10s # Bug ?????? - window leak reported at end of test run. [browser_purchase.js] +skip-if = e10s # Bug 933103 - mochitest's EventUtils.synthesizeMouse functions not e10s friendly [browser_openDialog.js] -tags = openwindow -skip-if = os == 'win' # Disabled on Windows due to intermittent failures (bug 1135866) +skip-if = e10s [browser_types.js] +skip-if = e10s # Bug ?????? - leaked until shutdown [nsGlobalWindow #1760 about:blank] [browser_inlinesettings.js] -[browser_inlinesettings_browser.js] [browser_inlinesettings_custom.js] [browser_inlinesettings_info.js] [browser_tabsettings.js] +skip-if = e10s # Bug ?????? - leaked until shutdown [nsGlobalWindow #1760 about:blank] [browser_pluginprefs.js] skip-if = buildapp == 'mulet' [browser_CTP_plugins.js] -skip-if = buildapp == 'mulet' -[browser_webext_options.js] -tags = webextensions +skip-if = buildapp == 'mulet' || e10s # Bug 899347 - no e10s click-to-play support diff --git a/toolkit/mozapps/extensions/test/browser/browser-window.ini b/toolkit/mozapps/extensions/test/browser/browser-window.ini index fcda90fc6..95494eb3e 100644 --- a/toolkit/mozapps/extensions/test/browser/browser-window.ini +++ b/toolkit/mozapps/extensions/test/browser/browser-window.ini @@ -1,52 +1,4 @@ [DEFAULT] install-to-subdir = test-window -support-files = - addons/* - addon_about.xul - addon_prefs.xul - cancelCompatCheck.sjs - discovery.html - discovery_frame.html - discovery_install.html - head.js - signed_hotfix.rdf - signed_hotfix.xpi - unsigned_hotfix.rdf - unsigned_hotfix.xpi - more_options.xul - options.xul - plugin_test.html - redirect.sjs - releaseNotes.xhtml - blockNoPlugins.xml - blockPluginHard.xml - browser_bug557956.rdf - browser_bug557956_8_2.xpi - browser_bug557956_9_2.xpi - browser_bug557956.xml - browser_bug591465.xml - browser_bug593535.xml - browser_searching.xml - browser_searching_empty.xml - browser_updatessl.rdf - browser_updatessl.rdf^headers^ - browser_install.rdf - browser_install.rdf^headers^ - browser_install.xml - browser_install1_3.xpi - browser_eula.xml - browser_purchase.xml - webapi_addon_listener.html - webapi_checkavailable.html - webapi_checkchromeframe.xul - webapi_checkframed.html - webapi_checknavigatedwindow.html - !/toolkit/mozapps/extensions/test/xpinstall/corrupt.xpi - !/toolkit/mozapps/extensions/test/xpinstall/incompatible.xpi - !/toolkit/mozapps/extensions/test/xpinstall/installtrigger.html - !/toolkit/mozapps/extensions/test/xpinstall/restartless.xpi - !/toolkit/mozapps/extensions/test/xpinstall/theme.xpi - !/toolkit/mozapps/extensions/test/xpinstall/unsigned.xpi - !/toolkit/mozapps/extensions/test/xpinstall/amosigned.xpi [include:browser-common.ini] diff --git a/toolkit/mozapps/extensions/test/browser/browser.ini b/toolkit/mozapps/extensions/test/browser/browser.ini index a23841d33..dc6f86bd6 100644 --- a/toolkit/mozapps/extensions/test/browser/browser.ini +++ b/toolkit/mozapps/extensions/test/browser/browser.ini @@ -1,18 +1,12 @@ [DEFAULT] -tags = addons +skip-if = buildapp == 'mulet' support-files = - addons/* addon_about.xul addon_prefs.xul cancelCompatCheck.sjs discovery.html discovery_frame.html discovery_install.html - head.js - signed_hotfix.rdf - signed_hotfix.xpi - unsigned_hotfix.rdf - unsigned_hotfix.xpi more_options.xul options.xul plugin_test.html @@ -28,6 +22,7 @@ support-files = browser_bug593535.xml browser_searching.xml browser_searching_empty.xml + browser_select_compatoverrides.xml browser_updatessl.rdf browser_updatessl.rdf^headers^ browser_install.rdf @@ -36,40 +31,23 @@ support-files = browser_install1_3.xpi browser_eula.xml browser_purchase.xml - webapi_addon_listener.html - webapi_checkavailable.html - webapi_checkchromeframe.xul - webapi_checkframed.html - webapi_checknavigatedwindow.html - !/toolkit/mozapps/extensions/test/xpinstall/corrupt.xpi - !/toolkit/mozapps/extensions/test/xpinstall/incompatible.xpi - !/toolkit/mozapps/extensions/test/xpinstall/installtrigger.html - !/toolkit/mozapps/extensions/test/xpinstall/restartless.xpi - !/toolkit/mozapps/extensions/test/xpinstall/theme.xpi - !/toolkit/mozapps/extensions/test/xpinstall/unsigned.xpi - !/toolkit/mozapps/extensions/test/xpinstall/amosigned.xpi [browser_addonrepository_performance.js] [browser_bug557956.js] +skip-if = e10s [browser_bug616841.js] [browser_cancelCompatCheck.js] [browser_checkAddonCompatibility.js] [browser_gmpProvider.js] -[browser_hotfix.js] -# Verifies the old style of signing hotfixes -skip-if = require_signing [browser_installssl.js] [browser_newaddon.js] +skip-if = e10s +[browser_select_compatoverrides.js] +[browser_select_confirm.js] +[browser_select_selection.js] +[browser_select_update.js] [browser_updatessl.js] -[browser_system_addons_are_e10s.js] [browser_task_next_test.js] [browser_discovery_install.js] -[browser_update.js] -[browser_webapi.js] -[browser_webapi_access.js] -[browser_webapi_addon_listener.js] -[browser_webapi_enable.js] -[browser_webapi_install.js] -[browser_webapi_uninstall.js] [include:browser-common.ini] diff --git a/toolkit/mozapps/extensions/test/browser/browser_CTP_plugins.js b/toolkit/mozapps/extensions/test/browser/browser_CTP_plugins.js index dd2992f81..1b119ca5b 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_CTP_plugins.js +++ b/toolkit/mozapps/extensions/test/browser/browser_CTP_plugins.js @@ -1,4 +1,11 @@ +/* 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/. */ + const gHttpTestRoot = "http://127.0.0.1:8888/" + RELATIVE_DIR + "/"; +let gManagerWindow; +let gTestPluginId; +let gPluginBrowser; function updateBlocklist(aCallback) { var blocklistNotifier = Cc["@mozilla.org/extensions/blocklist;1"] @@ -24,149 +31,204 @@ function resetBlocklist(aCallback) { Services.prefs.setCharPref("extensions.blocklist.url", _originalBlocklistURL); } -add_task(function*() { - SpecialPowers.pushPrefEnv({"set": [ - ["plugins.click_to_play", true], - ["extensions.blocklist.suppressUI", true] - ]}); - registerCleanupFunction(function*() { - let pluginTag = getTestPluginTag(); - pluginTag.enabledState = Ci.nsIPluginTag.STATE_ENABLED; - yield new Promise(resolve => { - setAndUpdateBlocklist(gHttpTestRoot + "blockNoPlugins.xml", resolve); - }); - resetBlocklist(); - }); - +function test() { + waitForExplicitFinish(); + Services.prefs.setBoolPref("plugins.click_to_play", true); + Services.prefs.setBoolPref("extensions.blocklist.suppressUI", true); let pluginTag = getTestPluginTag(); pluginTag.enabledState = Ci.nsIPluginTag.STATE_CLICKTOPLAY; - let managerWindow = yield new Promise(resolve => open_manager("addons://list/plugin", resolve)); + open_manager("addons://list/plugin", part1); +} - let plugins = yield new Promise(resolve => AddonManager.getAddonsByTypes(["plugin"], resolve)); +function part1(aWindow) { + gManagerWindow = aWindow; + AddonManager.getAddonsByTypes(["plugin"], part2); +} - let testPluginId; - for (let plugin of plugins) { +function part2(aPlugins) { + for (let plugin of aPlugins) { if (plugin.name == "Test Plug-in") { - testPluginId = plugin.id; + gTestPluginId = plugin.id; break; } } - ok(testPluginId, "part2: Test Plug-in should exist"); - - let testPlugin = yield new Promise(resolve => AddonManager.getAddonByID(testPluginId, resolve)); + ok(gTestPluginId, "part2: Test Plug-in should exist"); + AddonManager.getAddonByID(gTestPluginId, part3); +} - let pluginEl = get_addon_element(managerWindow, testPluginId); +function part3(aTestPlugin) { + let pluginEl = get_addon_element(gManagerWindow, gTestPluginId); pluginEl.parentNode.ensureElementIsVisible(pluginEl); - let enableButton = managerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "enable-btn"); + let enableButton = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "enable-btn"); is_element_hidden(enableButton, "part3: enable button should not be visible"); - let disableButton = managerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "enable-btn"); + let disableButton = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "enable-btn"); is_element_hidden(disableButton, "part3: disable button should not be visible"); - let menu = managerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "state-menulist"); + let menu = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "state-menulist"); is_element_visible(menu, "part3: state menu should be visible"); - let askToActivateItem = managerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "ask-to-activate-menuitem"); + let askToActivateItem = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "ask-to-activate-menuitem"); is(menu.selectedItem, askToActivateItem, "part3: state menu should have 'Ask To Activate' selected"); - let pluginTab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, gHttpTestRoot + "plugin_test.html"); - let pluginBrowser = pluginTab.linkedBrowser; - - let condition = () => PopupNotifications.getNotification("click-to-play-plugins", pluginBrowser); - yield BrowserTestUtils.waitForCondition(condition, "part4: should have a click-to-play notification"); - - yield BrowserTestUtils.removeTab(pluginTab); - - let alwaysActivateItem = managerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "always-activate-menuitem"); - menu.selectedItem = alwaysActivateItem; - alwaysActivateItem.doCommand(); - - pluginTab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, gHttpTestRoot + "plugin_test.html"); + gBrowser.selectedTab = gBrowser.addTab(); + gPluginBrowser = gBrowser.selectedBrowser; + gPluginBrowser.addEventListener("PluginBindingAttached", part4, true, true); + gPluginBrowser.contentWindow.location = gHttpTestRoot + "plugin_test.html"; +} - yield ContentTask.spawn(pluginTab.linkedBrowser, null, function*() { - let testPlugin = content.document.getElementById("test"); - ok(testPlugin, "part5: should have a plugin element in the page"); - let objLoadingContent = testPlugin.QueryInterface(Ci.nsIObjectLoadingContent); - let condition = () => objLoadingContent.activated; - yield ContentTaskUtils.waitForCondition(condition, "part5: waited too long for plugin to activate"); - ok(objLoadingContent.activated, "part6: plugin should be activated"); - }); +function part4() { + let condition = () => PopupNotifications.getNotification("click-to-play-plugins", gPluginBrowser); + waitForCondition(condition, () => { + gPluginBrowser.removeEventListener("PluginBindingAttached", part4); + gBrowser.removeCurrentTab(); + + let pluginEl = get_addon_element(gManagerWindow, gTestPluginId); + let menu = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "state-menulist"); + let alwaysActivateItem = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "always-activate-menuitem"); + menu.selectedItem = alwaysActivateItem; + alwaysActivateItem.doCommand(); + gBrowser.selectedTab = gBrowser.addTab(); + gPluginBrowser = gBrowser.selectedBrowser; + gPluginBrowser.addEventListener("load", part5, true); + gPluginBrowser.contentWindow.location = gHttpTestRoot + "plugin_test.html"; + }, "part4: should have a click-to-play notification"); +} - yield BrowserTestUtils.removeTab(pluginTab); +function part5() { + let testPlugin = gPluginBrowser.contentDocument.getElementById("test"); + ok(testPlugin, "part5: should have a plugin element in the page"); + let objLoadingContent = testPlugin.QueryInterface(Ci.nsIObjectLoadingContent); + let condition = function() objLoadingContent.activated; + waitForCondition(condition, part6, "part5: waited too long for plugin to activate"); +} - let neverActivateItem = managerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "never-activate-menuitem"); +function part6() { + let testPlugin = gPluginBrowser.contentDocument.getElementById("test"); + ok(testPlugin, "part6: should have a plugin element in the page"); + let objLoadingContent = testPlugin.QueryInterface(Ci.nsIObjectLoadingContent); + ok(objLoadingContent.activated, "part6: plugin should be activated"); + gPluginBrowser.removeEventListener("load", part5); + gBrowser.removeCurrentTab(); + + let pluginEl = get_addon_element(gManagerWindow, gTestPluginId); + let menu = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "state-menulist"); + let neverActivateItem = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "never-activate-menuitem"); menu.selectedItem = neverActivateItem; neverActivateItem.doCommand(); + gBrowser.selectedTab = gBrowser.addTab(); + gPluginBrowser = gBrowser.selectedBrowser; + gPluginBrowser.addEventListener("PluginBindingAttached", part7, true, true); + gPluginBrowser.contentWindow.location = gHttpTestRoot + "plugin_test.html"; +} - pluginTab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, gHttpTestRoot + "plugin_test.html"); - pluginBrowser = pluginTab.linkedBrowser; - - yield ContentTask.spawn(pluginTab.linkedBrowser, null, function*() { - let testPlugin = content.document.getElementById("test"); +function part7() { + let condition = () => PopupNotifications.getNotification("click-to-play-plugins", gPluginBrowser); + waitForCondition(condition, () => { + let testPlugin = gPluginBrowser.contentDocument.getElementById("test"); ok(testPlugin, "part7: should have a plugin element in the page"); let objLoadingContent = testPlugin.QueryInterface(Ci.nsIObjectLoadingContent); ok(!objLoadingContent.activated, "part7: plugin should not be activated"); - }); - yield BrowserTestUtils.removeTab(pluginTab); + gPluginBrowser.removeEventListener("PluginBindingAttached", part7); + gBrowser.removeCurrentTab(); - let details = managerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "details-btn"); - is_element_visible(details, "part7: details link should be visible"); - EventUtils.synthesizeMouseAtCenter(details, {}, managerWindow); - yield BrowserTestUtils.waitForEvent(managerWindow.document, "ViewChanged"); + let pluginEl = get_addon_element(gManagerWindow, gTestPluginId); + let details = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "details-btn"); + is_element_visible(details, "part7: details link should be visible"); + EventUtils.synthesizeMouseAtCenter(details, {}, gManagerWindow); + wait_for_view_load(gManagerWindow, part8); + }, "part7: disabled plugins still show a notification"); +} +function part8() { + let enableButton = gManagerWindow.document.getElementById("detail-enable-btn"); is_element_hidden(enableButton, "part8: detail enable button should be hidden"); + let disableButton = gManagerWindow.document.getElementById("detail-disable-btn"); is_element_hidden(disableButton, "part8: detail disable button should be hidden"); + let menu = gManagerWindow.document.getElementById("detail-state-menulist"); is_element_visible(menu, "part8: detail state menu should be visible"); + let neverActivateItem = gManagerWindow.document.getElementById("detail-never-activate-menuitem"); is(menu.selectedItem, neverActivateItem, "part8: state menu should have 'Never Activate' selected"); + let alwaysActivateItem = gManagerWindow.document.getElementById("detail-always-activate-menuitem"); menu.selectedItem = alwaysActivateItem; alwaysActivateItem.doCommand(); + gBrowser.selectedTab = gBrowser.addTab(); + gPluginBrowser = gBrowser.selectedBrowser; + gPluginBrowser.addEventListener("load", part9, true); + gPluginBrowser.contentWindow.location = gHttpTestRoot + "plugin_test.html"; +} - pluginTab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, gHttpTestRoot + "plugin_test.html"); - pluginBrowser = pluginTab.linkedBrowser; - - yield ContentTask.spawn(pluginTab.linkedBrowser, null, function*() { - let testPlugin = content.document.getElementById("test"); - ok(testPlugin, "part9: should have a plugin element in the page"); - let objLoadingContent = testPlugin.QueryInterface(Ci.nsIObjectLoadingContent); - let condition = () => objLoadingContent.activated; - yield ContentTaskUtils.waitForCondition(condition, "part9: waited too long for plugin to activate"); - ok(objLoadingContent.activated, "part10: plugin should be activated"); - }); +function part9() { + let testPlugin = gPluginBrowser.contentDocument.getElementById("test"); + ok(testPlugin, "part9: should have a plugin element in the page"); + let objLoadingContent = testPlugin.QueryInterface(Ci.nsIObjectLoadingContent); + let condition = function() objLoadingContent.activated; + waitForCondition(condition, part10, "part9: waited too long for plugin to activate"); +} - yield BrowserTestUtils.removeTab(pluginTab); +function part10() { + let testPlugin = gPluginBrowser.contentDocument.getElementById("test"); + ok(testPlugin, "part10: should have a plugin element in the page"); + let objLoadingContent = testPlugin.QueryInterface(Ci.nsIObjectLoadingContent); + ok(objLoadingContent.activated, "part10: plugin should be activated"); + gPluginBrowser.removeEventListener("load", part9); + gBrowser.removeCurrentTab(); + let menu = gManagerWindow.document.getElementById("detail-state-menulist"); + let askToActivateItem = gManagerWindow.document.getElementById("detail-ask-to-activate-menuitem"); menu.selectedItem = askToActivateItem; askToActivateItem.doCommand(); + gBrowser.selectedTab = gBrowser.addTab(); + gPluginBrowser = gBrowser.selectedBrowser; + gPluginBrowser.addEventListener("PluginBindingAttached", part11, true, true); + gPluginBrowser.contentWindow.location = gHttpTestRoot + "plugin_test.html"; +} - pluginTab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, gHttpTestRoot + "plugin_test.html"); - pluginBrowser = pluginTab.linkedBrowser; - - condition = () => PopupNotifications.getNotification("click-to-play-plugins", pluginBrowser); - yield BrowserTestUtils.waitForCondition(condition, "part11: should have a click-to-play notification"); +function part11() { + let condition = () => PopupNotifications.getNotification("click-to-play-plugins", gPluginBrowser); + waitForCondition(condition, () => { + gPluginBrowser.removeEventListener("PluginBindingAttached", part11); + gBrowser.removeCurrentTab(); - yield BrowserTestUtils.removeTab(pluginTab); + let pluginTag = getTestPluginTag(); // causes appDisabled to be set - managerWindow = yield new Promise(resolve => { setAndUpdateBlocklist(gHttpTestRoot + "blockPluginHard.xml", - () => { - close_manager(managerWindow, function() { - open_manager("addons://list/plugin", resolve); - }); - } - ); - }); + function() { + close_manager(gManagerWindow, function() { + open_manager("addons://list/plugin", part12); + }); + }); + }, "part11: should have a click-to-play notification"); +} - pluginEl = get_addon_element(managerWindow, testPluginId); +function part12(aWindow) { + gManagerWindow = aWindow; + let pluginEl = get_addon_element(gManagerWindow, gTestPluginId); pluginEl.parentNode.ensureElementIsVisible(pluginEl); - menu = managerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "state-menulist"); + let menu = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "state-menulist"); is(menu.disabled, true, "part12: state menu should be disabled"); - details = managerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "details-btn"); - EventUtils.synthesizeMouseAtCenter(details, {}, managerWindow); - yield BrowserTestUtils.waitForEvent(managerWindow.document, "ViewChanged"); + let details = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "details-btn"); + EventUtils.synthesizeMouseAtCenter(details, {}, gManagerWindow); + wait_for_view_load(gManagerWindow, part13); +} - menu = managerWindow.document.getElementById("detail-state-menulist"); +function part13() { + let menu = gManagerWindow.document.getElementById("detail-state-menulist"); is(menu.disabled, true, "part13: detail state menu should be disabled"); - managerWindow.close(); -}); + setAndUpdateBlocklist(gHttpTestRoot + "blockNoPlugins.xml", function() { + run_next_test(); + }); +} + +function end_test() { + Services.prefs.clearUserPref("plugins.click_to_play"); + Services.prefs.clearUserPref("extensions.blocklist.suppressUI"); + let pluginTag = getTestPluginTag(); + pluginTag.enabledState = Ci.nsIPluginTag.STATE_ENABLED; + resetBlocklist(); + close_manager(gManagerWindow, function() { + finish(); + }); +} diff --git a/toolkit/mozapps/extensions/test/browser/browser_addonrepository_performance.js b/toolkit/mozapps/extensions/test/browser/browser_addonrepository_performance.js index 879d7331e..0ba3127cd 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_addonrepository_performance.js +++ b/toolkit/mozapps/extensions/test/browser/browser_addonrepository_performance.js @@ -4,9 +4,9 @@ // Tests that the metadata request includes startup time measurements -var tmp = {}; +let tmp = {}; Components.utils.import("resource://gre/modules/addons/AddonRepository.jsm", tmp); -var AddonRepository = tmp.AddonRepository; +let AddonRepository = tmp.AddonRepository; var gTelemetry = Cc["@mozilla.org/base/telemetry;1"].getService(Ci.nsITelemetry); var gManagerWindow; diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug523784.js b/toolkit/mozapps/extensions/test/browser/browser_bug523784.js index e61fafd6b..c467e5cc0 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug523784.js +++ b/toolkit/mozapps/extensions/test/browser/browser_bug523784.js @@ -6,7 +6,7 @@ const URI_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul" // This tests that the blocklist dialog still affects soft-blocked add-ons // if the user clicks the "Restart Later" button. It also ensures that the // "Cancel" button is correctly renamed (to "Restart Later"). -var args = { +let args = { restart: false, list: [{ name: "Bug 523784 softblocked addon", @@ -31,7 +31,7 @@ function test() { win.addEventListener("load", function() { win.removeEventListener("load", arguments.callee, false); - executeSoon(() => bug523784_test1(win)); + executeSoon(function() bug523784_test1(win)); }, false); }; Services.ww.registerNotification(windowObserver); @@ -82,7 +82,7 @@ function bug523784_test2(win) { win.addEventListener("load", function() { win.removeEventListener("load", arguments.callee, false); - executeSoon(function() { + executeSoon(function(){ let moreInfoLink = win.document.getElementById("moreInfo"); let cancelButton = win.document.documentElement.getButton("cancel"); is(moreInfoLink.getAttribute("href"), diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug557956.js b/toolkit/mozapps/extensions/test/browser/browser_bug557956.js index 136e7cb74..919564b45 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug557956.js +++ b/toolkit/mozapps/extensions/test/browser/browser_bug557956.js @@ -8,14 +8,13 @@ const URI_EXTENSION_UPDATE_DIALOG = "chrome://mozapps/content/extensions/update.xul"; const PREF_GETADDONS_BYIDS = "extensions.getAddons.get.url"; -const PREF_MIN_APP_COMPAT = "extensions.minCompatibleAppVersion"; const PREF_MIN_PLATFORM_COMPAT = "extensions.minCompatiblePlatformVersion"; Services.prefs.setBoolPref(PREF_STRICT_COMPAT, true); // avoid the 'leaked window property' check -var scope = {}; +let scope = {}; Components.utils.import("resource://gre/modules/TelemetrySession.jsm", scope); -var TelemetrySession = scope.TelemetrySession; +let TelemetrySession = scope.TelemetrySession; /** * Test add-ons: @@ -45,9 +44,6 @@ function end_test() { for (let install of aInstalls) install.cancel(); - Services.prefs.clearUserPref(PREF_MIN_APP_COMPAT); - Services.prefs.clearUserPref(PREF_MIN_PLATFORM_COMPAT); - finish(); }); } @@ -95,16 +91,16 @@ function install_test_addons(aCallback) { } function uninstall_test_addons(aCallback) { - AddonManager.getAddonsByIDs(["bug557956-1@tests.mozilla.org", - "bug557956-2@tests.mozilla.org", - "bug557956-3@tests.mozilla.org", - "bug557956-4@tests.mozilla.org", - "bug557956-5@tests.mozilla.org", - "bug557956-6@tests.mozilla.org", - "bug557956-7@tests.mozilla.org", - "bug557956-8@tests.mozilla.org", - "bug557956-9@tests.mozilla.org", - "bug557956-10@tests.mozilla.org"], + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org", + "addon5@tests.mozilla.org", + "addon6@tests.mozilla.org", + "addon7@tests.mozilla.org", + "addon8@tests.mozilla.org", + "addon9@tests.mozilla.org", + "addon10@tests.mozilla.org"], function(aAddons) { for (let addon of aAddons) { if (addon) @@ -198,12 +194,7 @@ function check_telemetry({disabled, metaenabled, metadisabled, upgraded, failed, } add_test(function test_setup() { - let oldCanRecord = Services.telemetry.canRecordExtended; - Services.telemetry.canRecordExtended = true; - registerCleanupFunction(function () { - Services.telemetry.canRecordExtended = oldCanRecord; - }); - run_next_test(); + TelemetrySession.setup().then(run_next_test); }); // Tests that the right add-ons show up in the mismatch dialog and updates can @@ -212,19 +203,19 @@ add_test(function basic_mismatch() { install_test_addons(function() { // These add-ons become disabled var disabledAddonIds = [ - "bug557956-3@tests.mozilla.org", - "bug557956-6@tests.mozilla.org", - "bug557956-7@tests.mozilla.org", - "bug557956-8@tests.mozilla.org", - "bug557956-9@tests.mozilla.org" + "addon3@tests.mozilla.org", + "addon6@tests.mozilla.org", + "addon7@tests.mozilla.org", + "addon8@tests.mozilla.org", + "addon9@tests.mozilla.org" ]; - AddonManager.getAddonsByIDs(["bug557956-5@tests.mozilla.org", - "bug557956-6@tests.mozilla.org"], + AddonManager.getAddonsByIDs(["addon5@tests.mozilla.org", + "addon6@tests.mozilla.org"], function([a5, a6]) { // Check starting (pre-update) conditions - ok(!a5.isCompatible, "bug557956-5 should not be compatible"); - ok(!a6.isCompatible, "bug557956-6 should not be compatible"); + ok(!a5.isCompatible, "addon5 should not be compatible"); + ok(!a6.isCompatible, "addon6 should not be compatible"); open_compatibility_window(disabledAddonIds, function(aWindow) { var doc = aWindow.document; @@ -238,8 +229,8 @@ add_test(function basic_mismatch() { is(items[3], "Addon9 1.0", "Should have seen addon9 still incompatible"); // If it wasn't disabled by this run, we don't try to enable it - ok(!a5.isCompatible, "bug557956-5 should not be compatible"); - ok(a6.isCompatible, "bug557956-6 should be compatible"); + ok(!a5.isCompatible, "addon5 should not be compatible"); + ok(a6.isCompatible, "addon6 should be compatible"); var button = doc.documentElement.getButton("next"); EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow); @@ -281,12 +272,12 @@ add_test(function basic_mismatch() { EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow); wait_for_window_close(aWindow, function() { - AddonManager.getAddonsByIDs(["bug557956-8@tests.mozilla.org", - "bug557956-9@tests.mozilla.org"], + AddonManager.getAddonsByIDs(["addon8@tests.mozilla.org", + "addon9@tests.mozilla.org"], function([a8, a9]) { - is(a8.version, "2.0", "bug557956-8 should have updated"); - is(a9.version, "2.0", "bug557956-9 should have updated"); - + is(a8.version, "2.0", "addon8 should have updated"); + is(a9.version, "2.0", "addon9 should have updated"); + check_telemetry({disabled: 5, metaenabled: 1, metadisabled: 0, upgraded: 2, failed: 0, declined: 1}); @@ -307,11 +298,11 @@ add_test(function failure_page() { install_test_addons(function() { // These add-ons become disabled var disabledAddonIds = [ - "bug557956-3@tests.mozilla.org", - "bug557956-6@tests.mozilla.org", - "bug557956-7@tests.mozilla.org", - "bug557956-8@tests.mozilla.org", - "bug557956-9@tests.mozilla.org" + "addon3@tests.mozilla.org", + "addon6@tests.mozilla.org", + "addon7@tests.mozilla.org", + "addon8@tests.mozilla.org", + "addon9@tests.mozilla.org" ]; Services.prefs.setBoolPref("xpinstall.enabled", false); @@ -327,11 +318,11 @@ add_test(function failure_page() { is(items[3], "Addon9 1.0", "Should have seen addon9 still incompatible"); // Check that compatibility updates were applied. - AddonManager.getAddonsByIDs(["bug557956-5@tests.mozilla.org", - "bug557956-6@tests.mozilla.org"], + AddonManager.getAddonsByIDs(["addon5@tests.mozilla.org", + "addon6@tests.mozilla.org"], function([a5, a6]) { - ok(!a5.isCompatible, "bug557956-5 should not be compatible"); - ok(a6.isCompatible, "bug557956-6 should be compatible"); + ok(!a5.isCompatible, "addon5 should not be compatible"); + ok(a6.isCompatible, "addon6 should be compatible"); var button = doc.documentElement.getButton("next"); EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow); @@ -389,16 +380,16 @@ add_test(function failure_page() { // Tests that no add-ons show up in the mismatch dialog when they are all disabled add_test(function all_disabled() { install_test_addons(function() { - AddonManager.getAddonsByIDs(["bug557956-1@tests.mozilla.org", - "bug557956-2@tests.mozilla.org", - "bug557956-3@tests.mozilla.org", - "bug557956-4@tests.mozilla.org", - "bug557956-5@tests.mozilla.org", - "bug557956-6@tests.mozilla.org", - "bug557956-7@tests.mozilla.org", - "bug557956-8@tests.mozilla.org", - "bug557956-9@tests.mozilla.org", - "bug557956-10@tests.mozilla.org"], + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org", + "addon5@tests.mozilla.org", + "addon6@tests.mozilla.org", + "addon7@tests.mozilla.org", + "addon8@tests.mozilla.org", + "addon9@tests.mozilla.org", + "addon10@tests.mozilla.org"], function(aAddons) { for (let addon of aAddons) addon.userDisabled = true; @@ -416,19 +407,19 @@ add_test(function all_disabled() { // Tests that the right UI shows for when no updates are available add_test(function no_updates() { install_test_addons(function() { - AddonManager.getAddonsByIDs(["bug557956-7@tests.mozilla.org", - "bug557956-8@tests.mozilla.org", - "bug557956-9@tests.mozilla.org", - "bug557956-10@tests.mozilla.org"], + AddonManager.getAddonsByIDs(["addon7@tests.mozilla.org", + "addon8@tests.mozilla.org", + "addon9@tests.mozilla.org", + "addon10@tests.mozilla.org"], function(aAddons) { for (let addon of aAddons) addon.uninstall(); // These add-ons were disabled by the upgrade var inactiveAddonIds = [ - "bug557956-3@tests.mozilla.org", - "bug557956-5@tests.mozilla.org", - "bug557956-6@tests.mozilla.org" + "addon3@tests.mozilla.org", + "addon5@tests.mozilla.org", + "addon6@tests.mozilla.org" ]; open_compatibility_window(inactiveAddonIds, function(aWindow) { @@ -462,7 +453,6 @@ add_test(function no_updates() { // compatibility. add_test(function overrides_retrieved() { Services.prefs.setBoolPref(PREF_STRICT_COMPAT, false); - Services.prefs.setCharPref(PREF_MIN_APP_COMPAT, "0"); Services.prefs.setCharPref(PREF_MIN_PLATFORM_COMPAT, "0"); is(AddonManager.strictCompatibility, false, "Strict compatibility should be disabled"); @@ -471,20 +461,20 @@ add_test(function overrides_retrieved() { install_test_addons(function() { - AddonManager.getAddonsByIDs(["bug557956-1@tests.mozilla.org", - "bug557956-2@tests.mozilla.org", - "bug557956-3@tests.mozilla.org", - "bug557956-4@tests.mozilla.org", - "bug557956-5@tests.mozilla.org", - "bug557956-6@tests.mozilla.org", - "bug557956-7@tests.mozilla.org", - "bug557956-8@tests.mozilla.org", - "bug557956-9@tests.mozilla.org", - "bug557956-10@tests.mozilla.org"], + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org", + "addon5@tests.mozilla.org", + "addon6@tests.mozilla.org", + "addon7@tests.mozilla.org", + "addon8@tests.mozilla.org", + "addon9@tests.mozilla.org", + "addon10@tests.mozilla.org"], function(aAddons) { for (let addon of aAddons) { - if (addon.id == "bug557956-10@tests.mozilla.org") + if (addon.id == "addon10@tests.mozilla.org") is(addon.isCompatible, true, "Addon10 should be compatible before compat overrides are refreshed"); else addon.uninstall(); @@ -522,3 +512,7 @@ add_test(function overrides_retrieved() { }); }); }); + +add_test(function test_shutdown() { + TelemetrySession.shutdown().then(run_next_test); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug557956.rdf b/toolkit/mozapps/extensions/test/browser/browser_bug557956.rdf index c72eb9363..eebf6c0f9 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug557956.rdf +++ b/toolkit/mozapps/extensions/test/browser/browser_bug557956.rdf @@ -3,7 +3,7 @@ <RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#"> - <RDF:Description about="urn:mozilla:extension:bug557956-1@tests.mozilla.org"> + <RDF:Description about="urn:mozilla:extension:addon1@tests.mozilla.org"> <em:updates> <RDF:Seq> <RDF:li> @@ -11,13 +11,6 @@ <em:version>1.0</em:version> <em:targetApplication> <RDF:Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>0</em:minVersion> - <em:maxVersion>*</em:maxVersion> - </RDF:Description> - </em:targetApplication> - <em:targetApplication> - <RDF:Description> <em:id>toolkit@mozilla.org</em:id> <em:minVersion>0</em:minVersion> <em:maxVersion>*</em:maxVersion> @@ -29,7 +22,7 @@ </em:updates> </RDF:Description> - <RDF:Description about="urn:mozilla:extension:bug557956-2@tests.mozilla.org"> + <RDF:Description about="urn:mozilla:extension:addon2@tests.mozilla.org"> <em:updates> <RDF:Seq> <RDF:li> @@ -37,13 +30,6 @@ <em:version>1.0</em:version> <em:targetApplication> <RDF:Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>0</em:minVersion> - <em:maxVersion>0</em:maxVersion> - </RDF:Description> - </em:targetApplication> - <em:targetApplication> - <RDF:Description> <em:id>toolkit@mozilla.org</em:id> <em:minVersion>0</em:minVersion> <em:maxVersion>0</em:maxVersion> @@ -55,7 +41,7 @@ </em:updates> </RDF:Description> - <RDF:Description about="urn:mozilla:extension:bug557956-3@tests.mozilla.org"> + <RDF:Description about="urn:mozilla:extension:addon3@tests.mozilla.org"> <em:updates> <RDF:Seq> <RDF:li> @@ -63,13 +49,6 @@ <em:version>1.0</em:version> <em:targetApplication> <RDF:Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>0</em:minVersion> - <em:maxVersion>0</em:maxVersion> - </RDF:Description> - </em:targetApplication> - <em:targetApplication> - <RDF:Description> <em:id>toolkit@mozilla.org</em:id> <em:minVersion>0</em:minVersion> <em:maxVersion>0</em:maxVersion> @@ -81,7 +60,7 @@ </em:updates> </RDF:Description> - <RDF:Description about="urn:mozilla:extension:bug557956-4@tests.mozilla.org"> + <RDF:Description about="urn:mozilla:extension:addon4@tests.mozilla.org"> <em:updates> <RDF:Seq> <RDF:li> @@ -89,13 +68,6 @@ <em:version>1.0</em:version> <em:targetApplication> <RDF:Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>1</em:minVersion> - <em:maxVersion>*</em:maxVersion> - </RDF:Description> - </em:targetApplication> - <em:targetApplication> - <RDF:Description> <em:id>toolkit@mozilla.org</em:id> <em:minVersion>1</em:minVersion> <em:maxVersion>*</em:maxVersion> @@ -107,7 +79,7 @@ </em:updates> </RDF:Description> - <RDF:Description about="urn:mozilla:extension:bug557956-5@tests.mozilla.org"> + <RDF:Description about="urn:mozilla:extension:addon5@tests.mozilla.org"> <em:updates> <RDF:Seq> <RDF:li> @@ -115,13 +87,6 @@ <em:version>1.0</em:version> <em:targetApplication> <RDF:Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>0</em:minVersion> - <em:maxVersion>*</em:maxVersion> - </RDF:Description> - </em:targetApplication> - <em:targetApplication> - <RDF:Description> <em:id>toolkit@mozilla.org</em:id> <em:minVersion>0</em:minVersion> <em:maxVersion>*</em:maxVersion> @@ -133,7 +98,7 @@ </em:updates> </RDF:Description> - <RDF:Description about="urn:mozilla:extension:bug557956-6@tests.mozilla.org"> + <RDF:Description about="urn:mozilla:extension:addon6@tests.mozilla.org"> <em:updates> <RDF:Seq> <RDF:li> @@ -141,13 +106,6 @@ <em:version>1.0</em:version> <em:targetApplication> <RDF:Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>0</em:minVersion> - <em:maxVersion>*</em:maxVersion> - </RDF:Description> - </em:targetApplication> - <em:targetApplication> - <RDF:Description> <em:id>toolkit@mozilla.org</em:id> <em:minVersion>0</em:minVersion> <em:maxVersion>*</em:maxVersion> @@ -159,7 +117,7 @@ </em:updates> </RDF:Description> - <RDF:Description about="urn:mozilla:extension:bug557956-7@tests.mozilla.org"> + <RDF:Description about="urn:mozilla:extension:addon7@tests.mozilla.org"> <em:updates> <RDF:Seq> <RDF:li> @@ -167,13 +125,6 @@ <em:version>1.0</em:version> <em:targetApplication> <RDF:Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>0</em:minVersion> - <em:maxVersion>0</em:maxVersion> - </RDF:Description> - </em:targetApplication> - <em:targetApplication> - <RDF:Description> <em:id>toolkit@mozilla.org</em:id> <em:minVersion>0</em:minVersion> <em:maxVersion>0</em:maxVersion> @@ -186,15 +137,6 @@ <em:version>2.0</em:version> <em:targetApplication> <RDF:Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>0</em:minVersion> - <em:maxVersion>*</em:maxVersion> - <em:updateLink>http://example.com/browser/toolkit/mozapps/extensions/test/browser/browser_bug557956_7_2.xpi</em:updateLink> - <em:updateHash>sha1:18674cf7ad76664e0ead6280a43cc0c681180505</em:updateHash> - </RDF:Description> - </em:targetApplication> - <em:targetApplication> - <RDF:Description> <em:id>toolkit@mozilla.org</em:id> <em:minVersion>0</em:minVersion> <em:maxVersion>*</em:maxVersion> @@ -208,7 +150,7 @@ </em:updates> </RDF:Description> - <RDF:Description about="urn:mozilla:extension:bug557956-8@tests.mozilla.org"> + <RDF:Description about="urn:mozilla:extension:addon8@tests.mozilla.org"> <em:updates> <RDF:Seq> <RDF:li> @@ -216,13 +158,6 @@ <em:version>1.0</em:version> <em:targetApplication> <RDF:Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>0</em:minVersion> - <em:maxVersion>0</em:maxVersion> - </RDF:Description> - </em:targetApplication> - <em:targetApplication> - <RDF:Description> <em:id>toolkit@mozilla.org</em:id> <em:minVersion>0</em:minVersion> <em:maxVersion>0</em:maxVersion> @@ -235,20 +170,11 @@ <em:version>2.0</em:version> <em:targetApplication> <RDF:Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>0</em:minVersion> - <em:maxVersion>*</em:maxVersion> - <em:updateLink>http://example.com/browser/toolkit/mozapps/extensions/test/browser/browser_bug557956_8_2.xpi</em:updateLink> - <em:updateHash>sha1:5691c398e55ddf93aa1076b9820619d21d40acbc</em:updateHash> - </RDF:Description> - </em:targetApplication> - <em:targetApplication> - <RDF:Description> <em:id>toolkit@mozilla.org</em:id> <em:minVersion>0</em:minVersion> <em:maxVersion>*</em:maxVersion> <em:updateLink>http://example.com/browser/toolkit/mozapps/extensions/test/browser/browser_bug557956_8_2.xpi</em:updateLink> - <em:updateHash>sha1:5691c398e55ddf93aa1076b9820619d21d40acbc</em:updateHash> + <em:updateHash>sha1:d6240607c4f202226fa291d9b7e537ff2a309616</em:updateHash> </RDF:Description> </em:targetApplication> </RDF:Description> @@ -257,7 +183,7 @@ </em:updates> </RDF:Description> - <RDF:Description about="urn:mozilla:extension:bug557956-9@tests.mozilla.org"> + <RDF:Description about="urn:mozilla:extension:addon9@tests.mozilla.org"> <em:updates> <RDF:Seq> <RDF:li> @@ -265,13 +191,6 @@ <em:version>1.0</em:version> <em:targetApplication> <RDF:Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>0</em:minVersion> - <em:maxVersion>0</em:maxVersion> - </RDF:Description> - </em:targetApplication> - <em:targetApplication> - <RDF:Description> <em:id>toolkit@mozilla.org</em:id> <em:minVersion>0</em:minVersion> <em:maxVersion>0</em:maxVersion> @@ -284,20 +203,11 @@ <em:version>2.0</em:version> <em:targetApplication> <RDF:Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>0</em:minVersion> - <em:maxVersion>*</em:maxVersion> - <em:updateLink>http://example.com/browser/toolkit/mozapps/extensions/test/browser/browser_bug557956_9_2.xpi</em:updateLink> - <em:updateHash>sha1:1ae63bfc6f67a4503a1ff1bd02402c98fef19ae3</em:updateHash> - </RDF:Description> - </em:targetApplication> - <em:targetApplication> - <RDF:Description> <em:id>toolkit@mozilla.org</em:id> <em:minVersion>0</em:minVersion> <em:maxVersion>*</em:maxVersion> <em:updateLink>http://example.com/browser/toolkit/mozapps/extensions/test/browser/browser_bug557956_9_2.xpi</em:updateLink> - <em:updateHash>sha1:1ae63bfc6f67a4503a1ff1bd02402c98fef19ae3</em:updateHash> + <em:updateHash>sha1:b25d1ee94acc734a4a039d31c1620051bbbd5633</em:updateHash> </RDF:Description> </em:targetApplication> </RDF:Description> diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug557956.xml b/toolkit/mozapps/extensions/test/browser/browser_bug557956.xml index c32ed3062..6184e5214 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug557956.xml +++ b/toolkit/mozapps/extensions/test/browser/browser_bug557956.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" ?> <searchresults total_results="1"> <addon_compatibility hosted="false"> - <guid>bug557956-10@tests.mozilla.org</guid> + <guid>addon10@tests.mozilla.org</guid> <name>Addon10</name> <version_ranges> <version_range type="incompatible"> diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug557956_8_2.xpi b/toolkit/mozapps/extensions/test/browser/browser_bug557956_8_2.xpi Binary files differindex e99f3c3bd..9476a8907 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug557956_8_2.xpi +++ b/toolkit/mozapps/extensions/test/browser/browser_bug557956_8_2.xpi diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug557956_9_2.xpi b/toolkit/mozapps/extensions/test/browser/browser_bug557956_9_2.xpi Binary files differindex 23686b608..df7673672 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug557956_9_2.xpi +++ b/toolkit/mozapps/extensions/test/browser/browser_bug557956_9_2.xpi diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug562797.js b/toolkit/mozapps/extensions/test/browser/browser_bug562797.js index 55e882a05..6560e9a2c 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug562797.js +++ b/toolkit/mozapps/extensions/test/browser/browser_bug562797.js @@ -58,27 +58,23 @@ function test() { Services.prefs.setCharPref(PREF_DISCOVERURL, MAIN_URL); - SpecialPowers.pushPrefEnv({"set": [ - ["dom.ipc.processCount", 1], - ]}, () => { - var gProvider = new MockProvider(); - gProvider.createAddons([{ - id: "test1@tests.mozilla.org", - name: "Test add-on 1", - description: "foo" - }, - { - id: "test2@tests.mozilla.org", - name: "Test add-on 2", - description: "bar" - }, - { - id: "test3@tests.mozilla.org", - name: "Test add-on 3", - type: "theme", - description: "bar" - }]); - }); + var gProvider = new MockProvider(); + gProvider.createAddons([{ + id: "test1@tests.mozilla.org", + name: "Test add-on 1", + description: "foo" + }, + { + id: "test2@tests.mozilla.org", + name: "Test add-on 2", + description: "bar" + }, + { + id: "test3@tests.mozilla.org", + name: "Test add-on 3", + type: "theme", + description: "bar" + }]); run_next_test(); } @@ -97,11 +93,11 @@ function go_back(aManager) { } function go_back_backspace(aManager) { - EventUtils.synthesizeKey("VK_BACK_SPACE", {}); + EventUtils.synthesizeKey("VK_BACK_SPACE",{}); } function go_forward_backspace(aManager) { - EventUtils.synthesizeKey("VK_BACK_SPACE", {shiftKey: true}); + EventUtils.synthesizeKey("VK_BACK_SPACE",{shiftKey: true}); } function go_forward(aManager) { @@ -131,7 +127,7 @@ function is_in_list(aManager, view, canGoBack, canGoForward) { var doc = aManager.document; is(doc.getElementById("categories").selectedItem.value, view, "Should be on the right category"); - is(get_current_view(aManager).id, "list-view", "Should be on the right view"); + is(doc.getElementById("view-port").selectedPanel.id, "list-view", "Should be on the right view"); check_state(aManager, canGoBack, canGoForward); } @@ -140,7 +136,7 @@ function is_in_search(aManager, query, canGoBack, canGoForward) { var doc = aManager.document; is(doc.getElementById("categories").selectedItem.value, "addons://search/", "Should be on the right category"); - is(get_current_view(aManager).id, "search-view", "Should be on the right view"); + is(doc.getElementById("view-port").selectedPanel.id, "search-view", "Should be on the right view"); is(doc.getElementById("header-search").value, query, "Should have used the right query"); check_state(aManager, canGoBack, canGoForward); @@ -150,7 +146,7 @@ function is_in_detail(aManager, view, canGoBack, canGoForward) { var doc = aManager.document; is(doc.getElementById("categories").selectedItem.value, view, "Should be on the right category"); - is(get_current_view(aManager).id, "detail-view", "Should be on the right view"); + is(doc.getElementById("view-port").selectedPanel.id, "detail-view", "Should be on the right view"); check_state(aManager, canGoBack, canGoForward); } @@ -239,61 +235,55 @@ add_test(function() { return; } - function promiseViewLoad(manager) { - return new Promise(resolve => { - wait_for_view_load(manager, resolve); - }); - } - - function promiseManagerLoaded(manager) { - return new Promise(resolve => { - wait_for_manager_load(manager, resolve); - }); - } - - Task.spawn(function*() { - info("Part 1"); - yield BrowserTestUtils.openNewForegroundTab(gBrowser, "http://example.com/", true, true); - - info("Part 2"); - ok(!gBrowser.canGoBack, "Should not be able to go back"); - ok(!gBrowser.canGoForward, "Should not be able to go forward"); - - yield BrowserTestUtils.loadURI(gBrowser.selectedBrowser, "about:addons"); - yield BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser); - - let manager = yield promiseManagerLoaded(gBrowser.contentWindow.wrappedJSObject); - - info("Part 3"); - is_in_list(manager, "addons://list/extension", true, false); - - // XXX: This is less than ideal, as it's currently difficult to deal with - // the browser frame switching between remote/non-remote in e10s mode. - let promiseLoaded; - if (gMultiProcessBrowser) { - promiseLoaded = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser); - } else { - promiseLoaded = BrowserTestUtils.waitForEvent(gBrowser.selectedBrowser, "pageshow"); - } + info("Part 1"); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI("http://example.com/"); + gBrowser.addEventListener("pageshow", function(event) { + if (event.target.location != "http://example.com/") + return; + gBrowser.removeEventListener("pageshow", arguments.callee, false); - go_back(manager); - yield promiseLoaded; + //Must let the load complete for it to go into the session history + executeSoon(function() { + info("Part 2"); + ok(!gBrowser.canGoBack, "Should not be able to go back"); + ok(!gBrowser.canGoForward, "Should not be able to go forward"); - info("Part 4"); - is(gBrowser.currentURI.spec, "http://example.com/", "Should be showing the webpage"); - ok(!gBrowser.canGoBack, "Should not be able to go back"); - ok(gBrowser.canGoForward, "Should be able to go forward"); + gBrowser.loadURI("about:addons"); + gBrowser.addEventListener("pageshow", function(event) { + if (event.target.location != "about:addons") + return; + gBrowser.removeEventListener("pageshow", arguments.callee, true); - promiseLoaded = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser); - go_forward(manager); - yield promiseLoaded; + wait_for_view_load(gBrowser.contentWindow.wrappedJSObject, function(aManager) { + info("Part 3"); + is_in_list(aManager, "addons://list/extension", true, false); - manager = yield promiseManagerLoaded(gBrowser.contentWindow.wrappedJSObject); - info("Part 5"); - is_in_list(manager, "addons://list/extension", true, false); + executeSoon(() => go_back(aManager)); + gBrowser.addEventListener("pageshow", function() { + gBrowser.removeEventListener("pageshow", arguments.callee, false); + info("Part 4"); + executeSoon(() => executeSoon(function () { + is(gBrowser.currentURI.spec, "http://example.com/", "Should be showing the webpage"); + ok(!gBrowser.canGoBack, "Should not be able to go back"); + ok(gBrowser.canGoForward, "Should be able to go forward"); + + go_forward(aManager); + gBrowser.addEventListener("pageshow", function() { + gBrowser.removeEventListener("pageshow", arguments.callee, false); + wait_for_view_load(gBrowser.contentWindow.wrappedJSObject, function(aManager) { + info("Part 5"); + is_in_list(aManager, "addons://list/extension", true, false); - close_manager(manager, run_next_test); - }); + close_manager(aManager, run_next_test); + }); + }, false); + })); + }, false); + }); + }, true); + }); + }, false); }); // Tests simple forward and back navigation and that the right heading and @@ -928,7 +918,7 @@ add_test(function() { is_in_discovery(aManager, SECOND_URL, true, false); EventUtils.synthesizeMouseAtCenter(aManager.document.getElementById("category-discover"), { }, aManager); - + waitForLoad(aManager, function() { is_in_discovery(aManager, MAIN_URL, true, false); diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug562854.js b/toolkit/mozapps/extensions/test/browser/browser_bug562854.js index 53e890b71..4c06cebb7 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug562854.js +++ b/toolkit/mozapps/extensions/test/browser/browser_bug562854.js @@ -30,14 +30,14 @@ function is_in_list(aManager, view) { var doc = aManager.document; is(doc.getElementById("categories").selectedItem.value, view, "Should be on the right category"); - is(get_current_view(aManager).id, "list-view", "Should be on the right view"); + is(doc.getElementById("view-port").selectedPanel.id, "list-view", "Should be on the right view"); } function is_in_detail(aManager, view) { var doc = aManager.document; is(doc.getElementById("categories").selectedItem.value, view, "Should be on the right category"); - is(get_current_view(aManager).id, "detail-view", "Should be on the right view"); + is(doc.getElementById("view-port").selectedPanel.id, "detail-view", "Should be on the right view"); } // Check that double-click does something. diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug562890.js b/toolkit/mozapps/extensions/test/browser/browser_bug562890.js index ccb12c489..375cb9ef0 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug562890.js +++ b/toolkit/mozapps/extensions/test/browser/browser_bug562890.js @@ -25,7 +25,7 @@ function test() { description: "bar", optionsURL: addonPrefsURI }]); - + open_manager("addons://list/extension", function(aManager) { var addonList = aManager.document.getElementById("addon-list"); for (var addonItem of addonList.childNodes) { diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug562899.js b/toolkit/mozapps/extensions/test/browser/browser_bug562899.js index 9807be98f..8bfabf004 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug562899.js +++ b/toolkit/mozapps/extensions/test/browser/browser_bug562899.js @@ -5,9 +5,9 @@ // Simulates quickly switching between different list views to verify that only // the last selected is displayed -var tempScope = {}; +let tempScope = {}; Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm", tempScope); -var LightweightThemeManager = tempScope.LightweightThemeManager; +let LightweightThemeManager = tempScope.LightweightThemeManager; const xpi = "browser/toolkit/mozapps/extensions/test/browser/browser_installssl.xpi"; diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug567127.js b/toolkit/mozapps/extensions/test/browser/browser_bug567127.js index 1d9a75416..5c5dce069 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug567127.js +++ b/toolkit/mozapps/extensions/test/browser/browser_bug567127.js @@ -73,6 +73,7 @@ WindowOpenListener.prototype = { var gInstallNotificationObserver = { observe: function(aSubject, aTopic, aData) { var installInfo = aSubject.QueryInterface(Ci.amIWebInstallInfo); + is(installInfo.installs.length, 2, "Should be installing 2 files.") if (gTestInWindow) is(installInfo.browser, null, "Notification should have a null browser"); else @@ -108,8 +109,8 @@ add_task(function* test_install_from_file() { get_addon_file_url("browser_bug567127_1.xpi"), get_addon_file_url("browser_bug567127_2.xpi") ]; - MockFilePicker.returnFiles = filePaths.map(aPath => aPath.file); - + MockFilePicker.returnFiles = filePaths.map(function(aPath) aPath.file); + Services.obs.addObserver(gInstallNotificationObserver, "addon-install-started", false); @@ -118,8 +119,8 @@ add_task(function* test_install_from_file() { let pInstallURIClosed = new Promise((resolve, reject) => { new WindowOpenListener(INSTALL_URI, function(aWindow) { try { - test_confirmation(aWindow, filePaths.map(aPath => aPath.spec)); - } catch (e) { + test_confirmation(aWindow, filePaths.map(function(aPath) aPath.spec)); + } catch(e) { reject(e); } }, resolve); diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug570760.js b/toolkit/mozapps/extensions/test/browser/browser_bug570760.js index 0606a9a31..765665e8c 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug570760.js +++ b/toolkit/mozapps/extensions/test/browser/browser_bug570760.js @@ -5,7 +5,7 @@ // As part of bug 1077403, the leaking uncaught rejection should be fixed. thisTestLeaksUncaughtRejectionsAndShouldBeFixed(""); -// Bug 570760 - Make ctrl-f and / focus the search box in the add-ons manager +// Bug 570760 - Make ctrl-f and / focus the search box in the add-ons manager var gManagerWindow; var focusCount = 0; diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug573062.js b/toolkit/mozapps/extensions/test/browser/browser_bug573062.js index 6554451fb..c61131f03 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug573062.js +++ b/toolkit/mozapps/extensions/test/browser/browser_bug573062.js @@ -31,7 +31,7 @@ function test() { permissions: perms, operationsRequiringRestart: AddonManager.OP_NEEDS_RESTART_NONE }]); - + open_manager("addons://list/extension", function(aWindow) { let addonList = aWindow.document.getElementById("addon-list"); let ed_r_Item, un_r_Item, no_r_Item; @@ -52,9 +52,9 @@ function test() { // Check the buttons in the list view. function checkTooltips(aItem, aEnable, aDisable, aRemove) { - is(aItem._enableBtn.getAttribute("tooltiptext"), aEnable); - is(aItem._disableBtn.getAttribute("tooltiptext"), aDisable); - is(aItem._removeBtn.getAttribute("tooltiptext"), aRemove); + ok(aItem._enableBtn.getAttribute("tooltiptext") == aEnable); + ok(aItem._disableBtn.getAttribute("tooltiptext") == aDisable); + ok(aItem._removeBtn.getAttribute("tooltiptext") == aRemove); } let strs = aWindow.gStrings.ext; @@ -77,7 +77,7 @@ function test() { strs.GetStringFromName("enableAddonTooltip"), strs.GetStringFromName("disableAddonTooltip"), strs.GetStringFromName("uninstallAddonTooltip")]; - checkTooltips.apply(null, no_args); + checkTooltips.apply(null, no_args) // Check the buttons in the details view. function checkTooltips2(aItem, aEnable, aDisable, aRemove) { diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug577990.js b/toolkit/mozapps/extensions/test/browser/browser_bug577990.js index 913b3b954..2c3c7ba5a 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug577990.js +++ b/toolkit/mozapps/extensions/test/browser/browser_bug577990.js @@ -19,7 +19,7 @@ function test() { if (Components.classes["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).D2DEnabled) { requestLongerTimeout(2); } - } catch (e) {} + } catch(e) {} waitForExplicitFinish(); gProvider = new MockProvider(); diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug580298.js b/toolkit/mozapps/extensions/test/browser/browser_bug580298.js index d3d338203..8456cc433 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug580298.js +++ b/toolkit/mozapps/extensions/test/browser/browser_bug580298.js @@ -9,7 +9,9 @@ var gManagerWindow; var gCategoryUtilities; var gProvider; -add_task(function* test() { +function test() { + waitForExplicitFinish(); + gProvider = new MockProvider(); gProvider.createAddons([{ @@ -29,9 +31,16 @@ add_task(function* test() { version: "789" }]); - gManagerWindow = yield open_manager(); - gCategoryUtilities = new CategoryUtilities(gManagerWindow); -}); + open_manager(null, function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + run_next_test(); + }); +} + +function end_test() { + close_manager(gManagerWindow, finish); +} function get(aId) { return gManagerWindow.document.getElementById(aId); @@ -45,54 +54,58 @@ function open_details(aList, aItem, aCallback) { aList.ensureElementIsVisible(aItem); EventUtils.synthesizeMouseAtCenter(aItem, { clickCount: 1 }, gManagerWindow); EventUtils.synthesizeMouseAtCenter(aItem, { clickCount: 2 }, gManagerWindow); - return new Promise(resolve => wait_for_view_load(gManagerWindow, resolve)); + wait_for_view_load(gManagerWindow, aCallback); } -var check_addon_has_version = Task.async(function*(aList, aName, aVersion) { +function check_addon_has_version(aList, aName, aVersion) { for (let i = 0; i < aList.itemCount; i++) { let item = aList.getItemAtIndex(i); if (get_node(item, "name").value === aName) { ok(true, "Item with correct name found"); - let { version } = yield get_tooltip_info(item); - is(version, aVersion, "Item has correct version"); + is(get_node(item, "version").value, aVersion, "Item has correct version"); return item; } } ok(false, "Item with correct name was not found"); return null; -}); - -add_task(function*() { - yield gCategoryUtilities.openType("extension"); - info("Extension"); - let list = gManagerWindow.document.getElementById("addon-list"); - let item = yield check_addon_has_version(list, "Extension 1", "123"); - yield open_details(list, item); - is_element_visible(get("detail-version"), "Details view has version visible"); - is(get("detail-version").value, "123", "Details view has correct version"); -}); +} -add_task(function*() { - yield gCategoryUtilities.openType("theme"); - info("Normal theme"); - let list = gManagerWindow.document.getElementById("addon-list"); - let item = yield check_addon_has_version(list, "Theme 2", "456"); - yield open_details(list, item); - is_element_visible(get("detail-version"), "Details view has version visible"); - is(get("detail-version").value, "456", "Details view has correct version"); +add_test(function() { + gCategoryUtilities.openType("extension", function() { + info("Extension"); + let list = gManagerWindow.document.getElementById("addon-list"); + let item = check_addon_has_version(list, "Extension 1", "123"); + open_details(list, item, function() { + is_element_visible(get("detail-version"), "Details view has version visible"); + is(get("detail-version").value, "123", "Details view has correct version"); + run_next_test(); + }); + }); }); -add_task(function*() { - yield gCategoryUtilities.openType("theme"); - info("Lightweight theme"); - let list = gManagerWindow.document.getElementById("addon-list"); - // See that the version isn't displayed - let item = yield check_addon_has_version(list, "Persona 3", undefined); - yield open_details(list, item); - is_element_hidden(get("detail-version"), "Details view has version hidden"); - // If the version element is hidden then we don't care about its value +add_test(function() { + gCategoryUtilities.openType("theme", function() { + info("Normal theme"); + let list = gManagerWindow.document.getElementById("addon-list"); + let item = check_addon_has_version(list, "Theme 2", "456"); + open_details(list, item, function() { + is_element_visible(get("detail-version"), "Details view has version visible"); + is(get("detail-version").value, "456", "Details view has correct version"); + run_next_test(); + }); + }); }); -add_task(function end_test() { - close_manager(gManagerWindow, finish); +add_test(function() { + gCategoryUtilities.openType("theme", function() { + info("Lightweight theme"); + let list = gManagerWindow.document.getElementById("addon-list"); + // See that the version isn't displayed + let item = check_addon_has_version(list, "Persona 3", ""); + open_details(list, item, function() { + is_element_hidden(get("detail-version"), "Details view has version hidden"); + // If the version element is hidden then we don't care about its value + run_next_test(); + }); + }); }); diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug581076.js b/toolkit/mozapps/extensions/test/browser/browser_bug581076.js index b02a6cc3e..4c25c409d 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug581076.js +++ b/toolkit/mozapps/extensions/test/browser/browser_bug581076.js @@ -11,8 +11,6 @@ const SEARCH_URL = TESTROOT + "browser_searching.xml"; const SEARCH_EXPECTED_TOTAL = 100; const SEARCH_QUERY = "search"; -const SEARCHABLE_PAGE = "addons://list/extension"; - var gManagerWindow; @@ -22,7 +20,7 @@ function test() { waitForExplicitFinish(); - open_manager(SEARCHABLE_PAGE, function(aWindow) { + open_manager("addons://list/extension", function(aWindow) { gManagerWindow = aWindow; run_next_test(); }); @@ -47,11 +45,10 @@ function search(aRemoteSearch, aCallback) { EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow); wait_for_view_load(gManagerWindow, function() { - let filter; if (aRemoteSearch) - filter = gManagerWindow.document.getElementById("search-filter-remote"); + var filter = gManagerWindow.document.getElementById("search-filter-remote"); else - filter = gManagerWindow.document.getElementById("search-filter-local"); + var filter = gManagerWindow.document.getElementById("search-filter-local"); EventUtils.synthesizeMouseAtCenter(filter, { }, gManagerWindow); executeSoon(aCallback); @@ -78,7 +75,7 @@ add_test(function() { info("Searching locally"); search(false, function() { check_allresultslink(false); - restart_manager(gManagerWindow, SEARCHABLE_PAGE, function(aManager) { + restart_manager(gManagerWindow, null, function(aManager) { gManagerWindow = aManager; run_next_test(); }); @@ -86,12 +83,11 @@ add_test(function() { }); add_test(function() { - debugger; info("Searching remotely - more results than cap"); Services.prefs.setIntPref(PREF_GETADDONS_MAXRESULTS, 3); search(true, function() { check_allresultslink(true); - restart_manager(gManagerWindow, SEARCHABLE_PAGE, function(aManager) { + restart_manager(gManagerWindow, null, function(aManager) { gManagerWindow = aManager; run_next_test(); }); @@ -103,7 +99,7 @@ add_test(function() { Services.prefs.setIntPref(PREF_GETADDONS_MAXRESULTS, 200); search(true, function() { check_allresultslink(false); - restart_manager(gManagerWindow, SEARCHABLE_PAGE, function(aManager) { + restart_manager(gManagerWindow, null, function(aManager) { gManagerWindow = aManager; run_next_test(); }); diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug587970.js b/toolkit/mozapps/extensions/test/browser/browser_bug587970.js index ef05ba4ea..0ff6d1b59 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug587970.js +++ b/toolkit/mozapps/extensions/test/browser/browser_bug587970.js @@ -9,7 +9,7 @@ var gProvider; function test() { waitForExplicitFinish(); - + gProvider = new MockProvider(); gProvider.createAddons([{ @@ -28,7 +28,7 @@ function test() { version: "3.0", applyBackgroundUpdates: AddonManager.AUTOUPDATE_DISABLE }]); - + open_manager("addons://updates/available", function(aWindow) { gManagerWindow = aWindow; @@ -48,7 +48,7 @@ add_test(function() { var emptyNotice = gManagerWindow.document.getElementById("empty-availableUpdates-msg"); is_element_visible(emptyNotice, "Empty notice should be visible"); - + var updateSelected = gManagerWindow.document.getElementById("update-selected-btn"); is_element_hidden(updateSelected, "Update Selected button should be hidden"); @@ -86,7 +86,7 @@ add_test(function() { add_test(function() { var list = gManagerWindow.document.getElementById("updates-list"); is(list.childNodes.length, 3, "Available updates list should have 2 items"); - + var item1 = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); isnot(item1, null, "Item for addon1@tests.mozilla.org should be in list"); var item2 = get_addon_element(gManagerWindow, "addon2@tests.mozilla.org"); @@ -104,7 +104,7 @@ add_test(function() { is(item1._includeUpdate.checked, true, "Include Update checkbox should be checked by default for addon1"); is(item2._includeUpdate.checked, true, "Include Update checkbox should be checked by default for addon2"); is(item3._includeUpdate.checked, true, "Include Update checkbox should be checked by default for addon3"); - + info("Unchecking Include Update checkbox for addon1"); EventUtils.synthesizeMouse(item1._includeUpdate, 2, 2, { }, gManagerWindow); is(item1._includeUpdate.checked, false, "Include Update checkbox should now be be unchecked for addon1"); diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug590347.js b/toolkit/mozapps/extensions/test/browser/browser_bug590347.js index f805f0e19..8fe9c715e 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug590347.js +++ b/toolkit/mozapps/extensions/test/browser/browser_bug590347.js @@ -49,9 +49,8 @@ function get_list_view_warning_node() { } function get_detail_view_warning_node(aManagerWindow) { - if (aManagerWindow) + if(aManagerWindow) return aManagerWindow.document.getElementById("detail-warning"); - return undefined; } function test() { diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug591465.js b/toolkit/mozapps/extensions/test/browser/browser_bug591465.js index f759ffc1f..2380deee1 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug591465.js +++ b/toolkit/mozapps/extensions/test/browser/browser_bug591465.js @@ -5,9 +5,9 @@ // Bug 591465 - Context menu of add-ons miss context related state change entries -var tempScope = {}; +let tempScope = {}; Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm", tempScope); -var LightweightThemeManager = tempScope.LightweightThemeManager; +let LightweightThemeManager = tempScope.LightweightThemeManager; const PREF_GETADDONS_MAXRESULTS = "extensions.getAddons.maxResults"; diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug591465.xml b/toolkit/mozapps/extensions/test/browser/browser_bug591465.xml index 9c2e102e7..bd648cf0f 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug591465.xml +++ b/toolkit/mozapps/extensions/test/browser/browser_bug591465.xml @@ -17,7 +17,7 @@ <compatible_applications> <application> <name>Firefox</name> - <appID>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</appID> + <appID>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</appID> <min_version>0</min_version> <max_version>*</max_version> </application> diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug591663.js b/toolkit/mozapps/extensions/test/browser/browser_bug591663.js index 4a4f735af..0736aa391 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug591663.js +++ b/toolkit/mozapps/extensions/test/browser/browser_bug591663.js @@ -7,25 +7,25 @@ // Don't use a standard list view (e.g. "extension") to ensure that the list is // initially empty. Don't need to worry about the list of categories displayed // since only the list view itself is tested. -var VIEW_ID = "addons://list/mock-addon"; +let VIEW_ID = "addons://list/mock-addon"; -var LIST_ID = "addon-list"; -var EMPTY_ID = "addon-list-empty"; +let LIST_ID = "addon-list"; +let EMPTY_ID = "addon-list-empty"; -var gManagerWindow; -var gProvider; -var gItem; +let gManagerWindow; +let gProvider; +let gItem; -var gInstallProperties = { +let gInstallProperties = { name: "Bug 591663 Mock Install", type: "mock-addon" }; -var gAddonProperties = { +let gAddonProperties = { id: "test1@tests.mozilla.org", name: "Bug 591663 Mock Add-on", type: "mock-addon" }; -var gExtensionProperties = { +let gExtensionProperties = { name: "Bug 591663 Extension Install", type: "extension" }; @@ -64,7 +64,7 @@ function check_list(aItem) { // Check the children of the list let list = gManagerWindow.document.getElementById(LIST_ID); - is(list.childNodes.length, aItem ? 1 : 0, "Should get expected number of items in list"); + is(list.itemCount, aItem ? 1 : 0, "Should get expected number of items in list"); if (aItem != null) { let itemName = list.firstChild.getAttribute("name"); is(itemName, aItem.name, "List item should have correct name"); diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug593535.js b/toolkit/mozapps/extensions/test/browser/browser_bug593535.js index fd23d0036..a78ef9a23 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug593535.js +++ b/toolkit/mozapps/extensions/test/browser/browser_bug593535.js @@ -10,11 +10,10 @@ const SEARCH_URL = TESTROOT + "browser_bug593535.xml"; const QUERY = "NOTFOUND"; var gProvider; -var gManagerWindow; function test() { waitForExplicitFinish(); - + // Turn on searching for this test Services.prefs.setIntPref(PREF_SEARCH_MAXRESULTS, 15); @@ -86,12 +85,12 @@ function getAnonymousElementByAttribute(aElement, aName, aValue) { // Tests that a failed install for a remote add-on will ask to retry the install add_test(function() { var remoteItem; - + var listener = { onDownloadFailed: function(aInstall) { aInstall.removeListener(this); ok(true, "Install failed as expected"); - + executeSoon(function() { is(remoteItem.getAttribute("notification"), "warning", "Item should have notification attribute set to 'warning'"); is_element_visible(remoteItem._warning, "Warning text should be visible"); @@ -100,7 +99,7 @@ add_test(function() { run_next_test(); }); }, - + onInstallEnded: function() { ok(false, "Install should have failed"); } @@ -112,7 +111,7 @@ add_test(function() { list.ensureElementIsVisible(remoteItem); remoteItem.mAddon.install.addListener(listener); - + var installBtn = get_install_button(remoteItem); EventUtils.synthesizeMouseAtCenter(installBtn, { }, gManagerWindow); }); diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug593535.xml b/toolkit/mozapps/extensions/test/browser/browser_bug593535.xml index 411d9f383..847c2854d 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug593535.xml +++ b/toolkit/mozapps/extensions/test/browser/browser_bug593535.xml @@ -17,7 +17,7 @@ <compatible_applications> <application> <name>Firefox</name> - <appID>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</appID> + <appID>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</appID> <min_version>0</min_version> <max_version>*</max_version> </application> diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug596336.js b/toolkit/mozapps/extensions/test/browser/browser_bug596336.js index ec32e376f..935820613 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug596336.js +++ b/toolkit/mozapps/extensions/test/browser/browser_bug596336.js @@ -8,12 +8,19 @@ var gManagerWindow; var gCategoryUtilities; -add_task(function* test() { +function test() { waitForExplicitFinish(); - gManagerWindow = yield open_manager("addons://list/extension"); - gCategoryUtilities = new CategoryUtilities(gManagerWindow); -}); + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + run_next_test(); + }); +} + +function end_test() { + close_manager(gManagerWindow, finish); +} function get_list_item_count() { return get_test_items_in_list(gManagerWindow).length; @@ -27,130 +34,147 @@ function get_class_node(parent, cls) { return parent.ownerDocument.getAnonymousElementByAttribute(parent, "class", cls); } -function install_addon(aXpi) { - return new Promise(resolve => { - AddonManager.getInstallForURL(TESTROOT + "addons/" + aXpi + ".xpi", - function(aInstall) { - aInstall.addListener({ - onInstallEnded: function(aInstall) { - resolve(); - } - }); - aInstall.install(); - }, "application/x-xpinstall"); - }); +function install_addon(aXpi, aCallback) { + AddonManager.getInstallForURL(TESTROOT + "addons/" + aXpi + ".xpi", + function(aInstall) { + aInstall.addListener({ + onInstallEnded: function(aInstall) { + executeSoon(aCallback); + } + }); + aInstall.install(); + }, "application/x-xpinstall"); } -var check_addon = Task.async(function*(aAddon, aVersion) { +function check_addon(aAddon, version) { is(get_list_item_count(), 1, "Should be one item in the list"); - is(aAddon.version, aVersion, "Add-on should have the right version"); + is(aAddon.version, version, "Add-on should have the right version"); - let item = get_addon_element(gManagerWindow, "bug596336-1@tests.mozilla.org"); + let item = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); ok(!!item, "Should see the add-on in the list"); // Force XBL to apply item.clientTop; - let { version } = yield get_tooltip_info(item); - is(version, aVersion, "Version should be correct"); + is(get_node(item, "version").value, version, "Version should be correct"); if (aAddon.userDisabled) is_element_visible(get_class_node(item, "disabled-postfix"), "Disabled postfix should be hidden"); else is_element_hidden(get_class_node(item, "disabled-postfix"), "Disabled postfix should be hidden"); -}); +} // Install version 1 then upgrade to version 2 with the manager open -add_task(function*() { - yield install_addon("browser_bug596336_1"); - let [aAddon] = yield promiseAddonsByIDs(["bug596336-1@tests.mozilla.org"]); - yield check_addon(aAddon, "1.0"); - ok(!aAddon.userDisabled, "Add-on should not be disabled"); +add_test(function() { + install_addon("browser_bug596336_1", function() { + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) { + check_addon(aAddon, "1.0"); + ok(!aAddon.userDisabled, "Add-on should not be disabled"); + + install_addon("browser_bug596336_2", function() { + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) { + check_addon(aAddon, "2.0"); + ok(!aAddon.userDisabled, "Add-on should not be disabled"); - yield install_addon("browser_bug596336_2"); - [aAddon] = yield promiseAddonsByIDs(["bug596336-1@tests.mozilla.org"]); - yield check_addon(aAddon, "2.0"); - ok(!aAddon.userDisabled, "Add-on should not be disabled"); + aAddon.uninstall(); - aAddon.uninstall(); + is(get_list_item_count(), 0, "Should be no items in the list"); - is(get_list_item_count(), 0, "Should be no items in the list"); + run_next_test(); + }); + }); + }); + }); }); // Install version 1 mark it as disabled then upgrade to version 2 with the // manager open -add_task(function*() { - yield install_addon("browser_bug596336_1"); - let [aAddon] = yield promiseAddonsByIDs(["bug596336-1@tests.mozilla.org"]); - aAddon.userDisabled = true; - yield check_addon(aAddon, "1.0"); - ok(aAddon.userDisabled, "Add-on should be disabled"); +add_test(function() { + install_addon("browser_bug596336_1", function() { + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) { + aAddon.userDisabled = true; + check_addon(aAddon, "1.0"); + ok(aAddon.userDisabled, "Add-on should be disabled"); + + install_addon("browser_bug596336_2", function() { + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) { + check_addon(aAddon, "2.0"); + ok(aAddon.userDisabled, "Add-on should be disabled"); - yield install_addon("browser_bug596336_2"); - [aAddon] = yield promiseAddonsByIDs(["bug596336-1@tests.mozilla.org"]); - yield check_addon(aAddon, "2.0"); - ok(aAddon.userDisabled, "Add-on should be disabled"); + aAddon.uninstall(); - aAddon.uninstall(); + is(get_list_item_count(), 0, "Should be no items in the list"); - is(get_list_item_count(), 0, "Should be no items in the list"); + run_next_test(); + }); + }); + }); + }); }); // Install version 1 click the remove button and then upgrade to version 2 with // the manager open -add_task(function*() { - yield install_addon("browser_bug596336_1"); - let [aAddon] = yield promiseAddonsByIDs(["bug596336-1@tests.mozilla.org"]); - yield check_addon(aAddon, "1.0"); - ok(!aAddon.userDisabled, "Add-on should not be disabled"); +add_test(function() { + install_addon("browser_bug596336_1", function() { + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) { + check_addon(aAddon, "1.0"); + ok(!aAddon.userDisabled, "Add-on should not be disabled"); - let item = get_addon_element(gManagerWindow, "bug596336-1@tests.mozilla.org"); - EventUtils.synthesizeMouseAtCenter(get_node(item, "remove-btn"), { }, gManagerWindow); + let item = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); + EventUtils.synthesizeMouseAtCenter(get_node(item, "remove-btn"), { }, gManagerWindow); - // Force XBL to apply - item.clientTop; + // Force XBL to apply + item.clientTop; - ok(!!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should be pending uninstall"); - is_element_visible(get_class_node(item, "pending"), "Pending message should be visible"); + ok(!!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should be pending uninstall"); + is_element_visible(get_class_node(item, "pending"), "Pending message should be visible"); - yield install_addon("browser_bug596336_2"); - [aAddon] = yield promiseAddonsByIDs(["bug596336-1@tests.mozilla.org"]); - yield check_addon(aAddon, "2.0"); - ok(!aAddon.userDisabled, "Add-on should not be disabled"); + install_addon("browser_bug596336_2", function() { + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) { + check_addon(aAddon, "2.0"); + ok(!aAddon.userDisabled, "Add-on should not be disabled"); - aAddon.uninstall(); + aAddon.uninstall(); - is(get_list_item_count(), 0, "Should be no items in the list"); + is(get_list_item_count(), 0, "Should be no items in the list"); + + run_next_test(); + }); + }); + }); + }); }); // Install version 1, disable it, click the remove button and then upgrade to // version 2 with the manager open -add_task(function*() { - yield install_addon("browser_bug596336_1"); - let [aAddon] = yield promiseAddonsByIDs(["bug596336-1@tests.mozilla.org"]); - aAddon.userDisabled = true; - yield check_addon(aAddon, "1.0"); - ok(aAddon.userDisabled, "Add-on should be disabled"); +add_test(function() { + install_addon("browser_bug596336_1", function() { + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) { + aAddon.userDisabled = true; + check_addon(aAddon, "1.0"); + ok(aAddon.userDisabled, "Add-on should be disabled"); - let item = get_addon_element(gManagerWindow, "bug596336-1@tests.mozilla.org"); - EventUtils.synthesizeMouseAtCenter(get_node(item, "remove-btn"), { }, gManagerWindow); + let item = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); + EventUtils.synthesizeMouseAtCenter(get_node(item, "remove-btn"), { }, gManagerWindow); - // Force XBL to apply - item.clientTop; + // Force XBL to apply + item.clientTop; - ok(!!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should be pending uninstall"); - is_element_visible(get_class_node(item, "pending"), "Pending message should be visible"); + ok(!!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should be pending uninstall"); + is_element_visible(get_class_node(item, "pending"), "Pending message should be visible"); - yield install_addon("browser_bug596336_2"); - [aAddon] = yield promiseAddonsByIDs(["bug596336-1@tests.mozilla.org"]); - yield check_addon(aAddon, "2.0"); - ok(aAddon.userDisabled, "Add-on should be disabled"); + install_addon("browser_bug596336_2", function() { + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) { + check_addon(aAddon, "2.0"); + ok(aAddon.userDisabled, "Add-on should be disabled"); - aAddon.uninstall(); + aAddon.uninstall(); - is(get_list_item_count(), 0, "Should be no items in the list"); -}); + is(get_list_item_count(), 0, "Should be no items in the list"); -add_task(function end_test() { - close_manager(gManagerWindow, finish); + run_next_test(); + }); + }); + }); + }); }); diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug608316.js b/toolkit/mozapps/extensions/test/browser/browser_bug608316.js index 72bb61f49..39986c23b 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug608316.js +++ b/toolkit/mozapps/extensions/test/browser/browser_bug608316.js @@ -9,7 +9,7 @@ var gProvider; function test() { waitForExplicitFinish(); - + gProvider = new MockProvider(); gProvider.createAddons([{ diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug618502.js b/toolkit/mozapps/extensions/test/browser/browser_bug618502.js index 5bcc6baf1..36ba8fb69 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug618502.js +++ b/toolkit/mozapps/extensions/test/browser/browser_bug618502.js @@ -9,7 +9,7 @@ var gCategoryUtilities; function test() { waitForExplicitFinish(); - + run_next_test(); } diff --git a/toolkit/mozapps/extensions/test/browser/browser_cancelCompatCheck.js b/toolkit/mozapps/extensions/test/browser/browser_cancelCompatCheck.js index e7c672212..1799adcdd 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_cancelCompatCheck.js +++ b/toolkit/mozapps/extensions/test/browser/browser_cancelCompatCheck.js @@ -12,7 +12,7 @@ const PREF_GETADDONS_BYIDS = "extensions.getAddons.get.url"; const PREF_MIN_PLATFORM_COMPAT = "extensions.minCompatiblePlatformVersion"; const PREF_METADATA_LASTUPDATE = "extensions.getAddons.cache.lastUpdate"; -var repo = {}; +let repo = {}; Components.utils.import("resource://gre/modules/addons/AddonRepository.jsm", repo); Components.utils.import("resource://gre/modules/Promise.jsm", this); @@ -33,16 +33,16 @@ Components.utils.import("resource://gre/modules/Promise.jsm", this); */ // describe the addons -var ao1 = { file: "browser_bug557956_1", id: "bug557956-1@tests.mozilla.org"}; -var ao2 = { file: "browser_bug557956_2", id: "bug557956-2@tests.mozilla.org"}; -var ao3 = { file: "browser_bug557956_3", id: "bug557956-3@tests.mozilla.org"}; -var ao4 = { file: "browser_bug557956_4", id: "bug557956-4@tests.mozilla.org"}; -var ao5 = { file: "browser_bug557956_5", id: "bug557956-5@tests.mozilla.org"}; -var ao6 = { file: "browser_bug557956_6", id: "bug557956-6@tests.mozilla.org"}; -var ao7 = { file: "browser_bug557956_7", id: "bug557956-7@tests.mozilla.org"}; -var ao8 = { file: "browser_bug557956_8_1", id: "bug557956-8@tests.mozilla.org"}; -var ao9 = { file: "browser_bug557956_9_1", id: "bug557956-9@tests.mozilla.org"}; -var ao10 = { file: "browser_bug557956_10", id: "bug557956-10@tests.mozilla.org"}; +let ao1 = { file: "browser_bug557956_1", id: "addon1@tests.mozilla.org"}; +let ao2 = { file: "browser_bug557956_2", id: "addon2@tests.mozilla.org"}; +let ao3 = { file: "browser_bug557956_3", id: "addon3@tests.mozilla.org"}; +let ao4 = { file: "browser_bug557956_4", id: "addon4@tests.mozilla.org"}; +let ao5 = { file: "browser_bug557956_5", id: "addon5@tests.mozilla.org"}; +let ao6 = { file: "browser_bug557956_6", id: "addon6@tests.mozilla.org"}; +let ao7 = { file: "browser_bug557956_7", id: "addon7@tests.mozilla.org"}; +let ao8 = { file: "browser_bug557956_8_1", id: "addon8@tests.mozilla.org"}; +let ao9 = { file: "browser_bug557956_9_1", id: "addon9@tests.mozilla.org"}; +let ao10 = { file: "browser_bug557956_10", id: "addon10@tests.mozilla.org"}; // Return a promise that resolves after the specified delay in MS function delayMS(aDelay) { @@ -210,7 +210,7 @@ function get_list_names(aList) { } // These add-ons became inactive during the upgrade -var inactiveAddonIds = [ +let inactiveAddonIds = [ ao5.id, ao6.id, ao7.id, @@ -220,7 +220,7 @@ var inactiveAddonIds = [ // Make sure the addons in the list are not installed function* check_addons_uninstalled(aAddonList) { - let foundList = yield promise_addons_by_ids(aAddonList.map(a => a.id)); + let foundList = yield promise_addons_by_ids([addon.id for (addon of aAddonList)]); for (let i = 0; i < aAddonList.length; i++) { ok(!foundList[i], "Addon " + aAddonList[i].id + " is not installed"); } @@ -232,7 +232,7 @@ function* check_addons_uninstalled(aAddonList) { // Add-ons that have updates available should not update if they were disabled before // For this test, addon8 became disabled during update and addon9 was previously disabled, // so addon8 should update and addon9 should not -add_task(function* cancel_during_repopulate() { +add_task(function cancel_during_repopulate() { let a5, a8, a9, a10; Services.prefs.setBoolPref(PREF_STRICT_COMPAT, true); @@ -297,7 +297,7 @@ add_task(function* cancel_during_repopulate() { // calls in gVersionInfoPage_onPageShow() to complete // For this test, both addon8 and addon9 were disabled by this update, but addon8 // is set to not auto-update, so only addon9 should update in the background -add_task(function* cancel_during_findUpdates() { +add_task(function cancel_during_findUpdates() { let a5, a8, a9; Services.prefs.setBoolPref(PREF_STRICT_COMPAT, true); @@ -357,7 +357,7 @@ add_task(function* cancel_during_findUpdates() { // to continue updating in the background and cancels any other updates // Same conditions as the previous test - addon8 and addon9 have updates available, // addon8 is set to not auto-update so only addon9 should become compatible -add_task(function* cancel_mismatch() { +add_task(function cancel_mismatch() { let a3, a5, a7, a8, a9; Services.prefs.setBoolPref(PREF_STRICT_COMPAT, true); @@ -416,7 +416,7 @@ add_task(function* cancel_mismatch() { // Cancelling during the 'mismatch' screen with only add-ons that have // no updates available -add_task(function* cancel_mismatch_no_updates() { +add_task(function cancel_mismatch_no_updates() { let a3, a5, a6 Services.prefs.setBoolPref(PREF_STRICT_COMPAT, true); diff --git a/toolkit/mozapps/extensions/test/browser/browser_debug_button.js b/toolkit/mozapps/extensions/test/browser/browser_debug_button.js new file mode 100644 index 000000000..3f371e906 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_debug_button.js @@ -0,0 +1,112 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +/** + * Tests debug button for addons in list view + */ + +let { Promise } = Components.utils.import("resource://gre/modules/Promise.jsm", {}); +let { Task } = Components.utils.import("resource://gre/modules/Task.jsm", {}); + +const getDebugButton = node => + node.ownerDocument.getAnonymousElementByAttribute(node, "anonid", "debug-btn"); +const addonDebuggingEnabled = bool => + Services.prefs.setBoolPref("devtools.chrome.enabled", !!bool); +const remoteDebuggingEnabled = bool => + Services.prefs.setBoolPref("devtools.debugger.remote-enabled", !!bool); + +function test() { + requestLongerTimeout(2); + + waitForExplicitFinish(); + + + var gProvider = new MockProvider(); + gProvider.createAddons([{ + id: "non-debuggable@tests.mozilla.org", + name: "No debug", + description: "foo" + }, + { + id: "debuggable@tests.mozilla.org", + name: "Debuggable", + description: "bar", + isDebuggable: true + }]); + + Task.spawn(function* () { + addonDebuggingEnabled(false); + remoteDebuggingEnabled(false); + + yield testDOM((nondebug, debuggable) => { + is(nondebug.disabled, true, + "addon:disabled::remote:disabled button is disabled for legacy addons"); + is(nondebug.hidden, true, + "addon:disabled::remote:disabled button is hidden for legacy addons"); + is(debuggable.disabled, true, + "addon:disabled::remote:disabled button is disabled for debuggable addons"); + is(debuggable.hidden, true, + "addon:disabled::remote:disabled button is hidden for debuggable addons"); + }); + + addonDebuggingEnabled(true); + remoteDebuggingEnabled(false); + + yield testDOM((nondebug, debuggable) => { + is(nondebug.disabled, true, + "addon:enabled::remote:disabled button is disabled for legacy addons"); + is(nondebug.disabled, true, + "addon:enabled::remote:disabled button is hidden for legacy addons"); + is(debuggable.disabled, true, + "addon:enabled::remote:disabled button is disabled for debuggable addons"); + is(debuggable.disabled, true, + "addon:enabled::remote:disabled button is hidden for debuggable addons"); + }); + + addonDebuggingEnabled(false); + remoteDebuggingEnabled(true); + + yield testDOM((nondebug, debuggable) => { + is(nondebug.disabled, true, + "addon:disabled::remote:enabled button is disabled for legacy addons"); + is(nondebug.disabled, true, + "addon:disabled::remote:enabled button is hidden for legacy addons"); + is(debuggable.disabled, true, + "addon:disabled::remote:enabled button is disabled for debuggable addons"); + is(debuggable.disabled, true, + "addon:disabled::remote:enabled button is hidden for debuggable addons"); + }); + + addonDebuggingEnabled(true); + remoteDebuggingEnabled(true); + + yield testDOM((nondebug, debuggable) => { + is(nondebug.disabled, true, + "addon:enabled::remote:enabled button is disabled for legacy addons"); + is(nondebug.disabled, true, + "addon:enabled::remote:enabled button is hidden for legacy addons"); + is(debuggable.disabled, false, + "addon:enabled::remote:enabled button is enabled for debuggable addons"); + is(debuggable.hidden, false, + "addon:enabled::remote:enabled button is visible for debuggable addons"); + }); + + finish(); + }); + + function testDOM (testCallback) { + let deferred = Promise.defer(); + open_manager("addons://list/extension", function(aManager) { + const {document} = aManager; + const addonList = document.getElementById("addon-list"); + const nondebug = addonList.querySelector("[name='No debug']"); + const debuggable = addonList.querySelector("[name='Debuggable']"); + + testCallback.apply(null, [nondebug, debuggable].map(getDebugButton)); + + close_manager(aManager, deferred.resolve); + }); + return deferred.promise; + } +} diff --git a/toolkit/mozapps/extensions/test/browser/browser_details.js b/toolkit/mozapps/extensions/test/browser/browser_details.js index ce4c51b5a..7394c87da 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_details.js +++ b/toolkit/mozapps/extensions/test/browser/browser_details.js @@ -4,12 +4,9 @@ // Tests various aspects of the details view -const { REQUIRE_SIGNING } = Components.utils.import("resource://gre/modules/addons/AddonConstants.jsm", {}); - -const PREF_AUTOUPDATE_DEFAULT = "extensions.update.autoUpdateDefault"; +const PREF_AUTOUPDATE_DEFAULT = "extensions.update.autoUpdateDefault" const PREF_GETADDONS_GETSEARCHRESULTS = "extensions.getAddons.search.url"; const SEARCH_URL = TESTROOT + "browser_details.xml"; -const PREF_EM_HOTFIX_ID = "extensions.hotfix.id"; var gManagerWindow; var gCategoryUtilities; @@ -17,8 +14,9 @@ var gProvider; var gApp = document.getElementById("bundle_brand").getString("brandShortName"); var gVersion = Services.appinfo.version; +var gBlocklistURL = Services.urlFormatter.formatURLPref("extensions.blocklist.detailsURL"); +var gPluginURL = Services.urlFormatter.formatURLPref("plugins.update.url"); var gDate = new Date(2010, 7, 1); -var infoURL = Services.urlFormatter.formatURLPref("app.support.baseURL") + "unsigned-addons"; function open_details(aId, aType, aCallback) { requestLongerTimeout(2); @@ -49,7 +47,6 @@ function test() { // Turn on searching for this test Services.prefs.setIntPref(PREF_SEARCH_MAXRESULTS, 15); Services.prefs.setCharPref(PREF_GETADDONS_GETSEARCHRESULTS, SEARCH_URL); - Services.prefs.setCharPref(PREF_EM_HOTFIX_ID, "hotfix@tests.mozilla.org"); waitForExplicitFinish(); @@ -144,33 +141,6 @@ function test() { blocklistURL: "http://example.com/addon8@tests.mozilla.org", name: "Test add-on 8", blocklistState: Ci.nsIBlocklistService.STATE_OUTDATED - }, { - id: "addon9@tests.mozilla.org", - name: "Test add-on 9", - signedState: AddonManager.SIGNEDSTATE_MISSING, - }, { - id: "addon10@tests.mozilla.org", - name: "Test add-on 10", - signedState: AddonManager.SIGNEDSTATE_MISSING, - isActive: false, - appDisabled: true, - isCompatible: false, - }, { - id: "addon11@tests.mozilla.org", - name: "Test add-on 11", - signedState: AddonManager.SIGNEDSTATE_PRELIMINARY, - foreignInstall: true, - isActive: false, - appDisabled: true, - isCompatible: false, - }, { - id: "addon12@tests.mozilla.org", - name: "Test add-on 12", - signedState: AddonManager.SIGNEDSTATE_SIGNED, - foreignInstall: true, - }, { - id: "hotfix@tests.mozilla.org", - name: "Test hotfix 1", }]); open_manager(null, function(aWindow) { @@ -182,7 +152,6 @@ function test() { } function end_test() { - Services.prefs.clearUserPref(PREF_EM_HOTFIX_ID); close_manager(gManagerWindow, function() { finish(); }); @@ -196,7 +165,7 @@ add_test(function() { is(get("detail-version").value, "2.1", "Version should be correct"); is(get("detail-icon").src, "chrome://foo/skin/icon64.png", "Icon should be correct"); is_element_hidden(get("detail-creator"), "Creator should be hidden"); - is_element_hidden(get("detail-screenshot-box"), "Screenshot should be hidden"); + is_element_hidden(get("detail-screenshot"), "Screenshot should be hidden"); is(get("detail-screenshot").width, "", "Screenshot dimensions should not be set"); is(get("detail-screenshot").height, "", "Screenshot dimensions should not be set"); is(get("detail-desc").textContent, "Short description", "Description should be correct"); @@ -303,7 +272,7 @@ add_test(function() { is(get("detail-creator")._creatorName.value, "Mozilla", "Creator should be correct"); is_element_hidden(get("detail-creator")._creatorLink, "Creator link should be hidden"); - is_element_visible(get("detail-screenshot-box"), "Screenshot should be visible"); + is_element_visible(get("detail-screenshot"), "Screenshot should be visible"); is(get("detail-screenshot").src, "chrome://branding/content/about.png", "Should be showing the full sized screenshot"); is(get("detail-screenshot").width, 200, "Screenshot dimensions should be set"); is(get("detail-screenshot").height, 150, "Screenshot dimensions should be set"); @@ -360,7 +329,7 @@ add_test(function() { is(get("detail-creator")._creatorLink.value, "Mozilla", "Creator link should be correct"); is(get("detail-creator")._creatorLink.href, "http://www.mozilla.org", "Creator link href should be correct"); - is_element_visible(get("detail-screenshot-box"), "Screenshot should be visible"); + is_element_visible(get("detail-screenshot"), "Screenshot should be visible"); is(get("detail-screenshot").src, "chrome://branding/content/icon64.png", "Should be showing the thumbnail"); is(get("detail-screenshot").width, 160, "Screenshot dimensions should be set"); is(get("detail-screenshot").height, 120, "Screenshot dimensions should be set"); @@ -657,7 +626,7 @@ add_test(function() { is(get("detail-warning").textContent, "An important update is available for Test add-on 8.", "Warning message should be correct"); is_element_visible(get("detail-warning-link"), "Warning link should be visible"); is(get("detail-warning-link").value, "Update Now", "Warning link text should be correct"); - is(get("detail-warning-link").href, "http://example.com/addon8@tests.mozilla.org", "Warning link should be correct"); + is(get("detail-warning-link").href, gPluginURL, "Warning link should be correct"); is_element_hidden(get("detail-error"), "Error message should be hidden"); is_element_hidden(get("detail-error-link"), "Error link should be hidden"); is_element_hidden(get("detail-pending"), "Pending message should be hidden"); @@ -701,7 +670,7 @@ add_test(function() { is(get("detail-warning").textContent, "An important update is available for Test add-on 8.", "Warning message should be correct"); is_element_visible(get("detail-warning-link"), "Warning link should be visible"); is(get("detail-warning-link").value, "Update Now", "Warning link text should be correct"); - is(get("detail-warning-link").href, "http://example.com/addon8@tests.mozilla.org", "Warning link should be correct"); + is(get("detail-warning-link").href, gPluginURL, "Warning link should be correct"); is_element_hidden(get("detail-error"), "Error message should be hidden"); is_element_hidden(get("detail-error-link"), "Error link should be hidden"); is_element_hidden(get("detail-pending"), "Pending message should be hidden"); @@ -711,264 +680,6 @@ add_test(function() { }); }); -// These tests are only appropriate when signing can be turned off -if (!REQUIRE_SIGNING) { - // Opens and tests the details view for add-on 9 - add_test(function() { - open_details("addon9@tests.mozilla.org", "extension", function() { - is(get("detail-name").textContent, "Test add-on 9", "Name should be correct"); - - is_element_hidden(get("detail-prefs-btn"), "Preferences button should be hidden"); - is_element_hidden(get("detail-enable-btn"), "Enable button should be hidden"); - is_element_visible(get("detail-disable-btn"), "Disable button should be visible"); - is_element_visible(get("detail-uninstall-btn"), "Remove button should be visible"); - - is_element_hidden(get("detail-error"), "Error message should be hidden"); - is_element_hidden(get("detail-error-link"), "Error link should be hidden"); - is_element_visible(get("detail-warning"), "Error message should be visible"); - is(get("detail-warning").textContent, "Test add-on 9 could not be verified for use in " + gApp + ". Proceed with caution.", "Warning message should be correct"); - is_element_visible(get("detail-warning-link"), "Warning link should be visible"); - is(get("detail-warning-link").value, "More Information", "Warning link text should be correct"); - is(get("detail-warning-link").href, infoURL, "Warning link should be correct"); - is_element_hidden(get("detail-pending"), "Pending message should be hidden"); - - run_next_test(); - }); - }); -} - -// Opens and tests the details view for add-on 9 with signing required -add_test(function() { - close_manager(gManagerWindow, function() { - Services.prefs.setBoolPref("xpinstall.signatures.required", true); - open_manager(null, function(aWindow) { - gManagerWindow = aWindow; - gCategoryUtilities = new CategoryUtilities(gManagerWindow); - - open_details("addon9@tests.mozilla.org", "extension", function() { - is(get("detail-name").textContent, "Test add-on 9", "Name should be correct"); - - is_element_hidden(get("detail-prefs-btn"), "Preferences button should be hidden"); - is_element_hidden(get("detail-enable-btn"), "Enable button should be hidden"); - is_element_visible(get("detail-disable-btn"), "Disable button should be visible"); - is_element_visible(get("detail-uninstall-btn"), "Remove button should be visible"); - - is_element_hidden(get("detail-warning"), "Warning message should be hidden"); - is_element_hidden(get("detail-warning-link"), "Warning link should be hidden"); - is_element_visible(get("detail-error"), "Error message should be visible"); - is(get("detail-error").textContent, "Test add-on 9 could not be verified for use in " + gApp + " and has been disabled.", "Error message should be correct"); - is_element_visible(get("detail-error-link"), "Error link should be visible"); - is(get("detail-error-link").value, "More Information", "Error link text should be correct"); - is(get("detail-error-link").href, infoURL, "Error link should be correct"); - - close_manager(gManagerWindow, function() { - Services.prefs.setBoolPref("xpinstall.signatures.required", false); - open_manager(null, function(aWindow) { - gManagerWindow = aWindow; - gCategoryUtilities = new CategoryUtilities(gManagerWindow); - - run_next_test(); - }); - }); - }); - }); - }); -}); - -// These tests are only appropriate when signing can be turned off -if (!REQUIRE_SIGNING) { - // Opens and tests the details view for add-on 10 - add_test(function() { - open_details("addon10@tests.mozilla.org", "extension", function() { - is(get("detail-name").textContent, "Test add-on 10", "Name should be correct"); - - is_element_hidden(get("detail-prefs-btn"), "Preferences button should be hidden"); - is_element_hidden(get("detail-enable-btn"), "Enable button should be hidden"); - is_element_hidden(get("detail-disable-btn"), "Disable button should be hidden"); - is_element_visible(get("detail-uninstall-btn"), "Remove button should be visible"); - - is_element_visible(get("detail-warning"), "Warning message should be visible"); - is(get("detail-warning").textContent, "Test add-on 10 is incompatible with " + gApp + " " + gVersion + ".", "Warning message should be correct"); - is_element_hidden(get("detail-warning-link"), "Warning link should be hidden"); - is_element_hidden(get("detail-error"), "Error message should be hidden"); - is_element_hidden(get("detail-error-link"), "Error link should be hidden"); - is_element_hidden(get("detail-pending"), "Pending message should be hidden"); - - run_next_test(); - }); - }); -} - -// Opens and tests the details view for add-on 10 with signing required -add_test(function() { - close_manager(gManagerWindow, function() { - Services.prefs.setBoolPref("xpinstall.signatures.required", true); - open_manager(null, function(aWindow) { - gManagerWindow = aWindow; - gCategoryUtilities = new CategoryUtilities(gManagerWindow); - - open_details("addon10@tests.mozilla.org", "extension", function() { - is(get("detail-name").textContent, "Test add-on 10", "Name should be correct"); - - is_element_hidden(get("detail-prefs-btn"), "Preferences button should be hidden"); - is_element_hidden(get("detail-enable-btn"), "Enable button should be hidden"); - is_element_hidden(get("detail-disable-btn"), "Disable button should be hidden"); - is_element_visible(get("detail-uninstall-btn"), "Remove button should be visible"); - - is_element_hidden(get("detail-warning"), "Warning message should be hidden"); - is_element_hidden(get("detail-warning-link"), "Warning link should be hidden"); - is_element_visible(get("detail-error"), "Error message should be visible"); - is(get("detail-error").textContent, "Test add-on 10 could not be verified for use in " + gApp + " and has been disabled.", "Error message should be correct"); - is_element_visible(get("detail-error-link"), "Error link should be visible"); - is(get("detail-error-link").value, "More Information", "Error link text should be correct"); - is(get("detail-error-link").href, infoURL, "Error link should be correct"); - - close_manager(gManagerWindow, function() { - Services.prefs.setBoolPref("xpinstall.signatures.required", false); - open_manager(null, function(aWindow) { - gManagerWindow = aWindow; - gCategoryUtilities = new CategoryUtilities(gManagerWindow); - - run_next_test(); - }); - }); - }); - }); - }); -}); - -// Opens and tests the details view for add-on 11 -add_test(function() { - open_details("addon11@tests.mozilla.org", "extension", function() { - is(get("detail-name").textContent, "Test add-on 11", "Name should be correct"); - - is_element_hidden(get("detail-prefs-btn"), "Preferences button should be hidden"); - is_element_hidden(get("detail-enable-btn"), "Enable button should be hidden"); - is_element_hidden(get("detail-disable-btn"), "Disable button should be hidden"); - is_element_visible(get("detail-uninstall-btn"), "Remove button should be visible"); - - is_element_visible(get("detail-warning"), "Warning message should be visible"); - is(get("detail-warning").textContent, "Test add-on 11 is incompatible with " + gApp + " " + gVersion + ".", "Warning message should be correct"); - is_element_hidden(get("detail-warning-link"), "Warning link should be hidden"); - is_element_hidden(get("detail-error"), "Error message should be hidden"); - is_element_hidden(get("detail-error-link"), "Error link should be hidden"); - is_element_hidden(get("detail-pending"), "Pending message should be hidden"); - - run_next_test(); - }); -}); - -// Opens and tests the details view for add-on 11 with signing required -add_test(function() { - close_manager(gManagerWindow, function() { - Services.prefs.setBoolPref("xpinstall.signatures.required", true); - open_manager(null, function(aWindow) { - gManagerWindow = aWindow; - gCategoryUtilities = new CategoryUtilities(gManagerWindow); - - open_details("addon11@tests.mozilla.org", "extension", function() { - is(get("detail-name").textContent, "Test add-on 11", "Name should be correct"); - - is_element_hidden(get("detail-prefs-btn"), "Preferences button should be hidden"); - is_element_hidden(get("detail-enable-btn"), "Enable button should be hidden"); - is_element_hidden(get("detail-disable-btn"), "Disable button should be hidden"); - is_element_visible(get("detail-uninstall-btn"), "Remove button should be visible"); - - is_element_visible(get("detail-warning"), "Warning message should be visible"); - is(get("detail-warning").textContent, "Test add-on 11 is incompatible with " + gApp + " " + gVersion + ".", "Warning message should be correct"); - is_element_hidden(get("detail-warning-link"), "Warning link should be hidden"); - is_element_hidden(get("detail-error"), "Error message should be hidden"); - is_element_hidden(get("detail-error-link"), "Error link should be hidden"); - - close_manager(gManagerWindow, function() { - Services.prefs.setBoolPref("xpinstall.signatures.required", false); - open_manager(null, function(aWindow) { - gManagerWindow = aWindow; - gCategoryUtilities = new CategoryUtilities(gManagerWindow); - - run_next_test(); - }); - }); - }); - }); - }); -}); - -// Opens and tests the details view for add-on 12 -add_test(function() { - open_details("addon12@tests.mozilla.org", "extension", function() { - is(get("detail-name").textContent, "Test add-on 12", "Name should be correct"); - - is_element_hidden(get("detail-prefs-btn"), "Preferences button should be hidden"); - is_element_hidden(get("detail-enable-btn"), "Enable button should be hidden"); - is_element_visible(get("detail-disable-btn"), "Disable button should be visible"); - is_element_visible(get("detail-uninstall-btn"), "Remove button should be visible"); - - is_element_hidden(get("detail-warning"), "Warning message should be hidden"); - is_element_hidden(get("detail-warning-link"), "Warning link should be hidden"); - is_element_hidden(get("detail-error"), "Error message should be hidden"); - is_element_hidden(get("detail-error-link"), "Error link should be hidden"); - is_element_hidden(get("detail-pending"), "Pending message should be hidden"); - - run_next_test(); - }); -}); - -// Opens and tests the details view for add-on 12 with signing required -add_test(function() { - close_manager(gManagerWindow, function() { - Services.prefs.setBoolPref("xpinstall.signatures.required", true); - open_manager(null, function(aWindow) { - gManagerWindow = aWindow; - gCategoryUtilities = new CategoryUtilities(gManagerWindow); - - open_details("addon12@tests.mozilla.org", "extension", function() { - is(get("detail-name").textContent, "Test add-on 12", "Name should be correct"); - - is_element_hidden(get("detail-prefs-btn"), "Preferences button should be hidden"); - is_element_hidden(get("detail-enable-btn"), "Enable button should be hidden"); - is_element_visible(get("detail-disable-btn"), "Disable button should be visible"); - is_element_visible(get("detail-uninstall-btn"), "Remove button should be visible"); - - is_element_hidden(get("detail-warning"), "Warning message should be hidden"); - is_element_hidden(get("detail-warning-link"), "Warning link should be hidden"); - is_element_hidden(get("detail-error"), "Error message should be hidden"); - is_element_hidden(get("detail-error-link"), "Error link should be hidden"); - - close_manager(gManagerWindow, function() { - Services.prefs.setBoolPref("xpinstall.signatures.required", false); - open_manager(null, function(aWindow) { - gManagerWindow = aWindow; - gCategoryUtilities = new CategoryUtilities(gManagerWindow); - - run_next_test(); - }); - }); - }); - }); - }); -}); - -// Opens and tests the details view for hotfix 1 -add_test(function() { - open_details("hotfix@tests.mozilla.org", "extension", function() { - is(get("detail-name").textContent, "Test hotfix 1", "Name should be correct"); - - is_element_hidden(get("detail-updates-row"), "Updates should be hidden"); - - is_element_hidden(get("detail-prefs-btn"), "Preferences button should be hidden"); - is_element_hidden(get("detail-enable-btn"), "Enable button should be hidden"); - is_element_visible(get("detail-disable-btn"), "Disable button should be visible"); - is_element_visible(get("detail-uninstall-btn"), "Remove button should be visible"); - - is_element_hidden(get("detail-warning"), "Warning message should be hidden"); - is_element_hidden(get("detail-warning-link"), "Warning link should be hidden"); - is_element_hidden(get("detail-pending"), "Pending message should be hidden"); - - run_next_test(); - }); -}); - // Tests that upgrades with onExternalInstall apply immediately add_test(function() { open_details("addon1@tests.mozilla.org", "extension", function() { @@ -993,7 +704,7 @@ add_test(function() { is(get("detail-version").value, "2.5", "Version should be correct"); is(get("detail-icon").src, "chrome://foo/skin/icon264.png", "Icon should be correct"); is_element_hidden(get("detail-creator"), "Creator should be hidden"); - is_element_hidden(get("detail-screenshot-box"), "Screenshot should be hidden"); + is_element_hidden(get("detail-screenshot"), "Screenshot should be hidden"); is(get("detail-desc").textContent, "Short description replacement", "Description should be correct"); is(get("detail-fulldesc").textContent, "Longer description replacement", "Full description should be correct"); diff --git a/toolkit/mozapps/extensions/test/browser/browser_discovery.js b/toolkit/mozapps/extensions/test/browser/browser_discovery.js index ec336df2d..708ba311b 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_discovery.js +++ b/toolkit/mozapps/extensions/test/browser/browser_discovery.js @@ -576,13 +576,13 @@ add_test(function() { }); }); -// Test for Bug 601442 - extensions.getAddons.showPane need to be update +// Test for Bug 601442 - extensions.getAddons.showPane need to be update // for the new addon manager. function bug_601442_test_elements(visible) { open_manager("addons://list/extension", function(aWindow) { gManagerWindow = aWindow; gCategoryUtilities = new CategoryUtilities(gManagerWindow); - if (visible) + if(visible) ok(gCategoryUtilities.isTypeVisible("discover"), "Discover category should be visible"); else ok(!gCategoryUtilities.isTypeVisible("discover"), "Discover category should not be visible"); @@ -590,7 +590,7 @@ function bug_601442_test_elements(visible) { gManagerWindow.loadView("addons://list/dictionary"); wait_for_view_load(gManagerWindow, function(aManager) { var button = aManager.document.getElementById("discover-button-install"); - if (visible) + if(visible) ok(!is_hidden(button), "Discover button should be visible!"); else ok(is_hidden(button), "Discover button should not be visible!"); @@ -634,18 +634,4 @@ add_test(function() { close_manager(gManagerWindow, run_next_test); Services.prefs.clearUserPref(PREF_DISCOVER_ENABLED); }); -}); - -// Test for Bug 1219495 - should show placeholder content when offline -add_test(function() { - // set a URL to cause an error - Services.prefs.setCharPref(PREF_DISCOVERURL, "https://nocert.example.com/"); - - open_manager("addons://discover/", function(aWindow) { - gManagerWindow = aWindow; - - ok(isError(), "Should have shown the placeholder content"); - - close_manager(gManagerWindow, run_next_test); - }); -}); +});
\ No newline at end of file diff --git a/toolkit/mozapps/extensions/test/browser/browser_discovery_install.js b/toolkit/mozapps/extensions/test/browser/browser_discovery_install.js index 63516bd53..bd7d194f2 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_discovery_install.js +++ b/toolkit/mozapps/extensions/test/browser/browser_discovery_install.js @@ -4,26 +4,23 @@ // Tests that the discovery view can install add-ons correctly -const MAIN_URL = "https://example.com/" + RELATIVE_DIR + "discovery_install.html"; -const GOOD_FRAMED_URL = "https://example.com/" + RELATIVE_DIR + "discovery_frame.html"; -const BAD_FRAMED_URL = "https://example.org/" + RELATIVE_DIR + "discovery_frame.html"; - -const PREF_INSTALL_REQUIREBUILTINCERTS = "extensions.install.requireBuiltInCerts"; +const MAIN_URL = "https://test1.example.com/" + RELATIVE_DIR + "discovery_install.html"; +const GOOD_FRAMED_URL = "https://test1.example.com/" + RELATIVE_DIR + "discovery_frame.html"; +const BAD_FRAMED_URL = "https://test2.example.com/" + RELATIVE_DIR + "discovery_frame.html"; // Temporarily enable caching Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true); // Allow SSL from non-built-in certs -Services.prefs.setBoolPref(PREF_INSTALL_REQUIREBUILTINCERTS, false); +Services.prefs.setBoolPref("extensions.install.requireBuiltInCerts", false); // Allow installs from the test site -Services.perms.add(NetUtil.newURI("https://example.com/"), "install", +Services.perms.add(NetUtil.newURI("https://test1.example.com/"), "install", Ci.nsIPermissionManager.ALLOW_ACTION); -Services.perms.add(NetUtil.newURI("https://example.org/"), "install", +Services.perms.add(NetUtil.newURI("https://test2.example.com/"), "install", Ci.nsIPermissionManager.ALLOW_ACTION); registerCleanupFunction(() => { - Services.perms.remove(NetUtil.newURI("https://example.com/"), "install"); - Services.perms.remove(NetUtil.newURI("https://example.org/"), "install"); - Services.prefs.clearUserPref(PREF_INSTALL_REQUIREBUILTINCERTS); + Services.perms.remove("test1.example.com", "install"); + Services.perms.remove("test2.example.com", "install"); }); function clickLink(frameLoader, id) { diff --git a/toolkit/mozapps/extensions/test/browser/browser_dragdrop.js b/toolkit/mozapps/extensions/test/browser/browser_dragdrop.js index 960e7e933..1df288323 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_dragdrop.js +++ b/toolkit/mozapps/extensions/test/browser/browser_dragdrop.js @@ -8,13 +8,13 @@ // Tests are only simulations of the drag and drop events, we cannot really do // this automatically. -// Instead of loading EventUtils.js into the test scope in browser-test.js for all tests, -// we only need EventUtils.js for a few files which is why we are using loadSubScript. +// Instead of loading ChromeUtils.js into the test scope in browser-test.js for all tests, +// we only need ChromeUtils.js for a few files which is why we are using loadSubScript. var gManagerWindow; -var EventUtils = {}; +var ChromeUtils = {}; this._scriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"]. getService(Ci.mozIJSSubScriptLoader); -this._scriptLoader.loadSubScript("chrome://mochikit/content/tests/SimpleTest/EventUtils.js", EventUtils); +this._scriptLoader.loadSubScript("chrome://mochikit/content/tests/SimpleTest/ChromeUtils.js", ChromeUtils); // This listens for the next opened window and checks it is of the right url. // opencallback is called when the new window is fully loaded @@ -137,7 +137,7 @@ add_test(function() { }); var viewContainer = gManagerWindow.document.getElementById("view-port"); - var effect = EventUtils.synthesizeDrop(viewContainer, viewContainer, + var effect = ChromeUtils.synthesizeDrop(viewContainer, viewContainer, [[{type: "text/x-moz-url", data: url}]], "copy", gManagerWindow); is(effect, "copy", "Drag should be accepted"); @@ -158,7 +158,7 @@ add_test(function() { }); var viewContainer = gManagerWindow.document.getElementById("view-port"); - var effect = EventUtils.synthesizeDrop(viewContainer, viewContainer, + var effect = ChromeUtils.synthesizeDrop(viewContainer, viewContainer, [[{type: "application/x-moz-file", data: fileurl.file}]], "copy", gManagerWindow); is(effect, "copy", "Drag should be accepted"); @@ -180,7 +180,7 @@ add_test(function() { }); var viewContainer = gManagerWindow.document.getElementById("view-port"); - var effect = EventUtils.synthesizeDrop(viewContainer, viewContainer, + var effect = ChromeUtils.synthesizeDrop(viewContainer, viewContainer, [[{type: "text/x-moz-url", data: url1}], [{type: "text/x-moz-url", data: url2}]], "copy", gManagerWindow); @@ -203,7 +203,7 @@ add_test(function() { }); var viewContainer = gManagerWindow.document.getElementById("view-port"); - var effect = EventUtils.synthesizeDrop(viewContainer, viewContainer, + var effect = ChromeUtils.synthesizeDrop(viewContainer, viewContainer, [[{type: "application/x-moz-file", data: fileurl1.file}], [{type: "application/x-moz-file", data: fileurl2.file}]], "copy", gManagerWindow); @@ -226,7 +226,7 @@ add_test(function() { }); var viewContainer = gManagerWindow.document.getElementById("view-port"); - var effect = EventUtils.synthesizeDrop(viewContainer, viewContainer, + var effect = ChromeUtils.synthesizeDrop(viewContainer, viewContainer, [[{type: "text/x-moz-url", data: url}], [{type: "application/x-moz-file", data: fileurl.file}]], "copy", gManagerWindow); diff --git a/toolkit/mozapps/extensions/test/browser/browser_eula.xml b/toolkit/mozapps/extensions/test/browser/browser_eula.xml index 965ab8a0b..87b5997cf 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_eula.xml +++ b/toolkit/mozapps/extensions/test/browser/browser_eula.xml @@ -18,7 +18,7 @@ <compatible_applications> <application> <name>Firefox</name> - <appID>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</appID> + <appID>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</appID> <min_version>0</min_version> <max_version>*</max_version> </application> diff --git a/toolkit/mozapps/extensions/test/browser/browser_experiments.js b/toolkit/mozapps/extensions/test/browser/browser_experiments.js deleted file mode 100644 index 18a548de5..000000000 --- a/toolkit/mozapps/extensions/test/browser/browser_experiments.js +++ /dev/null @@ -1,654 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -Components.utils.import("resource://gre/modules/Promise.jsm", this); - -var {AddonManagerTesting} = Components.utils.import("resource://testing-common/AddonManagerTesting.jsm", {}); -var {HttpServer} = Components.utils.import("resource://testing-common/httpd.js", {}); - -var gManagerWindow; -var gCategoryUtilities; -var gExperiments; -var gHttpServer; - -var gSavedManifestURI; -var gIsEnUsLocale; - -const SEC_IN_ONE_DAY = 24 * 60 * 60; -const MS_IN_ONE_DAY = SEC_IN_ONE_DAY * 1000; - -function getExperimentAddons() { - let deferred = Promise.defer(); - AddonManager.getAddonsByTypes(["experiment"], (addons) => { - deferred.resolve(addons); - }); - return deferred.promise; -} - -function getInstallItem() { - let doc = gManagerWindow.document; - let view = get_current_view(gManagerWindow); - let list = doc.getElementById("addon-list"); - - let node = list.firstChild; - while (node) { - if (node.getAttribute("status") == "installing") { - return node; - } - node = node.nextSibling; - } - - return null; -} - -function patchPolicy(policy, data) { - for (let key of Object.keys(data)) { - Object.defineProperty(policy, key, { - value: data[key], - writable: true, - }); - } -} - -function defineNow(policy, time) { - patchPolicy(policy, { now: () => new Date(time) }); -} - -function openDetailsView(aId) { - let item = get_addon_element(gManagerWindow, aId); - Assert.ok(item, "Should have got add-on element."); - is_element_visible(item, "Add-on element should be visible."); - - EventUtils.synthesizeMouseAtCenter(item, { clickCount: 1 }, gManagerWindow); - EventUtils.synthesizeMouseAtCenter(item, { clickCount: 2 }, gManagerWindow); - - let deferred = Promise.defer(); - wait_for_view_load(gManagerWindow, deferred.resolve); - return deferred.promise; -} - -function clickRemoveButton(addonElement) { - let btn = gManagerWindow.document.getAnonymousElementByAttribute(addonElement, "anonid", "remove-btn"); - if (!btn) { - return Promise.reject(); - } - - EventUtils.synthesizeMouseAtCenter(btn, { clickCount: 1 }, gManagerWindow); - let deferred = Promise.defer(); - setTimeout(deferred.resolve, 0); - return deferred; -} - -function clickUndoButton(addonElement) { - let btn = gManagerWindow.document.getAnonymousElementByAttribute(addonElement, "anonid", "undo-btn"); - if (!btn) { - return Promise.reject(); - } - - EventUtils.synthesizeMouseAtCenter(btn, { clickCount: 1 }, gManagerWindow); - let deferred = Promise.defer(); - setTimeout(deferred.resolve, 0); - return deferred; -} - -add_task(function* initializeState() { - gManagerWindow = yield open_manager(); - gCategoryUtilities = new CategoryUtilities(gManagerWindow); - - registerCleanupFunction(() => { - Services.prefs.clearUserPref("experiments.enabled"); - Services.prefs.clearUserPref("toolkit.telemetry.enabled"); - if (gHttpServer) { - gHttpServer.stop(() => {}); - if (gSavedManifestURI !== undefined) { - Services.prefs.setCharPref("experments.manifest.uri", gSavedManifestURI); - } - } - if (gExperiments) { - let tmp = {}; - Cu.import("resource:///modules/experiments/Experiments.jsm", tmp); - gExperiments._policy = new tmp.Experiments.Policy(); - } - }); - - let chrome = Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIXULChromeRegistry); - gIsEnUsLocale = chrome.getSelectedLocale("global") == "en-US"; - - // The Experiments Manager will interfere with us by preventing installs - // of experiments it doesn't know about. We remove it from the equation - // because here we are only concerned with core Addon Manager operation, - // not the superset Experiments Manager has imposed. - if ("@mozilla.org/browser/experiments-service;1" in Components.classes) { - let tmp = {}; - Cu.import("resource:///modules/experiments/Experiments.jsm", tmp); - // There is a race condition between XPCOM service initialization and - // this test running. We have to initialize the instance first, then - // uninitialize it to prevent this. - gExperiments = tmp.Experiments.instance(); - yield gExperiments._mainTask; - yield gExperiments.uninit(); - } -}); - -// On an empty profile with no experiments, the experiment category -// should be hidden. -add_task(function* testInitialState() { - Assert.ok(gCategoryUtilities.get("experiment", false), "Experiment tab is defined."); - Assert.ok(!gCategoryUtilities.isTypeVisible("experiment"), "Experiment tab hidden by default."); -}); - -add_task(function* testExperimentInfoNotVisible() { - yield gCategoryUtilities.openType("extension"); - let el = gManagerWindow.document.getElementsByClassName("experiment-info-container")[0]; - is_element_hidden(el, "Experiment info not visible on other types."); -}); - -// If we have an active experiment, we should see the experiments tab -// and that tab should have some messages. -add_task(function* testActiveExperiment() { - let addon = yield install_addon("addons/browser_experiment1.xpi"); - - Assert.ok(addon.userDisabled, "Add-on is disabled upon initial install."); - Assert.equal(addon.isActive, false, "Add-on is not active."); - - Assert.ok(gCategoryUtilities.isTypeVisible("experiment"), "Experiment tab visible."); - - yield gCategoryUtilities.openType("experiment"); - let el = gManagerWindow.document.getElementsByClassName("experiment-info-container")[0]; - is_element_visible(el, "Experiment info is visible on experiment tab."); -}); - -add_task(function* testExperimentLearnMore() { - // Actual URL is irrelevant. - Services.prefs.setCharPref("toolkit.telemetry.infoURL", - "http://mochi.test:8888/server.js"); - - yield gCategoryUtilities.openType("experiment"); - let btn = gManagerWindow.document.getElementById("experiments-learn-more"); - - if (!gUseInContentUI) { - is_element_hidden(btn, "Learn more button hidden if not using in-content UI."); - Services.prefs.clearUserPref("toolkit.telemetry.infoURL"); - - return; - } - - is_element_visible(btn, "Learn more button visible."); - - let deferred = Promise.defer(); - window.addEventListener("DOMContentLoaded", function onLoad(event) { - info("Telemetry privacy policy window opened."); - window.removeEventListener("DOMContentLoaded", onLoad, false); - - let browser = gBrowser.selectedBrowser; - let expected = Services.prefs.getCharPref("toolkit.telemetry.infoURL"); - Assert.equal(browser.currentURI.spec, expected, "New tab should have loaded privacy policy."); - browser.contentWindow.close(); - - Services.prefs.clearUserPref("toolkit.telemetry.infoURL"); - - deferred.resolve(); - }, false); - - info("Opening telemetry privacy policy."); - EventUtils.synthesizeMouseAtCenter(btn, {}, gManagerWindow); - - yield deferred.promise; -}); - -add_task(function* testOpenPreferences() { - yield gCategoryUtilities.openType("experiment"); - let btn = gManagerWindow.document.getElementById("experiments-change-telemetry"); - if (!gUseInContentUI) { - is_element_hidden(btn, "Change telemetry button not enabled in out of window UI."); - info("Skipping preferences open test because not using in-content UI."); - return; - } - - is_element_visible(btn, "Change telemetry button visible in in-content UI."); - - let deferred = Promise.defer(); - Services.obs.addObserver(function observer(prefWin, topic, data) { - Services.obs.removeObserver(observer, "advanced-pane-loaded"); - info("Advanced preference pane opened."); - executeSoon(function() { - // We want this test to fail if the preferences pane changes. - let el = prefWin.document.getElementById("dataChoicesPanel"); - is_element_visible(el); - - prefWin.close(); - info("Closed preferences pane."); - - deferred.resolve(); - }); - }, "advanced-pane-loaded", false); - - info("Loading preferences pane."); - // We need to focus before synthesizing the mouse event (bug 1240052) as - // synthesizeMouseAtCenter currently only synthesizes the mouse in the child process. - // This can cause some subtle differences if the child isn't focused. - yield SimpleTest.promiseFocus(); - yield BrowserTestUtils.synthesizeMouseAtCenter("#experiments-change-telemetry", {}, - gBrowser.selectedBrowser); - - yield deferred.promise; -}); - -add_task(function* testButtonPresence() { - yield gCategoryUtilities.openType("experiment"); - let item = get_addon_element(gManagerWindow, "test-experiment1@experiments.mozilla.org"); - Assert.ok(item, "Got add-on element."); - item.parentNode.ensureElementIsVisible(item); - - let el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "remove-btn"); - // Corresponds to the uninstall permission. - is_element_visible(el, "Remove button is visible."); - // Corresponds to lack of disable permission. - el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "disable-btn"); - is_element_hidden(el, "Disable button not visible."); - // Corresponds to lack of enable permission. - el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "enable-btn"); - is_element_hidden(el, "Enable button not visible."); -}); - -// Remove the add-on we've been testing with. -add_task(function* testCleanup() { - yield AddonManagerTesting.uninstallAddonByID("test-experiment1@experiments.mozilla.org"); - // Verify some conditions, just in case. - let addons = yield getExperimentAddons(); - Assert.equal(addons.length, 0, "No experiment add-ons are installed."); -}); - -// The following tests should ideally live in browser/experiments/. However, -// they rely on some of the helper functions from head.js, which can't easily -// be consumed from other directories. So, they live here. - -add_task(function* testActivateExperiment() { - if (!gExperiments) { - info("Skipping experiments test because that feature isn't available."); - return; - } - - gHttpServer = new HttpServer(); - gHttpServer.start(-1); - let root = "http://localhost:" + gHttpServer.identity.primaryPort + "/"; - gHttpServer.registerPathHandler("/manifest", (request, response) => { - response.setStatusLine(null, 200, "OK"); - response.write(JSON.stringify({ - "version": 1, - "experiments": [ - { - id: "experiment-1", - xpiURL: TESTROOT + "addons/browser_experiment1.xpi", - xpiHash: "IRRELEVANT", - startTime: Date.now() / 1000 - 3600, - endTime: Date.now() / 1000 + 3600, - maxActiveSeconds: 600, - appName: [Services.appinfo.name], - channel: [gExperiments._policy.updatechannel()], - }, - ], - })); - response.processAsync(); - response.finish(); - }); - - gSavedManifestURI = Services.prefs.getCharPref("experiments.manifest.uri"); - Services.prefs.setCharPref("experiments.manifest.uri", root + "manifest"); - - // We need to remove the cache file to help ensure consistent state. - yield OS.File.remove(gExperiments._cacheFilePath); - - Services.prefs.setBoolPref("toolkit.telemetry.enabled", true); - Services.prefs.setBoolPref("experiments.enabled", true); - - info("Initializing experiments service."); - yield gExperiments.init(); - info("Experiments service finished first run."); - - // Check conditions, just to be sure. - let experiments = yield gExperiments.getExperiments(); - Assert.equal(experiments.length, 0, "No experiments known to the service."); - - // This makes testing easier. - gExperiments._policy.ignoreHashes = true; - - info("Manually updating experiments manifest."); - yield gExperiments.updateManifest(); - info("Experiments update complete."); - - let deferred = Promise.defer(); - gHttpServer.stop(() => { - gHttpServer = null; - - info("getting experiment by ID"); - AddonManager.getAddonByID("test-experiment1@experiments.mozilla.org", (addon) => { - Assert.ok(addon, "Add-on installed via Experiments manager."); - - deferred.resolve(); - }); - }); - - yield deferred.promise; - - Assert.ok(gCategoryUtilities.isTypeVisible, "experiment", "Experiment tab visible."); - yield gCategoryUtilities.openType("experiment"); - let el = gManagerWindow.document.getElementsByClassName("experiment-info-container")[0]; - is_element_visible(el, "Experiment info is visible on experiment tab."); -}); - -add_task(function* testDeactivateExperiment() { - if (!gExperiments) { - return; - } - - // Fake an empty manifest to purge data from previous manifest. - yield gExperiments._updateExperiments({ - "version": 1, - "experiments": [], - }); - - yield gExperiments.disableExperiment("testing"); - - // We should have a record of the previously-active experiment. - let experiments = yield gExperiments.getExperiments(); - Assert.equal(experiments.length, 1, "1 experiment is known."); - Assert.equal(experiments[0].active, false, "Experiment is not active."); - - // We should have a previous experiment in the add-ons manager. - let deferred = Promise.defer(); - AddonManager.getAddonsByTypes(["experiment"], (addons) => { - deferred.resolve(addons); - }); - let addons = yield deferred.promise; - Assert.equal(addons.length, 1, "1 experiment add-on known."); - Assert.ok(addons[0].appDisabled, "It is a previous experiment."); - Assert.equal(addons[0].id, "experiment-1", "Add-on ID matches expected."); - - // Verify the UI looks sane. - - Assert.ok(gCategoryUtilities.isTypeVisible("experiment"), "Experiment tab visible."); - let item = get_addon_element(gManagerWindow, "experiment-1"); - Assert.ok(item, "Got add-on element."); - Assert.ok(!item.active, "Element should not be active."); - item.parentNode.ensureElementIsVisible(item); - - // User control buttons should not be present because previous experiments - // should have no permissions. - let el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "remove-btn"); - is_element_hidden(el, "Remove button is not visible."); - el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "disable-btn"); - is_element_hidden(el, "Disable button is not visible."); - el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "enable-btn"); - is_element_hidden(el, "Enable button is not visible."); - el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "preferences-btn"); - is_element_hidden(el, "Preferences button is not visible."); -}); - -add_task(function* testActivateRealExperiments() { - if (!gExperiments) { - info("Skipping experiments test because that feature isn't available."); - return; - } - - yield gExperiments._updateExperiments({ - "version": 1, - "experiments": [ - { - id: "experiment-2", - xpiURL: TESTROOT + "addons/browser_experiment1.xpi", - xpiHash: "IRRELEVANT", - startTime: Date.now() / 1000 - 3600, - endTime: Date.now() / 1000 + 3600, - maxActiveSeconds: 600, - appName: [Services.appinfo.name], - channel: [gExperiments._policy.updatechannel()], - }, - ], - }); - yield gExperiments._run(); - - // Check the active experiment. - - let item = get_addon_element(gManagerWindow, "test-experiment1@experiments.mozilla.org"); - Assert.ok(item, "Got add-on element."); - item.parentNode.ensureElementIsVisible(item); - - let el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "experiment-state"); - is_element_visible(el, "Experiment state label should be visible."); - if (gIsEnUsLocale) { - Assert.equal(el.value, "Active"); - } - - el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "experiment-time"); - is_element_visible(el, "Experiment time label should be visible."); - if (gIsEnUsLocale) { - Assert.equal(el.value, "Less than a day remaining"); - } - - el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "error-container"); - is_element_hidden(el, "error-container should be hidden."); - el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "warning-container"); - is_element_hidden(el, "warning-container should be hidden."); - el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "pending-container"); - is_element_hidden(el, "pending-container should be hidden."); - let { version } = yield get_tooltip_info(item); - Assert.equal(version, undefined, "version should be hidden."); - el = item.ownerDocument.getAnonymousElementByAttribute(item, "class", "disabled-postfix"); - is_element_hidden(el, "disabled-postfix should be hidden."); - el = item.ownerDocument.getAnonymousElementByAttribute(item, "class", "update-postfix"); - is_element_hidden(el, "update-postfix should be hidden."); - el = item.ownerDocument.getAnonymousElementByAttribute(item, "class", "experiment-bullet"); - is_element_visible(el, "experiment-bullet should be visible."); - - // Check the previous experiment. - - item = get_addon_element(gManagerWindow, "experiment-1"); - Assert.ok(item, "Got add-on element."); - item.parentNode.ensureElementIsVisible(item); - - el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "experiment-state"); - is_element_visible(el, "Experiment state label should be visible."); - if (gIsEnUsLocale) { - Assert.equal(el.value, "Complete"); - } - - el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "experiment-time"); - is_element_visible(el, "Experiment time label should be visible."); - if (gIsEnUsLocale) { - Assert.equal(el.value, "Less than a day ago"); - } - - el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "error-container"); - is_element_hidden(el, "error-container should be hidden."); - el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "warning-container"); - is_element_hidden(el, "warning-container should be hidden."); - el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "pending-container"); - is_element_hidden(el, "pending-container should be hidden."); - ({ version } = yield get_tooltip_info(item)); - Assert.equal(version, undefined, "version should be hidden."); - el = item.ownerDocument.getAnonymousElementByAttribute(item, "class", "disabled-postfix"); - is_element_hidden(el, "disabled-postfix should be hidden."); - el = item.ownerDocument.getAnonymousElementByAttribute(item, "class", "update-postfix"); - is_element_hidden(el, "update-postfix should be hidden."); - el = item.ownerDocument.getAnonymousElementByAttribute(item, "class", "experiment-bullet"); - is_element_visible(el, "experiment-bullet should be visible."); - - // Install an "older" experiment. - - yield gExperiments.disableExperiment("experiment-2"); - - let now = Date.now(); - let fakeNow = now - 5 * MS_IN_ONE_DAY; - defineNow(gExperiments._policy, fakeNow); - - yield gExperiments._updateExperiments({ - "version": 1, - "experiments": [ - { - id: "experiment-3", - xpiURL: TESTROOT + "addons/browser_experiment1.xpi", - xpiHash: "IRRELEVANT", - startTime: fakeNow / 1000 - SEC_IN_ONE_DAY, - endTime: now / 1000 + 10 * SEC_IN_ONE_DAY, - maxActiveSeconds: 100 * SEC_IN_ONE_DAY, - appName: [Services.appinfo.name], - channel: [gExperiments._policy.updatechannel()], - }, - ], - }); - yield gExperiments._run(); - - // Check the active experiment. - - item = get_addon_element(gManagerWindow, "test-experiment1@experiments.mozilla.org"); - Assert.ok(item, "Got add-on element."); - item.parentNode.ensureElementIsVisible(item); - - el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "experiment-state"); - is_element_visible(el, "Experiment state label should be visible."); - if (gIsEnUsLocale) { - Assert.equal(el.value, "Active"); - } - - el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "experiment-time"); - is_element_visible(el, "Experiment time label should be visible."); - if (gIsEnUsLocale) { - Assert.equal(el.value, "10 days remaining"); - } - - // Disable it and check it's previous experiment entry. - - yield gExperiments.disableExperiment("experiment-3"); - - item = get_addon_element(gManagerWindow, "experiment-3"); - Assert.ok(item, "Got add-on element."); - item.parentNode.ensureElementIsVisible(item); - - el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "experiment-state"); - is_element_visible(el, "Experiment state label should be visible."); - if (gIsEnUsLocale) { - Assert.equal(el.value, "Complete"); - } - - el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "experiment-time"); - is_element_visible(el, "Experiment time label should be visible."); - if (gIsEnUsLocale) { - Assert.equal(el.value, "5 days ago"); - } -}); - -add_task(function* testDetailView() { - if (!gExperiments) { - info("Skipping experiments test because that feature isn't available."); - return; - } - - defineNow(gExperiments._policy, Date.now()); - yield gExperiments._updateExperiments({ - "version": 1, - "experiments": [ - { - id: "experiment-4", - xpiURL: TESTROOT + "addons/browser_experiment1.xpi", - xpiHash: "IRRELEVANT", - startTime: Date.now() / 1000 - 3600, - endTime: Date.now() / 1000 + 3600, - maxActiveSeconds: 600, - appName: [Services.appinfo.name], - channel: [gExperiments._policy.updatechannel()], - }, - ], - }); - yield gExperiments._run(); - - // Check active experiment. - - yield openDetailsView("test-experiment1@experiments.mozilla.org"); - - let el = gManagerWindow.document.getElementById("detail-experiment-state"); - is_element_visible(el, "Experiment state label should be visible."); - if (gIsEnUsLocale) { - Assert.equal(el.value, "Active"); - } - - el = gManagerWindow.document.getElementById("detail-experiment-time"); - is_element_visible(el, "Experiment time label should be visible."); - if (gIsEnUsLocale) { - Assert.equal(el.value, "Less than a day remaining"); - } - - el = gManagerWindow.document.getElementById("detail-version"); - is_element_hidden(el, "detail-version should be hidden."); - el = gManagerWindow.document.getElementById("detail-creator"); - is_element_hidden(el, "detail-creator should be hidden."); - el = gManagerWindow.document.getElementById("detail-experiment-bullet"); - is_element_visible(el, "experiment-bullet should be visible."); - - // Check previous experiment. - - yield gCategoryUtilities.openType("experiment"); - yield openDetailsView("experiment-3"); - - el = gManagerWindow.document.getElementById("detail-experiment-state"); - is_element_visible(el, "Experiment state label should be visible."); - if (gIsEnUsLocale) { - Assert.equal(el.value, "Complete"); - } - - el = gManagerWindow.document.getElementById("detail-experiment-time"); - is_element_visible(el, "Experiment time label should be visible."); - if (gIsEnUsLocale) { - Assert.equal(el.value, "5 days ago"); - } - - el = gManagerWindow.document.getElementById("detail-version"); - is_element_hidden(el, "detail-version should be hidden."); - el = gManagerWindow.document.getElementById("detail-creator"); - is_element_hidden(el, "detail-creator should be hidden."); - el = gManagerWindow.document.getElementById("detail-experiment-bullet"); - is_element_visible(el, "experiment-bullet should be visible."); -}); - -add_task(function* testRemoveAndUndo() { - if (!gExperiments) { - info("Skipping experiments test because that feature isn't available."); - return; - } - - yield gCategoryUtilities.openType("experiment"); - - let addon = get_addon_element(gManagerWindow, "test-experiment1@experiments.mozilla.org"); - Assert.ok(addon, "Got add-on element."); - - yield clickRemoveButton(addon); - addon.parentNode.ensureElementIsVisible(addon); - - let el = gManagerWindow.document.getAnonymousElementByAttribute(addon, "class", "pending"); - is_element_visible(el, "Uninstall undo information should be visible."); - - yield clickUndoButton(addon); - addon = get_addon_element(gManagerWindow, "test-experiment1@experiments.mozilla.org"); - Assert.ok(addon, "Got add-on element."); -}); - -add_task(function* testCleanup() { - if (gExperiments) { - Services.prefs.clearUserPref("experiments.enabled"); - Services.prefs.setCharPref("experiments.manifest.uri", gSavedManifestURI); - - // We perform the uninit/init cycle to purge any leftover state. - yield OS.File.remove(gExperiments._cacheFilePath); - yield gExperiments.uninit(); - yield gExperiments.init(); - - Services.prefs.clearUserPref("toolkit.telemetry.enabled"); - } - - // Check post-conditions. - let addons = yield getExperimentAddons(); - Assert.equal(addons.length, 0, "No experiment add-ons are installed."); - - yield close_manager(gManagerWindow); -}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_globalinformations.js b/toolkit/mozapps/extensions/test/browser/browser_globalinformations.js new file mode 100644 index 000000000..33890d8f5 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_globalinformations.js @@ -0,0 +1,55 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Bug 656269 - Add link to Mozilla plugin check from Add-ons Manager + +const MAIN_URL = "https://example.com/" + RELATIVE_DIR + "discovery.html"; +const PREF_PLUGINCHECKURL = "plugins.update.url"; + +function test() { + waitForExplicitFinish(); + + Services.prefs.setCharPref(PREF_PLUGINCHECKURL, MAIN_URL); + registerCleanupFunction(function() { + Services.prefs.clearUserPref(PREF_PLUGINCHECKURL); + }); + + run_next_test(); +} + +function end_test() { + finish(); +} + +add_test(function() { + open_manager("addons://list/extension", function(aManager) { + info("Testing plugin check information"); + var button = aManager.document.querySelector("#list-view button.global-info-plugincheck"); + is_element_hidden(button, "Plugin Check message button should be hidden"); + + info("Changing view to plugins") + EventUtils.synthesizeMouseAtCenter(aManager.document.getElementById("category-plugin"), { }, aManager); + + wait_for_view_load(aManager, function(aManager) { + var button = aManager.document.querySelector("#list-view button.global-info-plugincheck"); + is_element_visible(button, "Plugin Check message button should be visible"); + + info("Clicking 'Plugin Check' button"); + EventUtils.synthesizeMouseAtCenter(button, { }, aManager); + gBrowser.addEventListener("load", function(event) { + if (!(event.target instanceof Document) || + event.target.location.href == "about:blank") + return; + gBrowser.removeEventListener("load", arguments.callee, true); + + is(gBrowser.currentURI.spec, Services.urlFormatter.formatURLPref("plugins.update.url"), "Plugin Check URL should match"); + + gBrowser.removeCurrentTab(); + close_manager(aManager, function() { + run_next_test(); + }); + }, true); + }); + }); +});
\ No newline at end of file diff --git a/toolkit/mozapps/extensions/test/browser/browser_gmpProvider.js b/toolkit/mozapps/extensions/test/browser/browser_gmpProvider.js index 52079a263..1813df78c 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_gmpProvider.js +++ b/toolkit/mozapps/extensions/test/browser/browser_gmpProvider.js @@ -5,42 +5,37 @@ "use strict"; Cu.import("resource://gre/modules/Promise.jsm"); -Cu.import("resource://gre/modules/AppConstants.jsm"); -var {AddonTestUtils} = Cu.import("resource://testing-common/AddonManagerTesting.jsm", {}); -var GMPScope = Cu.import("resource://gre/modules/addons/GMPProvider.jsm"); +let {AddonTestUtils} = Cu.import("resource://testing-common/AddonManagerTesting.jsm", {}); +let GMPScope = Cu.import("resource://gre/modules/addons/GMPProvider.jsm"); const TEST_DATE = new Date(2013, 0, 1, 12); -var gManagerWindow; -var gCategoryUtilities; -var gIsEnUsLocale; +let gManagerWindow; +let gCategoryUtilities; +let gIsEnUsLocale; -var gMockAddons = []; +let gMockAddons = []; for (let plugin of GMPScope.GMP_PLUGINS) { let mockAddon = Object.freeze({ id: plugin.id, isValid: true, isInstalled: false, - isEME: (plugin.id == "gmp-widevinecdm" || - plugin.id.indexOf("gmp-eme-") == 0) ? true : false, + isEME: plugin.id.indexOf("gmp-eme-") == 0 ? true : false, }); gMockAddons.push(mockAddon); } -var gInstalledAddonId = ""; -var gInstallDeferred = null; -var gPrefs = Services.prefs; -var getKey = GMPScope.GMPPrefs.getPrefKey; +let gInstalledAddonId = ""; +let gInstallDeferred = null; +let gPrefs = Services.prefs; +let getKey = GMPScope.GMPPrefs.getPrefKey; function MockGMPInstallManager() { } MockGMPInstallManager.prototype = { - checkForAddons: () => Promise.resolve({ - usedFallback: true, - gmpAddons: gMockAddons - }), + checkForAddons: () => Promise.resolve(gMockAddons), installAddon: addon => { gInstalledAddonId = addon.id; @@ -49,7 +44,7 @@ MockGMPInstallManager.prototype = { }, }; -var gOptionsObserver = { +let gOptionsObserver = { lastDisplayed: null, observe: function(aSubject, aTopic, aData) { if (aTopic == AddonManager.OPTIONS_NOTIFICATION_DISPLAYED) { @@ -74,14 +69,10 @@ function getInstallItem() { } function openDetailsView(aId) { - let view = get_current_view(gManagerWindow); - Assert.equal(view.id, "list-view", "Should be in the list view to use this function"); - let item = get_addon_element(gManagerWindow, aId); Assert.ok(item, "Should have got add-on element."); is_element_visible(item, "Add-on element should be visible."); - item.scrollIntoView(); EventUtils.synthesizeMouseAtCenter(item, { clickCount: 1 }, gManagerWindow); EventUtils.synthesizeMouseAtCenter(item, { clickCount: 2 }, gManagerWindow); @@ -105,8 +96,7 @@ add_task(function* initializeState() { gPrefs.clearUserPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_LAST_UPDATE, addon.id)); gPrefs.clearUserPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_AUTOUPDATE, addon.id)); gPrefs.clearUserPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_VERSION, addon.id)); - gPrefs.clearUserPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_VISIBLE, addon.id)); - gPrefs.clearUserPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_FORCE_SUPPORTED, addon.id)); + gPrefs.clearUserPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_FORCEVISIBLE, addon.id)); } gPrefs.clearUserPref(GMPScope.GMPPrefs.KEY_LOGGING_DUMP); gPrefs.clearUserPref(GMPScope.GMPPrefs.KEY_LOGGING_LEVEL); @@ -129,8 +119,8 @@ add_task(function* initializeState() { gPrefs.setIntPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_LAST_UPDATE, addon.id), 0); gPrefs.setBoolPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_AUTOUPDATE, addon.id), false); gPrefs.setCharPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_VERSION, addon.id), ""); - gPrefs.setBoolPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_VISIBLE, addon.id), true); - gPrefs.setBoolPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_FORCE_SUPPORTED, addon.id), true); + gPrefs.setBoolPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_FORCEVISIBLE, addon.id), + true); } yield GMPScope.GMPProvider.shutdown(); GMPScope.GMPProvider.startup(); @@ -175,12 +165,13 @@ add_task(function* testNotInstalledDisabledDetails() { el = doc.getElementById("detail-warning"); is_element_hidden(el, "Warning notification is hidden."); el = doc.getElementsByTagName("setting")[0]; - - yield gCategoryUtilities.openType("plugin"); } }); add_task(function* testNotInstalled() { + Assert.ok(gCategoryUtilities.isTypeVisible("plugin"), "Plugin tab visible."); + yield gCategoryUtilities.openType("plugin"); + for (let addon of gMockAddons) { gPrefs.setBoolPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_ENABLED, addon.id), true); let item = get_addon_element(gManagerWindow, addon.id); @@ -217,8 +208,6 @@ add_task(function* testNotInstalledDetails() { el = doc.getElementById("detail-warning"); is_element_visible(el, "Warning notification is visible."); el = doc.getElementsByTagName("setting")[0]; - - yield gCategoryUtilities.openType("plugin"); } }); @@ -229,6 +218,8 @@ add_task(function* testInstalled() { gPrefs.setBoolPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_AUTOUPDATE, addon.id), false); gPrefs.setCharPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_VERSION, addon.id), "1.2.3.4"); + yield gCategoryUtilities.openType("plugin"); + let item = get_addon_element(gManagerWindow, addon.id); Assert.ok(item, "Got add-on element."); item.parentNode.ensureElementIsVisible(item); @@ -278,14 +269,14 @@ add_task(function* testInstalledDetails() { let menuSep = doc.getElementById("addonitem-menuseparator"); is_element_hidden(menuSep, "Menu separator is hidden."); contextMenu.hidePopup(); - - yield gCategoryUtilities.openType("plugin"); } }); add_task(function* testInstalledGlobalEmeDisabled() { gPrefs.setBoolPref(GMPScope.GMPPrefs.KEY_EME_ENABLED, false); for (let addon of gMockAddons) { + yield gCategoryUtilities.openType("plugin"); + let item = get_addon_element(gManagerWindow, addon.id); if (addon.isEME) { Assert.ok(!item, "Couldn't get add-on element."); @@ -374,7 +365,7 @@ add_task(function* testUpdateButton() { add_task(function* testEmeSupport() { for (let addon of gMockAddons) { - gPrefs.clearUserPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_FORCE_SUPPORTED, addon.id)); + gPrefs.clearUserPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_FORCEVISIBLE, addon.id)); } yield GMPScope.GMPProvider.shutdown(); GMPScope.GMPProvider.startup(); @@ -384,29 +375,21 @@ add_task(function* testEmeSupport() { let doc = gManagerWindow.document; let item = get_addon_element(gManagerWindow, addon.id); if (addon.id == GMPScope.EME_ADOBE_ID) { - if (AppConstants.isPlatformAndVersionAtLeast("win", "6")) { + if (Services.appinfo.OS == "WINNT" && + Services.sysinfo.getPropertyAsInt32("version") >= 6) { Assert.ok(item, "Adobe EME supported, found add-on element."); } else { Assert.ok(!item, "Adobe EME not supported, couldn't find add-on element."); } - } else if (addon.id == GMPScope.WIDEVINE_ID) { - if (AppConstants.isPlatformAndVersionAtLeast("win", "6") || - AppConstants.platform == "macosx" || - AppConstants.platform == "linux") { - Assert.ok(item, "Widevine supported, found add-on element."); - } else { - Assert.ok(!item, - "Widevine not supported, couldn't find add-on element."); - } } else { Assert.ok(item, "Found add-on element."); } } for (let addon of gMockAddons) { - gPrefs.setBoolPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_VISIBLE, addon.id), true); - gPrefs.setBoolPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_FORCE_SUPPORTED, addon.id), true); + gPrefs.setBoolPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_FORCEVISIBLE, addon.id), + true); } yield GMPScope.GMPProvider.shutdown(); GMPScope.GMPProvider.startup(); diff --git a/toolkit/mozapps/extensions/test/browser/browser_hotfix.js b/toolkit/mozapps/extensions/test/browser/browser_hotfix.js deleted file mode 100644 index b7bb3f580..000000000 --- a/toolkit/mozapps/extensions/test/browser/browser_hotfix.js +++ /dev/null @@ -1,171 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -const PREF_EM_HOTFIX_ID = "extensions.hotfix.id"; -const PREF_EM_HOTFIX_LASTVERSION = "extensions.hotfix.lastVersion"; -const PREF_EM_HOTFIX_URL = "extensions.hotfix.url"; -const PREF_EM_HOTFIX_CERTS = "extensions.hotfix.certs."; -const PREF_EM_CERT_CHECKATTRIBUTES = "extensions.hotfix.cert.checkAttributes"; - -const PREF_INSTALL_REQUIREBUILTINCERTS = "extensions.install.requireBuiltInCerts"; -const PREF_UPDATE_REQUIREBUILTINCERTS = "extensions.update.requireBuiltInCerts"; - -const PREF_APP_UPDATE_ENABLED = "app.update.enabled"; -const PREF_APP_UPDATE_URL = "app.update.url"; - -const HOTFIX_ID = "hotfix@tests.mozilla.org"; - -/* - * Register an addon install listener and return a promise that: - * resolves with the AddonInstall object if the install succeeds - * rejects with the AddonInstall if the install fails - */ -function promiseInstallListener() { - return new Promise((resolve, reject) => { - let listener = { - onInstallEnded: ai => { - AddonManager.removeInstallListener(listener); - resolve(ai); - }, - onDownloadCancelled: ai => { - AddonManager.removeInstallListener(listener); - reject(ai); - } - }; - AddonManager.addInstallListener(listener); - }); -} - -function promiseSuccessfulInstall() { - return promiseInstallListener().then( - aInstall => { - ok(true, "Should have seen the install complete"); - is(aInstall.addon.id, HOTFIX_ID, "Should have installed the right add-on"); - aInstall.addon.uninstall(); - Services.prefs.clearUserPref(PREF_EM_HOTFIX_LASTVERSION); - }, - aInstall => { - ok(false, "Should not have seen the download cancelled"); - is(aInstall.addon.id, HOTFIX_ID, "Should have seen the right add-on"); - }); -} - -function promiseFailedInstall() { - return promiseInstallListener().then( - aInstall => { - ok(false, "Should not have seen the install complete"); - is(aInstall.addon.id, HOTFIX_ID, "Should have installed the right add-on"); - aInstall.addon.uninstall(); - Services.prefs.clearUserPref(PREF_EM_HOTFIX_LASTVERSION); - }, - aInstall => { - ok(true, "Should have seen the download cancelled"); - is(aInstall.addon.id, HOTFIX_ID, "Should have seen the right add-on"); - }); -} - -add_task(function setup() { - var oldAusUrl = Services.prefs.getDefaultBranch(null).getCharPref(PREF_APP_UPDATE_URL); - Services.prefs.getDefaultBranch(null).setCharPref(PREF_APP_UPDATE_URL, TESTROOT + "ausdummy.xml"); - Services.prefs.setBoolPref(PREF_APP_UPDATE_ENABLED, true); - Services.prefs.setBoolPref(PREF_INSTALL_REQUIREBUILTINCERTS, false); - Services.prefs.setBoolPref(PREF_UPDATE_REQUIREBUILTINCERTS, false); - Services.prefs.setCharPref(PREF_EM_HOTFIX_ID, HOTFIX_ID); - var oldURL = Services.prefs.getCharPref(PREF_EM_HOTFIX_URL); - Services.prefs.setCharPref(PREF_EM_HOTFIX_URL, TESTROOT + "signed_hotfix.rdf"); - - registerCleanupFunction(function() { - Services.prefs.setBoolPref(PREF_APP_UPDATE_ENABLED, false); - Services.prefs.getDefaultBranch(null).setCharPref(PREF_APP_UPDATE_URL, oldAusUrl); - Services.prefs.clearUserPref(PREF_EM_HOTFIX_ID); - Services.prefs.setCharPref(PREF_EM_HOTFIX_URL, oldURL); - Services.prefs.clearUserPref(PREF_INSTALL_REQUIREBUILTINCERTS); - Services.prefs.clearUserPref(PREF_UPDATE_REQUIREBUILTINCERTS); - - Services.prefs.clearUserPref(PREF_EM_CERT_CHECKATTRIBUTES); - var prefs = Services.prefs.getChildList(PREF_EM_HOTFIX_CERTS); - prefs.forEach(Services.prefs.clearUserPref); - }); -}); - -add_task(function* check_no_cert_checks() { - Services.prefs.setBoolPref(PREF_EM_CERT_CHECKATTRIBUTES, false); - yield Promise.all([ - promiseSuccessfulInstall(), - AddonManagerPrivate.backgroundUpdateCheck() - ]); -}); - -add_task(function* check_wrong_cert_fingerprint() { - Services.prefs.setBoolPref(PREF_EM_CERT_CHECKATTRIBUTES, true); - Services.prefs.setCharPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint", "foo"); - - yield Promise.all([ - promiseFailedInstall(), - AddonManagerPrivate.backgroundUpdateCheck() - ]); - Services.prefs.clearUserPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint"); -}); - -add_task(function* check_right_cert_fingerprint() { - Services.prefs.setBoolPref(PREF_EM_CERT_CHECKATTRIBUTES, true); - Services.prefs.setCharPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint", "3E:B9:4E:07:12:FE:3C:01:41:46:13:46:FC:84:52:1A:8C:BE:1D:A2"); - - yield Promise.all([ - promiseSuccessfulInstall(), - AddonManagerPrivate.backgroundUpdateCheck() - ]); - - Services.prefs.clearUserPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint"); -}); - -add_task(function* check_multi_cert_fingerprint_1() { - Services.prefs.setBoolPref(PREF_EM_CERT_CHECKATTRIBUTES, true); - Services.prefs.setCharPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint", "3E:B9:4E:07:12:FE:3C:01:41:46:13:46:FC:84:52:1A:8C:BE:1D:A2"); - Services.prefs.setCharPref(PREF_EM_HOTFIX_CERTS + "2.sha1Fingerprint", "foo"); - - yield Promise.all([ - promiseSuccessfulInstall(), - AddonManagerPrivate.backgroundUpdateCheck() - ]); - - Services.prefs.clearUserPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint"); - Services.prefs.clearUserPref(PREF_EM_HOTFIX_CERTS + "2.sha1Fingerprint"); -}); - -add_task(function* check_multi_cert_fingerprint_2() { - Services.prefs.setBoolPref(PREF_EM_CERT_CHECKATTRIBUTES, true); - Services.prefs.setCharPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint", "foo"); - Services.prefs.setCharPref(PREF_EM_HOTFIX_CERTS + "2.sha1Fingerprint", "3E:B9:4E:07:12:FE:3C:01:41:46:13:46:FC:84:52:1A:8C:BE:1D:A2"); - - yield Promise.all([ - promiseSuccessfulInstall(), - AddonManagerPrivate.backgroundUpdateCheck() - ]); - - Services.prefs.clearUserPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint"); - Services.prefs.clearUserPref(PREF_EM_HOTFIX_CERTS + "2.sha1Fingerprint"); -}); - -add_task(function* check_no_cert_no_checks() { - Services.prefs.setBoolPref(PREF_EM_CERT_CHECKATTRIBUTES, false); - Services.prefs.setCharPref(PREF_EM_HOTFIX_URL, TESTROOT + "unsigned_hotfix.rdf"); - - yield Promise.all([ - promiseSuccessfulInstall(), - AddonManagerPrivate.backgroundUpdateCheck() - ]); -}); - -add_task(function* check_no_cert_cert_fingerprint_check() { - Services.prefs.setBoolPref(PREF_EM_CERT_CHECKATTRIBUTES, true); - Services.prefs.setCharPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint", "3E:B9:4E:07:12:FE:3C:01:41:46:13:46:FC:84:52:1A:8C:BE:1D:A2"); - - yield Promise.all([ - promiseFailedInstall(), - AddonManagerPrivate.backgroundUpdateCheck() - ]); - - Services.prefs.clearUserPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint"); -}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_inlinesettings.js b/toolkit/mozapps/extensions/test/browser/browser_inlinesettings.js index e2814ddf4..c1dd7f762 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_inlinesettings.js +++ b/toolkit/mozapps/extensions/test/browser/browser_inlinesettings.js @@ -3,7 +3,6 @@ */ // Tests various aspects of the details view -Components.utils.import("resource://gre/modules/Preferences.jsm"); var gManagerWindow; var gCategoryUtilities; @@ -89,14 +88,14 @@ function test() { optionsURL: CHROMEROOT + "options.xul", optionsType: AddonManager.OPTIONS_TYPE_INLINE, operationsRequiringRestart: AddonManager.OP_NEEDS_RESTART_DISABLE, - }, { + },{ id: "inlinesettings3@tests.mozilla.org", name: "Inline Settings (More Options)", description: "Tests for option types introduced after Mozilla 7.0", version: "1", optionsURL: CHROMEROOT + "more_options.xul", optionsType: AddonManager.OPTIONS_TYPE_INLINE - }, { + },{ id: "noninlinesettings@tests.mozilla.org", name: "Non-Inline Settings", version: "1", @@ -219,7 +218,7 @@ add_test(function() { ok(!settings[1].hasAttribute("first-row"), "Not the first row"); Services.prefs.setIntPref("extensions.inlinesettings1.boolint", 0); - input = gManagerWindow.document.getAnonymousElementByAttribute(settings[1], "anonid", "input"); + var input = gManagerWindow.document.getAnonymousElementByAttribute(settings[1], "anonid", "input"); isnot(input.checked, true, "Checkbox should have initial value"); EventUtils.synthesizeMouseAtCenter(input, { clickCount: 1 }, gManagerWindow); is(input.checked, true, "Checkbox should have updated value"); @@ -230,7 +229,7 @@ add_test(function() { ok(!settings[2].hasAttribute("first-row"), "Not the first row"); Services.prefs.setIntPref("extensions.inlinesettings1.integer", 0); - input = gManagerWindow.document.getAnonymousElementByAttribute(settings[2], "anonid", "input"); + var input = gManagerWindow.document.getAnonymousElementByAttribute(settings[2], "anonid", "input"); is(input.value, "0", "Number box should have initial value"); input.select(); EventUtils.synthesizeKey("1", {}, gManagerWindow); @@ -243,21 +242,20 @@ add_test(function() { ok(!settings[3].hasAttribute("first-row"), "Not the first row"); Services.prefs.setCharPref("extensions.inlinesettings1.string", "foo"); - input = gManagerWindow.document.getAnonymousElementByAttribute(settings[3], "anonid", "input"); + var input = gManagerWindow.document.getAnonymousElementByAttribute(settings[3], "anonid", "input"); is(input.value, "foo", "Text box should have initial value"); input.select(); EventUtils.synthesizeKey("b", {}, gManagerWindow); EventUtils.synthesizeKey("a", {}, gManagerWindow); EventUtils.synthesizeKey("r", {}, gManagerWindow); is(input.value, "bar", "Text box should have updated value"); - input.value += "\u03DE"; // Cheat to add this non-ASCII character without typing it. EventUtils.synthesizeKey("/", {}, gManagerWindow); - is(input.value, "bar\u03DE/", "Text box should have updated value"); + is(input.value, "bar/", "Text box should have updated value"); is(gManagerWindow.document.getBindingParent(gManagerWindow.document.activeElement), input, "Search box should not have focus"); - is(Preferences.get("extensions.inlinesettings1.string", "wrong"), "bar\u03DE/", "String pref should have been updated"); + is(Services.prefs.getCharPref("extensions.inlinesettings1.string"), "bar/", "String pref should have been updated"); ok(!settings[4].hasAttribute("first-row"), "Not the first row"); - input = settings[4].firstElementChild; + var input = settings[4].firstElementChild; is(input.value, "1", "Menulist should have initial value"); input.focus(); EventUtils.synthesizeKey("b", {}, gManagerWindow); @@ -284,25 +282,24 @@ add_test(function() { is(input.value, "", "Label value should be empty"); is(input.tooltipText, "", "Label tooltip should be empty"); - var testFile = Services.dirsvc.get("ProfD", Ci.nsIFile); - testFile.append("\u2622"); + var profD = Services.dirsvc.get("ProfD", Ci.nsIFile); var curProcD = Services.dirsvc.get("CurProcD", Ci.nsIFile); - MockFilePicker.returnFiles = [testFile]; + MockFilePicker.returnFiles = [profD]; MockFilePicker.returnValue = Ci.nsIFilePicker.returnOK; EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); is(MockFilePicker.mode, Ci.nsIFilePicker.modeOpen, "File picker mode should be open file"); - is(input.value, testFile.path, "Label value should match file chosen"); - is(input.tooltipText, testFile.path, "Label tooltip should match file chosen"); - is(Preferences.get("extensions.inlinesettings1.file", "wrong"), testFile.path, "File pref should match file chosen"); + is(input.value, profD.path, "Label value should match file chosen"); + is(input.tooltipText, profD.path, "Label tooltip should match file chosen"); + is(Services.prefs.getCharPref("extensions.inlinesettings1.file"), profD.path, "File pref should match file chosen"); MockFilePicker.returnFiles = [curProcD]; MockFilePicker.returnValue = Ci.nsIFilePicker.returnCancel; EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); is(MockFilePicker.mode, Ci.nsIFilePicker.modeOpen, "File picker mode should be open file"); - is(input.value, testFile.path, "Label value should not have changed"); - is(input.tooltipText, testFile.path, "Label tooltip should not have changed"); - is(Preferences.get("extensions.inlinesettings1.file", "wrong"), testFile.path, "File pref should not have changed"); + is(input.value, profD.path, "Label value should not have changed"); + is(input.tooltipText, profD.path, "Label tooltip should not have changed"); + is(Services.prefs.getCharPref("extensions.inlinesettings1.file"), profD.path, "File pref should not have changed"); ok(!settings[7].hasAttribute("first-row"), "Not the first row"); button = gManagerWindow.document.getAnonymousElementByAttribute(settings[7], "anonid", "button"); @@ -310,21 +307,21 @@ add_test(function() { is(input.value, "", "Label value should be empty"); is(input.tooltipText, "", "Label tooltip should be empty"); - MockFilePicker.returnFiles = [testFile]; + MockFilePicker.returnFiles = [profD]; MockFilePicker.returnValue = Ci.nsIFilePicker.returnOK; EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); is(MockFilePicker.mode, Ci.nsIFilePicker.modeGetFolder, "File picker mode should be directory"); - is(input.value, testFile.path, "Label value should match file chosen"); - is(input.tooltipText, testFile.path, "Label tooltip should match file chosen"); - is(Preferences.get("extensions.inlinesettings1.directory", "wrong"), testFile.path, "Directory pref should match file chosen"); + is(input.value, profD.path, "Label value should match file chosen"); + is(input.tooltipText, profD.path, "Label tooltip should match file chosen"); + is(Services.prefs.getCharPref("extensions.inlinesettings1.directory"), profD.path, "Directory pref should match file chosen"); MockFilePicker.returnFiles = [curProcD]; MockFilePicker.returnValue = Ci.nsIFilePicker.returnCancel; EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); is(MockFilePicker.mode, Ci.nsIFilePicker.modeGetFolder, "File picker mode should be directory"); - is(input.value, testFile.path, "Label value should not have changed"); - is(input.tooltipText, testFile.path, "Label tooltip should not have changed"); - is(Preferences.get("extensions.inlinesettings1.directory", "wrong"), testFile.path, "Directory pref should not have changed"); + is(input.value, profD.path, "Label value should not have changed"); + is(input.tooltipText, profD.path, "Label tooltip should not have changed"); + is(Services.prefs.getCharPref("extensions.inlinesettings1.directory"), profD.path, "Directory pref should not have changed"); var unsizedInput = gManagerWindow.document.getAnonymousElementByAttribute(settings[2], "anonid", "input"); var sizedInput = gManagerWindow.document.getAnonymousElementByAttribute(settings[8], "anonid", "input"); @@ -367,7 +364,7 @@ add_test(function() { ok(!settings[1].hasAttribute("first-row"), "Not the first row"); Services.prefs.setIntPref("extensions.inlinesettings3.radioInt", 5); - radios = settings[1].getElementsByTagName("radio"); + var radios = settings[1].getElementsByTagName("radio"); isnot(radios[0].selected, true, "Correct radio button should be selected"); is(radios[1].selected, true, "Correct radio button should be selected"); isnot(radios[2].selected, true, "Correct radio button should be selected"); @@ -378,14 +375,14 @@ add_test(function() { ok(!settings[2].hasAttribute("first-row"), "Not the first row"); Services.prefs.setCharPref("extensions.inlinesettings3.radioString", "juliet"); - radios = settings[2].getElementsByTagName("radio"); + var radios = settings[2].getElementsByTagName("radio"); isnot(radios[0].selected, true, "Correct radio button should be selected"); is(radios[1].selected, true, "Correct radio button should be selected"); isnot(radios[2].selected, true, "Correct radio button should be selected"); EventUtils.synthesizeMouseAtCenter(radios[0], { clickCount: 1 }, gManagerWindow); - is(Preferences.get("extensions.inlinesettings3.radioString", "wrong"), "india", "Radio pref should have been updated"); + is(Services.prefs.getCharPref("extensions.inlinesettings3.radioString"), "india", "Radio pref should have been updated"); EventUtils.synthesizeMouseAtCenter(radios[2], { clickCount: 1 }, gManagerWindow); - is(Preferences.get("extensions.inlinesettings3.radioString", "wrong"), "kilo \u338F", "Radio pref should have been updated"); + is(Services.prefs.getCharPref("extensions.inlinesettings3.radioString"), "kilo", "Radio pref should have been updated"); ok(!settings[3].hasAttribute("first-row"), "Not the first row"); Services.prefs.setIntPref("extensions.inlinesettings3.menulist", 8); @@ -449,7 +446,7 @@ add_test(function() { is_element_hidden(node, "Unsupported settings should not be visible"); ok(!node.hasAttribute("first-row"), "Hidden row is not the first row"); - button = gManagerWindow.document.getElementById("detail-prefs-btn"); + var button = gManagerWindow.document.getElementById("detail-prefs-btn"); is_element_hidden(button, "Preferences button should not be visible"); gCategoryUtilities.openType("extension", run_next_test); @@ -503,7 +500,7 @@ add_test(function() { // disable var button = gManagerWindow.document.getElementById("detail-disable-btn"); - button.scrollIntoView(); + button.focus(); // make sure it's in view EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); observer.checkHidden("inlinesettings1@tests.mozilla.org"); @@ -564,7 +561,7 @@ add_test(function() { // disable var button = gManagerWindow.document.getElementById("detail-disable-btn"); - button.scrollIntoView(); + button.focus(); // make sure it's in view EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); observer.checkNotHidden(); @@ -573,7 +570,7 @@ add_test(function() { // cancel pending disable button = gManagerWindow.document.getElementById("detail-enable-btn"); - button.scrollIntoView(); + button.focus(); // make sure it's in view EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); observer.checkNotDisplayed(); @@ -591,7 +588,7 @@ add_test(function() { Services.prefs.setBoolPref("extensions.inlinesettings1.bool", false); Services.prefs.setIntPref("extensions.inlinesettings1.boolint", 1); Services.prefs.setIntPref("extensions.inlinesettings1.integer", 12); - Preferences.set("extensions.inlinesettings1.string", "bar\u03DE/"); + Services.prefs.setCharPref("extensions.inlinesettings1.string", "bar/"); Services.prefs.setCharPref("extensions.inlinesettings1.color", "#FF9900"); Services.prefs.setCharPref("extensions.inlinesettings1.file", profD.path); Services.prefs.setCharPref("extensions.inlinesettings1.directory", profD.path); @@ -611,14 +608,14 @@ add_test(function() { var input = gManagerWindow.document.getAnonymousElementByAttribute(settings[0], "anonid", "input"); is(input.checked, false, "Checkbox should have initial value"); - input = gManagerWindow.document.getAnonymousElementByAttribute(settings[1], "anonid", "input"); + var input = gManagerWindow.document.getAnonymousElementByAttribute(settings[1], "anonid", "input"); is(input.checked, true, "Checkbox should have initial value"); - input = gManagerWindow.document.getAnonymousElementByAttribute(settings[2], "anonid", "input"); + var input = gManagerWindow.document.getAnonymousElementByAttribute(settings[2], "anonid", "input"); is(input.value, "12", "Number box should have initial value"); - input = gManagerWindow.document.getAnonymousElementByAttribute(settings[3], "anonid", "input"); - is(input.value, "bar\u03DE/", "Text box should have initial value"); + var input = gManagerWindow.document.getAnonymousElementByAttribute(settings[3], "anonid", "input"); + is(input.value, "bar/", "Text box should have initial value"); input = gManagerWindow.document.getAnonymousElementByAttribute(settings[5], "anonid", "input"); is(input.color, "#FF9900", "Color picker should have initial value"); @@ -643,7 +640,7 @@ add_test(function() { // change the tests above. Services.prefs.setBoolPref("extensions.inlinesettings3.radioBool", false); Services.prefs.setIntPref("extensions.inlinesettings3.radioInt", 6); - Preferences.set("extensions.inlinesettings3.radioString", "kilo \u338F"); + Services.prefs.setCharPref("extensions.inlinesettings3.radioString", "kilo"); Services.prefs.setIntPref("extensions.inlinesettings3.menulist", 9); var addon = get_addon_element(gManagerWindow, "inlinesettings3@tests.mozilla.org"); @@ -662,12 +659,12 @@ add_test(function() { isnot(radios[0].selected, true, "Correct radio button should be selected"); is(radios[1].selected, true, "Correct radio button should be selected"); - radios = settings[1].getElementsByTagName("radio"); + var radios = settings[1].getElementsByTagName("radio"); isnot(radios[0].selected, true, "Correct radio button should be selected"); isnot(radios[1].selected, true, "Correct radio button should be selected"); is(radios[2].selected, true, "Correct radio button should be selected"); - radios = settings[2].getElementsByTagName("radio"); + var radios = settings[2].getElementsByTagName("radio"); isnot(radios[0].selected, true, "Correct radio button should be selected"); isnot(radios[1].selected, true, "Correct radio button should be selected"); is(radios[2].selected, true, "Correct radio button should be selected"); diff --git a/toolkit/mozapps/extensions/test/browser/browser_inlinesettings_browser.js b/toolkit/mozapps/extensions/test/browser/browser_inlinesettings_browser.js deleted file mode 100644 index 5a704530a..000000000 --- a/toolkit/mozapps/extensions/test/browser/browser_inlinesettings_browser.js +++ /dev/null @@ -1,207 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -/* globals TestUtils */ - -var {Extension} = Components.utils.import("resource://gre/modules/Extension.jsm", {}); - -var gAddon; -var gOtherAddon; -var gManagerWindow; -var gCategoryUtilities; - -var installedAddons = []; - -function installAddon(details) { - let id = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator) - .generateUUID().number; - if (!details.manifest) { - details.manifest = {}; - } - details.manifest.applications = {gecko: {id}}; - let xpi = Extension.generateXPI(details); - - return AddonManager.installTemporaryAddon(xpi).then(addon => { - SimpleTest.registerCleanupFunction(function() { - addon.uninstall(); - - Services.obs.notifyObservers(xpi, "flush-cache-entry", null); - xpi.remove(false); - }); - - return addon; - }); -} - -add_task(function*() { - gAddon = yield installAddon({ - manifest: { - "options_ui": { - "page": "options.html", - } - }, - - files: { - "options.html": `<!DOCTYPE html> - <html> - <head> - <meta charset="UTF-8"> - <style type="text/css"> - body > p { - height: 300px; - margin: 0; - } - body.bigger > p { - height: 600px; - } - </style> - </head> - <body> - <p>The quick mauve fox jumps over the opalescent dog.</p> - </body> - </html>`, - }, - }); - - // Create another add-on with no inline options, to verify that detail - // view switches work correctly. - gOtherAddon = yield installAddon({}); - - gManagerWindow = yield open_manager("addons://list/extension"); - gCategoryUtilities = new CategoryUtilities(gManagerWindow); -}); - - -function* openDetailsBrowser(addonId) { - var addon = get_addon_element(gManagerWindow, addonId); - - is(addon.mAddon.optionsType, AddonManager.OPTIONS_TYPE_INLINE_BROWSER, - "Options should be inline browser type"); - - addon.parentNode.ensureElementIsVisible(addon); - - var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "preferences-btn"); - - is_element_visible(button, "Preferences button should be visible"); - - EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); - - yield TestUtils.topicObserved(AddonManager.OPTIONS_NOTIFICATION_DISPLAYED, - (subject, data) => data == addonId); - - is(gManagerWindow.gViewController.currentViewId, - `addons://detail/${encodeURIComponent(addonId)}/preferences`, - "Current view should scroll to preferences"); - - var browser = gManagerWindow.document.querySelector( - "#detail-grid > rows > .inline-options-browser"); - var rows = browser.parentNode; - - ok(browser, "Grid should have a browser child"); - is(browser.localName, "browser", "Grid should have a browser child"); - is(browser.currentURI.spec, addon.mAddon.optionsURL, "Browser has the expected options URL loaded") - - is(browser.clientWidth, rows.clientWidth, - "Browser should be the same width as its parent node"); - - button = gManagerWindow.document.getElementById("detail-prefs-btn"); - is_element_hidden(button, "Preferences button should not be visible"); - - return browser; -} - - -add_task(function* test_inline_browser_addon() { - let browser = yield openDetailsBrowser(gAddon.id); - - let body = browser.contentDocument.body; - - function checkHeights(expected) { - is(body.clientHeight, expected, `Document body should be ${expected}px tall`); - is(body.clientHeight, body.scrollHeight, - "Document body should be tall enough to fit its contents"); - - let heightDiff = browser.clientHeight - expected; - ok(heightDiff >= 0 && heightDiff < 50, - "Browser should be slightly taller than the document body"); - } - - // Delay long enough to avoid hitting our resize rate limit. - let delay = () => new Promise(resolve => setTimeout(resolve, 300)); - - checkHeights(300); - - info("Increase the document height, and expect the browser to grow correspondingly"); - body.classList.toggle("bigger"); - - yield delay(); - - checkHeights(600); - - info("Decrease the document height, and expect the browser to shrink correspondingly"); - body.classList.toggle("bigger"); - - yield delay(); - - checkHeights(300); - - yield new Promise(resolve => - gCategoryUtilities.openType("extension", resolve)); - - browser = gManagerWindow.document.querySelector( - ".inline-options-browser"); - - is(browser, null, "Options browser should be removed from the document"); -}); - - -// Test that loading an add-on with no inline browser works as expected -// after having viewed our main test add-on. -add_task(function* test_plain_addon() { - var addon = get_addon_element(gManagerWindow, gOtherAddon.id); - - is(addon.mAddon.optionsType, null, "Add-on should have no options"); - - addon.parentNode.ensureElementIsVisible(addon); - - yield EventUtils.synthesizeMouseAtCenter(addon, { clickCount: 1 }, gManagerWindow); - - EventUtils.synthesizeMouseAtCenter(addon, { clickCount: 2 }, gManagerWindow); - - yield BrowserTestUtils.waitForEvent(gManagerWindow, "ViewChanged"); - - is(gManagerWindow.gViewController.currentViewId, - `addons://detail/${encodeURIComponent(gOtherAddon.id)}`, - "Detail view should be open"); - - var browser = gManagerWindow.document.querySelector( - "#detail-grid > rows > .inline-options-browser"); - - is(browser, null, "Detail view should have no inline browser"); - - yield new Promise(resolve => - gCategoryUtilities.openType("extension", resolve)); -}); - - -// Test that loading the original add-on details successfully creates a -// browser. -add_task(function* test_inline_browser_addon_again() { - let browser = yield openDetailsBrowser(gAddon.id); - - yield new Promise(resolve => - gCategoryUtilities.openType("extension", resolve)); - - browser = gManagerWindow.document.querySelector( - ".inline-options-browser"); - - is(browser, null, "Options browser should be removed from the document"); -}); - -add_task(function*() { - yield close_manager(gManagerWindow); - - gManagerWindow = null; - gCategoryUtilities = null; -}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_inlinesettings_info.js b/toolkit/mozapps/extensions/test/browser/browser_inlinesettings_info.js index ce618b7fa..05b43a238 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_inlinesettings_info.js +++ b/toolkit/mozapps/extensions/test/browser/browser_inlinesettings_info.js @@ -3,7 +3,6 @@ */ // Tests various aspects of the details view -Components.utils.import("resource://gre/modules/Preferences.jsm"); var gManagerWindow; var gCategoryUtilities; @@ -89,14 +88,14 @@ function test() { optionsURL: CHROMEROOT + "options.xul", optionsType: AddonManager.OPTIONS_TYPE_INLINE_INFO, operationsRequiringRestart: AddonManager.OP_NEEDS_RESTART_DISABLE, - }, { + },{ id: "inlinesettings3@tests.mozilla.org", name: "Inline Settings (More Options)", description: "Tests for option types introduced after Mozilla 7.0", version: "1", optionsURL: CHROMEROOT + "more_options.xul", optionsType: AddonManager.OPTIONS_TYPE_INLINE_INFO - }, { + },{ id: "noninlinesettings@tests.mozilla.org", name: "Non-Inline Settings", version: "1", @@ -215,7 +214,7 @@ add_test(function() { ok(!settings[1].hasAttribute("first-row"), "Not the first row"); Services.prefs.setIntPref("extensions.inlinesettings1.boolint", 0); - input = gManagerWindow.document.getAnonymousElementByAttribute(settings[1], "anonid", "input"); + var input = gManagerWindow.document.getAnonymousElementByAttribute(settings[1], "anonid", "input"); isnot(input.checked, true, "Checkbox should have initial value"); EventUtils.synthesizeMouseAtCenter(input, { clickCount: 1 }, gManagerWindow); is(input.checked, true, "Checkbox should have updated value"); @@ -226,7 +225,7 @@ add_test(function() { ok(!settings[2].hasAttribute("first-row"), "Not the first row"); Services.prefs.setIntPref("extensions.inlinesettings1.integer", 0); - input = gManagerWindow.document.getAnonymousElementByAttribute(settings[2], "anonid", "input"); + var input = gManagerWindow.document.getAnonymousElementByAttribute(settings[2], "anonid", "input"); is(input.value, "0", "Number box should have initial value"); input.select(); EventUtils.synthesizeKey("1", {}, gManagerWindow); @@ -239,7 +238,7 @@ add_test(function() { ok(!settings[3].hasAttribute("first-row"), "Not the first row"); Services.prefs.setCharPref("extensions.inlinesettings1.string", "foo"); - input = gManagerWindow.document.getAnonymousElementByAttribute(settings[3], "anonid", "input"); + var input = gManagerWindow.document.getAnonymousElementByAttribute(settings[3], "anonid", "input"); is(input.value, "foo", "Text box should have initial value"); input.select(); EventUtils.synthesizeKey("b", {}, gManagerWindow); @@ -249,7 +248,7 @@ add_test(function() { is(Services.prefs.getCharPref("extensions.inlinesettings1.string"), "bar", "String pref should have been updated"); ok(!settings[4].hasAttribute("first-row"), "Not the first row"); - input = settings[4].firstElementChild; + var input = settings[4].firstElementChild; is(input.value, "1", "Menulist should have initial value"); input.focus(); EventUtils.synthesizeKey("b", {}, gManagerWindow); @@ -272,10 +271,6 @@ add_test(function() { try { ok(!settings[6].hasAttribute("first-row"), "Not the first row"); var button = gManagerWindow.document.getAnonymousElementByAttribute(settings[6], "anonid", "button"); - - // Workaround for bug 1155324 - we need to ensure that the button is scrolled into view. - button.scrollIntoView(); - input = gManagerWindow.document.getAnonymousElementByAttribute(settings[6], "anonid", "input"); is(input.value, "", "Label value should be empty"); is(input.tooltipText, "", "Label tooltip should be empty"); @@ -359,7 +354,7 @@ add_test(function() { ok(!settings[1].hasAttribute("first-row"), "Not the first row"); Services.prefs.setIntPref("extensions.inlinesettings3.radioInt", 5); - radios = settings[1].getElementsByTagName("radio"); + var radios = settings[1].getElementsByTagName("radio"); isnot(radios[0].selected, true, "Correct radio button should be selected"); is(radios[1].selected, true, "Correct radio button should be selected"); isnot(radios[2].selected, true, "Correct radio button should be selected"); @@ -370,14 +365,14 @@ add_test(function() { ok(!settings[2].hasAttribute("first-row"), "Not the first row"); Services.prefs.setCharPref("extensions.inlinesettings3.radioString", "juliet"); - radios = settings[2].getElementsByTagName("radio"); + var radios = settings[2].getElementsByTagName("radio"); isnot(radios[0].selected, true, "Correct radio button should be selected"); is(radios[1].selected, true, "Correct radio button should be selected"); isnot(radios[2].selected, true, "Correct radio button should be selected"); EventUtils.synthesizeMouseAtCenter(radios[0], { clickCount: 1 }, gManagerWindow); is(Services.prefs.getCharPref("extensions.inlinesettings3.radioString"), "india", "Radio pref should have been updated"); EventUtils.synthesizeMouseAtCenter(radios[2], { clickCount: 1 }, gManagerWindow); - is(Preferences.get("extensions.inlinesettings3.radioString", "wrong"), "kilo \u338F", "Radio pref should have been updated"); + is(Services.prefs.getCharPref("extensions.inlinesettings3.radioString"), "kilo", "Radio pref should have been updated"); ok(!settings[3].hasAttribute("first-row"), "Not the first row"); Services.prefs.setIntPref("extensions.inlinesettings3.menulist", 8); @@ -441,7 +436,7 @@ add_test(function() { is_element_hidden(node, "Unsupported settings should not be visible"); ok(!node.hasAttribute("first-row"), "Hidden row is not the first row"); - button = gManagerWindow.document.getElementById("detail-prefs-btn"); + var button = gManagerWindow.document.getElementById("detail-prefs-btn"); is_element_hidden(button, "Preferences button should not be visible"); gCategoryUtilities.openType("extension", run_next_test); diff --git a/toolkit/mozapps/extensions/test/browser/browser_install.js b/toolkit/mozapps/extensions/test/browser/browser_install.js index 880a4624d..3f7d17d37 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_install.js +++ b/toolkit/mozapps/extensions/test/browser/browser_install.js @@ -31,7 +31,7 @@ function end_test() { close_manager(gManagerWindow, function() { Services.prefs.clearUserPref("extensions.checkUpdateSecurity"); - AddonManager.getAddonByID("install1@tests.mozilla.org", function(aAddon) { + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) { aAddon.uninstall(); finish(); }); @@ -55,7 +55,7 @@ function installAddon(aCallback) { } function installUpgrade(aCallback) { - AddonManager.getAddonByID("install1@tests.mozilla.org", function(aAddon) { + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) { aAddon.findUpdates({ onUpdateAvailable: function(aAddon, aInstall) { is(get_list_item_count(), 1, "Should be only one item in the list"); @@ -103,7 +103,7 @@ function installSearchResult(aCallback) { let remote = gManagerWindow.document.getElementById("search-filter-remote") EventUtils.synthesizeMouseAtCenter(remote, { }, gManagerWindow); - let item = get_addon_element(gManagerWindow, "install1@tests.mozilla.org"); + let item = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); ok(!!item, "Should see the search result in the list"); let status = get_node(item, "install-status"); @@ -124,7 +124,7 @@ function get_list_item_count() { function check_undo_install() { is(get_list_item_count(), 1, "Should be only one item in the list"); - let item = get_addon_element(gManagerWindow, "install1@tests.mozilla.org"); + let item = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); ok(!!item, "Should see the pending install in the list"); // Force XBL to apply item.clientTop; @@ -135,14 +135,14 @@ function check_undo_install() { is(get_list_item_count(), 0, "Should be no items in the list"); - item = get_addon_element(gManagerWindow, "install1@tests.mozilla.org"); + item = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); ok(!item, "Should no longer see the pending install"); } function check_undo_upgrade() { is(get_list_item_count(), 1, "Should be only one item in the list"); - let item = get_addon_element(gManagerWindow, "install1@tests.mozilla.org"); + let item = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); ok(!!item, "Should see the pending upgrade in the list"); // Force XBL to apply item.clientTop; @@ -153,7 +153,7 @@ function check_undo_upgrade() { is(get_list_item_count(), 1, "Should be only one item in the list"); - item = get_addon_element(gManagerWindow, "install1@tests.mozilla.org"); + item = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); ok(!!item, "Should still see installed item in the list"); is_element_hidden(get_node(item, "pending"), "Pending message should be hidden"); } @@ -285,7 +285,7 @@ add_test(function() { add_test(function() { cancelInstall(function() { is(get_list_item_count(), 1, "Should be no items in the list"); - let item = get_addon_element(gManagerWindow, "install1@tests.mozilla.org"); + let item = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); ok(!!item, "Should still see installed item in the list"); is_element_hidden(get_node(item, "pending"), "Pending message should be hidden"); @@ -301,7 +301,7 @@ add_test(function() { gManagerWindow = aWindow; gCategoryUtilities = new CategoryUtilities(gManagerWindow); is(get_list_item_count(), 1, "Should be no items in the list"); - let item = get_addon_element(gManagerWindow, "install1@tests.mozilla.org"); + let item = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); ok(!!item, "Should still see installed item in the list"); is_element_hidden(get_node(item, "pending"), "Pending message should be hidden"); diff --git a/toolkit/mozapps/extensions/test/browser/browser_install.rdf b/toolkit/mozapps/extensions/test/browser/browser_install.rdf index 437bf9b85..7dc0477f0 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_install.rdf +++ b/toolkit/mozapps/extensions/test/browser/browser_install.rdf @@ -3,7 +3,7 @@ <RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#"> - <Description about="urn:mozilla:extension:install1@tests.mozilla.org"> + <Description about="urn:mozilla:extension:addon1@tests.mozilla.org"> <em:updates> <Seq> <li> @@ -15,7 +15,7 @@ <em:minVersion>0</em:minVersion> <em:maxVersion>*</em:maxVersion> <em:updateLink>https://example.com/browser/toolkit/mozapps/extensions/test/browser/browser_install1_3.xpi</em:updateLink> - <em:updateHash>sha1:4f0f4391914e3e036beca50cbac33958e5269643</em:updateHash> + <em:updateHash>sha1:6760e51269941245105a17076afeb5f45621de0e</em:updateHash> </Description> </em:targetApplication> </Description> diff --git a/toolkit/mozapps/extensions/test/browser/browser_install.xml b/toolkit/mozapps/extensions/test/browser/browser_install.xml index 0643c811a..84067a6a3 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_install.xml +++ b/toolkit/mozapps/extensions/test/browser/browser_install.xml @@ -3,7 +3,7 @@ <addon> <name>Install Tests</name> <type id='1'>Extension</type> - <guid>install1@tests.mozilla.org</guid> + <guid>addon1@tests.mozilla.org</guid> <version>1.0</version> <authors> <author> @@ -17,7 +17,7 @@ <compatible_applications> <application> <name>Firefox</name> - <appID>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</appID> + <appID>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</appID> <min_version>0</min_version> <max_version>*</max_version> </application> diff --git a/toolkit/mozapps/extensions/test/browser/browser_install1_3.xpi b/toolkit/mozapps/extensions/test/browser/browser_install1_3.xpi Binary files differindex de3c90353..31bb4b2a6 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_install1_3.xpi +++ b/toolkit/mozapps/extensions/test/browser/browser_install1_3.xpi diff --git a/toolkit/mozapps/extensions/test/browser/browser_list.js b/toolkit/mozapps/extensions/test/browser/browser_list.js index 49427329f..fd6cfed7e 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_list.js +++ b/toolkit/mozapps/extensions/test/browser/browser_list.js @@ -4,10 +4,10 @@ // Tests the list view -var tempScope = {}; +let tempScope = {}; Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm", tempScope); -var LightweightThemeManager = tempScope.LightweightThemeManager; -const { REQUIRE_SIGNING } = Components.utils.import("resource://gre/modules/addons/AddonConstants.jsm", {}); +let LightweightThemeManager = tempScope.LightweightThemeManager; + var gProvider; var gManagerWindow; @@ -16,10 +16,8 @@ var gCategoryUtilities; var gApp = document.getElementById("bundle_brand").getString("brandShortName"); var gVersion = Services.appinfo.version; var gBlocklistURL = Services.urlFormatter.formatURLPref("extensions.blocklist.detailsURL"); +var gPluginURL = Services.urlFormatter.formatURLPref("plugins.update.url"); var gDate = new Date(2010, 7, 16); -var infoURL = Services.urlFormatter.formatURLPref("app.support.baseURL") + "unsigned-addons"; - -const EXPECTED_ADDONS = 13; var gLWTheme = { id: "4", @@ -34,7 +32,10 @@ var gLWTheme = { iconURL: "http://mochi.test:8888/data/icon.png" }; -add_task(function*() { + +function test() { + waitForExplicitFinish(); + gProvider = new MockProvider(); gProvider.createAddons([{ @@ -95,36 +96,20 @@ add_task(function*() { blocklistURL: "http://example.com/addon9@tests.mozilla.org", name: "Test add-on 9", blocklistState: Ci.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE, - }, { - id: "addon10@tests.mozilla.org", - name: "Test add-on 10", - signedState: AddonManager.SIGNEDSTATE_MISSING, - }, { - id: "addon11@tests.mozilla.org", - name: "Test add-on 11", - signedState: AddonManager.SIGNEDSTATE_MISSING, - isActive: false, - isCompatible: false, - appDisabled: true, - }, { - id: "addon12@tests.mozilla.org", - name: "Test add-on 12", - signedState: AddonManager.SIGNEDSTATE_PRELIMINARY, - foreignInstall: true, - }, { - id: "addon13@tests.mozilla.org", - name: "Test add-on 13", - signedState: AddonManager.SIGNEDSTATE_SIGNED, - foreignInstall: true, - }, { - id: "addon15@tests.mozilla.org", - name: "Test add-on 15", - hidden: true, }]); - gManagerWindow = yield open_manager(null); - gCategoryUtilities = new CategoryUtilities(gManagerWindow); -}); + open_manager(null, function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + run_next_test(); + }); +} + +function end_test() { + close_manager(gManagerWindow, function() { + finish(); + }); +} function get_test_items() { var tests = "@tests.mozilla.org"; @@ -133,8 +118,7 @@ function get_test_items() { var item = gManagerWindow.document.getElementById("addon-list").firstChild; while (item) { - if (item.mAddon.id.substring(item.mAddon.id.length - tests.length) == tests && - !is_hidden(item)) + if (item.mAddon.id.substring(item.mAddon.id.length - tests.length) == tests) items[item.mAddon.name] = item; item = item.nextSibling; } @@ -152,538 +136,476 @@ function get_class_node(parent, cls) { // Check that the list appears to have displayed correctly and trigger some // changes -add_task(function*() { - yield gCategoryUtilities.openType("extension"); - let items = get_test_items(); - is(Object.keys(items).length, EXPECTED_ADDONS, "Should be the right number of add-ons installed"); - - info("Addon 1"); - let addon = items["Test add-on"]; - addon.parentNode.ensureElementIsVisible(addon); - let { name, version } = yield get_tooltip_info(addon); - is(get_node(addon, "name").value, "Test add-on", "Name should be correct"); - is(name, "Test add-on", "Tooltip name should be correct"); - is(version, "1.0", "Tooltip version should be correct"); - is(get_node(addon, "description").value, "A test add-on", "Description should be correct"); - is_element_hidden(get_class_node(addon, "disabled-postfix"), "Disabled postfix should be hidden"); - is_element_hidden(get_class_node(addon, "update-postfix"), "Update postfix should be hidden"); - is(get_node(addon, "date-updated").value, formatDate(gDate), "Update date should be correct"); - - is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); - is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); - is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); - is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); - - is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); - is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); - is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); - is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); - is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); - - info("Disabling"); - EventUtils.synthesizeMouseAtCenter(get_node(addon, "disable-btn"), {}, gManagerWindow); - is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); - is_element_visible(get_node(addon, "enable-btn"), "Enable button should be visible"); - is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden"); - is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); - - is_element_hidden(get_node(addon, "warning"), "Warning message should be visible"); - is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); - is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); - is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); - is_element_visible(get_node(addon, "pending"), "Pending message should be visible"); - is(get_node(addon, "pending").textContent, "Test add-on will be disabled after you restart " + gApp + ".", "Pending message should be correct"); - - info("Addon 2"); - addon = items["Test add-on 2"]; - addon.parentNode.ensureElementIsVisible(addon); - ({ name, version } = yield get_tooltip_info(addon)); - is(get_node(addon, "name").value, "Test add-on 2", "Name should be correct"); - is(name, "Test add-on 2", "Tooltip name should be correct"); - is(version, "2.0", "Tooltip version should be correct"); - is_element_hidden(get_node(addon, "description"), "Description should be hidden"); - is_element_visible(get_class_node(addon, "disabled-postfix"), "Disabled postfix should be visible"); - is_element_hidden(get_class_node(addon, "update-postfix"), "Update postfix should be hidden"); - is(get_node(addon, "date-updated").value, "Unknown", "Date should be correct"); +add_test(function() { + gCategoryUtilities.openType("extension", function() { + let items = get_test_items(); + is(Object.keys(items).length, 9, "Should be nine add-ons installed"); - is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); - is_element_visible(get_node(addon, "enable-btn"), "Enable button should be visible"); - is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden"); - is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + info("Addon 1"); + let addon = items["Test add-on"]; + addon.parentNode.ensureElementIsVisible(addon); + is(get_node(addon, "name").value, "Test add-on", "Name should be correct"); + is_element_visible(get_node(addon, "version"), "Version should be visible"); + is(get_node(addon, "version").value, "1.0", "Version should be correct"); + is_element_visible(get_node(addon, "description"), "Description should be visible"); + is(get_node(addon, "description").value, "A test add-on", "Description should be correct"); + is_element_hidden(get_class_node(addon, "disabled-postfix"), "Disabled postfix should be hidden"); + is_element_hidden(get_class_node(addon, "update-postfix"), "Update postfix should be hidden"); + is(get_node(addon, "date-updated").value, formatDate(gDate), "Update date should be correct"); - is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); - is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); - is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); - is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); - is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); + is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); - info("Enabling"); - EventUtils.synthesizeMouseAtCenter(get_node(addon, "enable-btn"), {}, gManagerWindow); - is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); - is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); - is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); - is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); - is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); - is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); - is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); - is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); - is_element_visible(get_node(addon, "pending"), "Pending message should be visible"); - is(get_node(addon, "pending").textContent, "Test add-on 2 will be enabled after you restart " + gApp + ".", "Pending message should be correct"); + info("Disabling"); + EventUtils.synthesizeMouseAtCenter(get_node(addon, "disable-btn"), {}, gManagerWindow); + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_visible(get_node(addon, "enable-btn"), "Enable button should be visible"); + is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); - info("Addon 3"); - addon = items["Test add-on 3"]; - addon.parentNode.ensureElementIsVisible(addon); - ({ name, version } = yield get_tooltip_info(addon)); - is(get_node(addon, "name").value, "Test add-on 3", "Name should be correct"); - is(name, "Test add-on 3", "Tooltip name should be correct"); - is(version, undefined, "Tooltip version should be hidden"); + is_element_hidden(get_node(addon, "warning"), "Warning message should be visible"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_visible(get_node(addon, "pending"), "Pending message should be visible"); + is(get_node(addon, "pending").textContent, "Test add-on will be disabled after you restart " + gApp + ".", "Pending message should be correct"); - is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); - is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); - is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden"); - is_element_hidden(get_node(addon, "remove-btn"), "Remove button should be hidden"); + info("Addon 2"); + addon = items["Test add-on 2"]; + addon.parentNode.ensureElementIsVisible(addon); + is(get_node(addon, "name").value, "Test add-on 2", "Name should be correct"); + is_element_visible(get_node(addon, "version"), "Version should be visible"); + is(get_node(addon, "version").value, "2.0", "Version should be correct"); + is_element_hidden(get_node(addon, "description"), "Description should be hidden"); + is_element_visible(get_class_node(addon, "disabled-postfix"), "Disabled postfix should be visible"); + is_element_hidden(get_class_node(addon, "update-postfix"), "Update postfix should be hidden"); + is(get_node(addon, "date-updated").value, "Unknown", "Date should be correct"); - is_element_visible(get_node(addon, "warning"), "Warning message should be visible"); - is(get_node(addon, "warning").textContent, "Test add-on 3 is incompatible with " + gApp + " " + gVersion + ".", "Warning message should be correct"); - is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); - is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); - is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); - is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_visible(get_node(addon, "enable-btn"), "Enable button should be visible"); + is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); - info("Addon 4"); - addon = items["Test add-on 4"]; - addon.parentNode.ensureElementIsVisible(addon); - ({ name, version } = yield get_tooltip_info(addon)); - is(get_node(addon, "name").value, "Test add-on 4", "Name should be correct"); - is(name, "Test add-on 4", "Tooltip name should be correct"); + is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); - is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); - is_element_visible(get_node(addon, "enable-btn"), "Enable button should be visible"); - is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden"); - is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + info("Enabling"); + EventUtils.synthesizeMouseAtCenter(get_node(addon, "enable-btn"), {}, gManagerWindow); + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); + is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); - is_element_visible(get_node(addon, "warning"), "Warning message should be visible"); - is(get_node(addon, "warning").textContent, "Test add-on 4 is known to cause security or stability issues.", "Warning message should be correct"); - is_element_visible(get_node(addon, "warning-link"), "Warning link should be visible"); - is(get_node(addon, "warning-link").value, "More Information", "Warning link text should be correct"); - is(get_node(addon, "warning-link").href, "http://example.com/addon4@tests.mozilla.org", "Warning link should be correct"); - is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); - is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); - is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); + is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_visible(get_node(addon, "pending"), "Pending message should be visible"); + is(get_node(addon, "pending").textContent, "Test add-on 2 will be enabled after you restart " + gApp + ".", "Pending message should be correct"); - info("Enabling"); - EventUtils.synthesizeMouseAtCenter(get_node(addon, "enable-btn"), {}, gManagerWindow); - is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); - is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); - is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); - is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + info("Addon 3"); + addon = items["Test add-on 3"]; + addon.parentNode.ensureElementIsVisible(addon); + is(get_node(addon, "name").value, "Test add-on 3", "Name should be correct"); + is_element_hidden(get_node(addon, "version"), "Version should be hidden"); - is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); - is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); - is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); - is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); - is_element_visible(get_node(addon, "pending"), "Pending message should be visible"); - is(get_node(addon, "pending").textContent, "Test add-on 4 will be enabled after you restart " + gApp + ".", "Pending message should be correct"); + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); + is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden"); + is_element_hidden(get_node(addon, "remove-btn"), "Remove button should be hidden"); - info("Addon 5"); - addon = items["Test add-on 5"]; - addon.parentNode.ensureElementIsVisible(addon); - ({ name, version } = yield get_tooltip_info(addon)); - is(get_node(addon, "name").value, "Test add-on 5", "Name should be correct"); - is(name, "Test add-on 5", "Tooltip name should be correct"); + is_element_visible(get_node(addon, "warning"), "Warning message should be visible"); + is(get_node(addon, "warning").textContent, "Test add-on 3 is incompatible with " + gApp + " " + gVersion + ".", "Warning message should be correct"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); - is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); - is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); - is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden"); - is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + info("Addon 4"); + addon = items["Test add-on 4"]; + addon.parentNode.ensureElementIsVisible(addon); + is(get_node(addon, "name").value, "Test add-on 4", "Name should be correct"); - is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); - is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); - is_element_visible(get_node(addon, "error"), "Error message should be visible"); - is(get_node(addon, "error").textContent, "Test add-on 5 has been disabled due to security or stability issues.", "Error message should be correct"); - is_element_visible(get_node(addon, "error-link"), "Error link should be visible"); - is(get_node(addon, "error-link").value, "More Information", "Error link text should be correct"); - is(get_node(addon, "error-link").href, "http://example.com/addon5@tests.mozilla.org", "Error link should be correct"); - is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_visible(get_node(addon, "enable-btn"), "Enable button should be visible"); + is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); - info("Addon 6"); - addon = items["Test add-on 6"]; - addon.parentNode.ensureElementIsVisible(addon); - ({ name, version } = yield get_tooltip_info(addon)); - is(get_node(addon, "name").value, "Test add-on 6", "Name should be correct"); - is(name, "Test add-on 6", "Tooltip name should be correct"); - is_element_hidden(get_class_node(addon, "disabled-postfix"), "Disabled postfix should be hidden"); + is_element_visible(get_node(addon, "warning"), "Warning message should be visible"); + is(get_node(addon, "warning").textContent, "Test add-on 4 is known to cause security or stability issues.", "Warning message should be correct"); + is_element_visible(get_node(addon, "warning-link"), "Warning link should be visible"); + is(get_node(addon, "warning-link").value, "More Information", "Warning link text should be correct"); + is(get_node(addon, "warning-link").href, "http://example.com/addon4@tests.mozilla.org", "Warning link should be correct"); + is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); - is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); - is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); - is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); - is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + info("Enabling"); + EventUtils.synthesizeMouseAtCenter(get_node(addon, "enable-btn"), {}, gManagerWindow); + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); + is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); - is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); - is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); - is_element_hidden(get_node(addon, "error"), "Error message should be visible"); - is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); - is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); + is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_visible(get_node(addon, "pending"), "Pending message should be visible"); + is(get_node(addon, "pending").textContent, "Test add-on 4 will be enabled after you restart " + gApp + ".", "Pending message should be correct"); - info("Disabling"); - EventUtils.synthesizeMouseAtCenter(get_node(addon, "disable-btn"), {}, gManagerWindow); - is_element_visible(get_class_node(addon, "disabled-postfix"), "Disabled postfix should be visible"); + info("Addon 5"); + addon = items["Test add-on 5"]; + addon.parentNode.ensureElementIsVisible(addon); + is(get_node(addon, "name").value, "Test add-on 5", "Name should be correct"); - is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); - is_element_visible(get_node(addon, "enable-btn"), "Enable button should be visible"); - is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden"); - is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); + is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); - is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); - is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); - is_element_hidden(get_node(addon, "error"), "Error message should be visible"); - is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); - is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); + is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_visible(get_node(addon, "error"), "Error message should be visible"); + is(get_node(addon, "error").textContent, "Test add-on 5 has been disabled due to security or stability issues.", "Error message should be correct"); + is_element_visible(get_node(addon, "error-link"), "Error link should be visible"); + is(get_node(addon, "error-link").value, "More Information", "Error link text should be correct"); + is(get_node(addon, "error-link").href, "http://example.com/addon5@tests.mozilla.org", "Error link should be correct"); + is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); - info("Addon 7"); - addon = items["Test add-on 7"]; - addon.parentNode.ensureElementIsVisible(addon); - ({ name, version } = yield get_tooltip_info(addon)); - is(get_node(addon, "name").value, "Test add-on 7", "Name should be correct"); - is(name, "Test add-on 7", "Tooltip name should be correct"); + info("Addon 6"); + addon = items["Test add-on 6"]; + addon.parentNode.ensureElementIsVisible(addon); + is(get_node(addon, "name").value, "Test add-on 6", "Name should be correct"); + is_element_hidden(get_class_node(addon, "disabled-postfix"), "Disabled postfix should be hidden"); - is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); - is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); - is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); - is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); + is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); - is_element_visible(get_node(addon, "warning"), "Warning message should be hidden"); - is(get_node(addon, "warning").textContent, "An important update is available for Test add-on 7.", "Warning message should be correct"); - is_element_visible(get_node(addon, "warning-link"), "Warning link should be visible"); - is(get_node(addon, "warning-link").value, "Update Now", "Warning link text should be correct"); - is(get_node(addon, "warning-link").href, "http://example.com/addon7@tests.mozilla.org", "Warning link should be correct"); - is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); - is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); - is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); + is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_hidden(get_node(addon, "error"), "Error message should be visible"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); - info("Disabling"); - EventUtils.synthesizeMouseAtCenter(get_node(addon, "disable-btn"), {}, gManagerWindow); - is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); - is_element_visible(get_node(addon, "enable-btn"), "Enable button should be visible"); - is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden"); - is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + info("Disabling"); + EventUtils.synthesizeMouseAtCenter(get_node(addon, "disable-btn"), {}, gManagerWindow); + is_element_visible(get_class_node(addon, "disabled-postfix"), "Disabled postfix should be visible"); - is_element_hidden(get_node(addon, "warning"), "Warning message should be visible"); - is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); - is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); - is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); - is_element_visible(get_node(addon, "pending"), "Pending message should be visible"); - is(get_node(addon, "pending").textContent, "Test add-on 7 will be disabled after you restart " + gApp + ".", "Pending message should be correct"); + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_visible(get_node(addon, "enable-btn"), "Enable button should be visible"); + is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); - info("Addon 8"); - addon = items["Test add-on 8"]; - addon.parentNode.ensureElementIsVisible(addon); - ({ name, version } = yield get_tooltip_info(addon)); - is(get_node(addon, "name").value, "Test add-on 8", "Name should be correct"); - is(name, "Test add-on 8", "Tooltip name should be correct"); + is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_hidden(get_node(addon, "error"), "Error message should be visible"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); - is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); - is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); - is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); - is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + info("Addon 7"); + addon = items["Test add-on 7"]; + addon.parentNode.ensureElementIsVisible(addon); + is(get_node(addon, "name").value, "Test add-on 7", "Name should be correct"); - is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); - is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); - is_element_visible(get_node(addon, "error"), "Error message should be visible"); - is(get_node(addon, "error").textContent, "Test add-on 8 is known to be vulnerable and should be updated.", "Error message should be correct"); - is_element_visible(get_node(addon, "error-link"), "Error link should be visible"); - is(get_node(addon, "error-link").value, "Update Now", "Error link text should be correct"); - is(get_node(addon, "error-link").href, "http://example.com/addon8@tests.mozilla.org", "Error link should be correct"); - is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); + is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); - info("Addon 9"); - addon = items["Test add-on 9"]; - addon.parentNode.ensureElementIsVisible(addon); - ({ name, version } = yield get_tooltip_info(addon)); - is(get_node(addon, "name").value, "Test add-on 9", "Name should be correct"); - is(name, "Test add-on 9", "Tooltip name should be correct"); + is_element_visible(get_node(addon, "warning"), "Warning message should be hidden"); + is(get_node(addon, "warning").textContent, "An important update is available for Test add-on 7.", "Warning message should be correct"); + is_element_visible(get_node(addon, "warning-link"), "Warning link should be visible"); + is(get_node(addon, "warning-link").value, "Update Now", "Warning link text should be correct"); + is(get_node(addon, "warning-link").href, gPluginURL, "Warning link should be correct"); + is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); - is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); - is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); - is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); - is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + info("Disabling"); + EventUtils.synthesizeMouseAtCenter(get_node(addon, "disable-btn"), {}, gManagerWindow); + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_visible(get_node(addon, "enable-btn"), "Enable button should be visible"); + is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); - is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); - is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); - is_element_visible(get_node(addon, "error"), "Error message should be visible"); - is(get_node(addon, "error").textContent, "Test add-on 9 is known to be vulnerable. Use with caution.", "Error message should be correct"); - is_element_visible(get_node(addon, "error-link"), "Error link should be visible"); - is(get_node(addon, "error-link").value, "More Information", "Error link text should be correct"); - is(get_node(addon, "error-link").href, "http://example.com/addon9@tests.mozilla.org", "Error link should be correct"); - is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); + is_element_hidden(get_node(addon, "warning"), "Warning message should be visible"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_visible(get_node(addon, "pending"), "Pending message should be visible"); + is(get_node(addon, "pending").textContent, "Test add-on 7 will be disabled after you restart " + gApp + ".", "Pending message should be correct"); - // These tests are only appropriate when signing can be turned off - if (!REQUIRE_SIGNING) { - info("Addon 10"); - addon = items["Test add-on 10"]; + info("Addon 8"); + addon = items["Test add-on 8"]; addon.parentNode.ensureElementIsVisible(addon); - ({ name, version } = yield get_tooltip_info(addon)); - is(get_node(addon, "name").value, "Test add-on 10", "Name should be correct"); - is(name, "Test add-on 10", "Tooltip name should be correct"); + is(get_node(addon, "name").value, "Test add-on 8", "Name should be correct"); is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); - is_element_visible(get_node(addon, "warning"), "Warning message should be visible"); - is(get_node(addon, "warning").textContent, "Test add-on 10 could not be verified for use in " + gApp + ". Proceed with caution.", "Warning message should be correct"); - is_element_visible(get_node(addon, "warning-link"), "Warning link should be visible"); - is(get_node(addon, "warning-link").value, "More Information", "Warning link text should be correct"); - is(get_node(addon, "warning-link").href, infoURL, "Warning link should be correct"); - is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); - is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_visible(get_node(addon, "error"), "Error message should be visible"); + is(get_node(addon, "error").textContent, "Test add-on 8 is known to be vulnerable and should be updated.", "Error message should be correct"); + is_element_visible(get_node(addon, "error-link"), "Error link should be visible"); + is(get_node(addon, "error-link").value, "Update Now", "Error link text should be correct"); + is(get_node(addon, "error-link").href, "http://example.com/addon8@tests.mozilla.org", "Error link should be correct"); is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); - info("Addon 11"); - addon = items["Test add-on 11"]; + info("Addon 9"); + addon = items["Test add-on 9"]; addon.parentNode.ensureElementIsVisible(addon); - ({ name, version } = yield get_tooltip_info(addon)); - is(get_node(addon, "name").value, "Test add-on 11", "Name should be correct"); - is(name, "Test add-on 11", "Tooltip name should be correct"); + is(get_node(addon, "name").value, "Test add-on 9", "Name should be correct"); is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); - is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden"); + is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); - is_element_visible(get_node(addon, "warning"), "Warning message should be visible"); - is(get_node(addon, "warning").textContent, "Test add-on 11 is incompatible with " + gApp + " " + gVersion + ".", "Warning message should be correct"); + is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); - is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); - is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_visible(get_node(addon, "error"), "Error message should be visible"); + is(get_node(addon, "error").textContent, "Test add-on 9 is known to be vulnerable. Use with caution.", "Error message should be correct"); + is_element_visible(get_node(addon, "error-link"), "Error link should be visible"); + is(get_node(addon, "error-link").value, "More Information", "Error link text should be correct"); + is(get_node(addon, "error-link").href, "http://example.com/addon9@tests.mozilla.org", "Error link should be correct"); is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); - info("Filter for disabled unsigned extensions shouldn't appear because signing checks are off"); - let filterButton = gManagerWindow.document.getElementById("show-disabled-unsigned-extensions"); - let showAllButton = gManagerWindow.document.getElementById("show-all-extensions"); - let signingInfoUI = gManagerWindow.document.getElementById("disabled-unsigned-addons-info"); - is_element_hidden(filterButton, "Button for showing disabled unsigned extensions should be hidden"); - is_element_hidden(showAllButton, "Button for showing all extensions should be hidden"); - is_element_hidden(signingInfoUI, "Signing info UI should be hidden"); - } + run_next_test(); + }); }); // Check the add-ons are now in the right state -add_task(function*() { - let [a1, a2, a4, a6] = yield promiseAddonsByIDs(["addon1@tests.mozilla.org", - "addon2@tests.mozilla.org", - "addon4@tests.mozilla.org", - "addon6@tests.mozilla.org"]); - - is(a1.pendingOperations, AddonManager.PENDING_DISABLE, "Add-on 1 should be pending disable"); - is(a2.pendingOperations, AddonManager.PENDING_ENABLE, "Add-on 2 should be pending enable"); - is(a4.pendingOperations, AddonManager.PENDING_ENABLE, "Add-on 4 should be pending enable"); +add_test(function() { + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon4@tests.mozilla.org", + "addon6@tests.mozilla.org"], + function([a1, a2, a4, a6]) { + is(a1.pendingOperations, AddonManager.PENDING_DISABLE, "Add-on 1 should be pending disable"); + is(a2.pendingOperations, AddonManager.PENDING_ENABLE, "Add-on 2 should be pending enable"); + is(a4.pendingOperations, AddonManager.PENDING_ENABLE, "Add-on 4 should be pending enable"); + + run_next_test(); + }); }); // Reload the list to make sure the changes are still pending and that undoing // works -add_task(function*() { - yield gCategoryUtilities.openType("plugin"); - yield gCategoryUtilities.openType("extension"); - - let items = get_test_items(); - is(Object.keys(items).length, EXPECTED_ADDONS, "Should be the right number of add-ons installed"); - - info("Addon 1"); - let addon = items["Test add-on"]; - addon.parentNode.ensureElementIsVisible(addon); - let { name, version } = yield get_tooltip_info(addon); - is(get_node(addon, "name").value, "Test add-on", "Name should be correct"); - is(name, "Test add-on", "Tooltip name should be correct"); - is(version, "1.0", "Tooltip version should be correct"); - is_element_visible(get_node(addon, "description"), "Description should be visible"); - is(get_node(addon, "description").value, "A test add-on", "Description should be correct"); - is_element_hidden(get_class_node(addon, "disabled-postfix"), "Disabled postfix should be hidden"); - is_element_hidden(get_class_node(addon, "update-postfix"), "Update postfix should be hidden"); - is(get_node(addon, "date-updated").value, formatDate(gDate), "Update date should be correct"); - - is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); - is_element_visible(get_node(addon, "enable-btn"), "Enable button should be visible"); - is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden"); - is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); - - is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); - is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); - is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); - is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); - is_element_visible(get_node(addon, "pending"), "Pending message should be visible"); - is(get_node(addon, "pending").textContent, "Test add-on will be disabled after you restart " + gApp + ".", "Pending message should be correct"); - - info("Undoing"); - EventUtils.synthesizeMouseAtCenter(get_node(addon, "undo-btn"), {}, gManagerWindow); - is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); - is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); - is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); - is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); - - is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); - is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); - is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); - is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); - is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); - - info("Addon 2"); - addon = items["Test add-on 2"]; - addon.parentNode.ensureElementIsVisible(addon); - ({ name, version } = yield get_tooltip_info(addon)); - is(get_node(addon, "name").value, "Test add-on 2", "Name should be correct"); - is(name, "Test add-on 2", "Tooltip name should be correct"); - is(version, "2.0", "Tooltip version should be correct"); - is_element_hidden(get_node(addon, "description"), "Description should be hidden"); - is_element_visible(get_class_node(addon, "disabled-postfix"), "Disabled postfix should be visible"); - is_element_hidden(get_class_node(addon, "update-postfix"), "Update postfix should be hidden"); - is(get_node(addon, "date-updated").value, "Unknown", "Date should be correct"); - - is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); - is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); - is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); - is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); - - is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); - is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); - is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); - is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); - is_element_visible(get_node(addon, "pending"), "Pending message should be visible"); - is(get_node(addon, "pending").textContent, "Test add-on 2 will be enabled after you restart " + gApp + ".", "Pending message should be correct"); - - info("Undoing"); - EventUtils.synthesizeMouseAtCenter(get_node(addon, "undo-btn"), {}, gManagerWindow); - is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); - is_element_visible(get_node(addon, "enable-btn"), "Enable button should be visible"); - is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden"); - is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); - - is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); - is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); - is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); - is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); - is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); - - info("Addon 4"); - addon = items["Test add-on 4"]; - addon.parentNode.ensureElementIsVisible(addon); - ({ name, version } = yield get_tooltip_info(addon)); - is(get_node(addon, "name").value, "Test add-on 4", "Name should be correct"); - is(name, "Test add-on 4", "Tooltip name should be correct"); - - is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); - is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); - is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); - is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); - - is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); - is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); - is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); - is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); - is_element_visible(get_node(addon, "pending"), "Pending message should be visible"); - is(get_node(addon, "pending").textContent, "Test add-on 4 will be enabled after you restart " + gApp + ".", "Pending message should be correct"); - - info("Undoing"); - EventUtils.synthesizeMouseAtCenter(get_node(addon, "undo-btn"), {}, gManagerWindow); - is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); - is_element_visible(get_node(addon, "enable-btn"), "Enable button should be visible"); - is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden"); - is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); - - is_element_visible(get_node(addon, "warning"), "Warning message should be visible"); - is(get_node(addon, "warning").textContent, "Test add-on 4 is known to cause security or stability issues.", "Warning message should be correct"); - is_element_visible(get_node(addon, "warning-link"), "Warning link should be visible"); - is(get_node(addon, "warning-link").value, "More Information", "Warning link text should be correct"); - is(get_node(addon, "warning-link").href, "http://example.com/addon4@tests.mozilla.org", "Warning link should be correct"); - is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); - is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); - is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); - - info("Addon 6"); - addon = items["Test add-on 6"]; - addon.parentNode.ensureElementIsVisible(addon); - ({ name, version } = yield get_tooltip_info(addon)); - is(get_node(addon, "name").value, "Test add-on 6", "Name should be correct"); - is(name, "Test add-on 6", "Tooltip name should be correct"); - is_element_visible(get_class_node(addon, "disabled-postfix"), "Disabled postfix should be visible"); - - is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); - is_element_visible(get_node(addon, "enable-btn"), "Enable button should be visible"); - is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden"); - is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); - - is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); - is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); - is_element_hidden(get_node(addon, "error"), "Error message should be visible"); - is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); - is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); - - info("Enabling"); - EventUtils.synthesizeMouseAtCenter(get_node(addon, "enable-btn"), {}, gManagerWindow); - is_element_hidden(get_class_node(addon, "disabled-postfix"), "Disabled postfix should be hidden"); - - is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); - is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); - is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); - is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); - - is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); - is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); - is_element_hidden(get_node(addon, "error"), "Error message should be visible"); - is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); - is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); - - info("Addon 7"); - addon = items["Test add-on 7"]; - addon.parentNode.ensureElementIsVisible(addon); - ({ name, version } = yield get_tooltip_info(addon)); - is(get_node(addon, "name").value, "Test add-on 7", "Name should be correct"); - is(name, "Test add-on 7", "Tooltip name should be correct"); - - is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); - is_element_visible(get_node(addon, "enable-btn"), "Enable button should be visible"); - is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden"); - is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); - - is_element_hidden(get_node(addon, "warning"), "Warning message should be visible"); - is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); - is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); - is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); - is_element_visible(get_node(addon, "pending"), "Pending message should be visible"); - is(get_node(addon, "pending").textContent, "Test add-on 7 will be disabled after you restart " + gApp + ".", "Pending message should be correct"); - - info("Undoing"); - EventUtils.synthesizeMouseAtCenter(get_node(addon, "undo-btn"), {}, gManagerWindow); - is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); - is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); - is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); - is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); - - is_element_visible(get_node(addon, "warning"), "Warning message should be hidden"); - is(get_node(addon, "warning").textContent, "An important update is available for Test add-on 7.", "Warning message should be correct"); - is_element_visible(get_node(addon, "warning-link"), "Warning link should be visible"); - is(get_node(addon, "warning-link").value, "Update Now", "Warning link text should be correct"); - is(get_node(addon, "warning-link").href, "http://example.com/addon7@tests.mozilla.org", "Warning link should be correct"); - is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); - is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); - is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); +add_test(function() { + gCategoryUtilities.openType("plugin", function() { + gCategoryUtilities.openType("extension", function() { + let items = get_test_items(); + is(Object.keys(items).length, 9, "Should be nine add-ons installed"); + + info("Addon 1"); + let addon = items["Test add-on"]; + addon.parentNode.ensureElementIsVisible(addon); + is(get_node(addon, "name").value, "Test add-on", "Name should be correct"); + is_element_visible(get_node(addon, "version"), "Version should be visible"); + is(get_node(addon, "version").value, "1.0", "Version should be correct"); + is_element_visible(get_node(addon, "description"), "Description should be visible"); + is(get_node(addon, "description").value, "A test add-on", "Description should be correct"); + is_element_hidden(get_class_node(addon, "disabled-postfix"), "Disabled postfix should be hidden"); + is_element_hidden(get_class_node(addon, "update-postfix"), "Update postfix should be hidden"); + is(get_node(addon, "date-updated").value, formatDate(gDate), "Update date should be correct"); + + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_visible(get_node(addon, "enable-btn"), "Enable button should be visible"); + is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + + is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_visible(get_node(addon, "pending"), "Pending message should be visible"); + is(get_node(addon, "pending").textContent, "Test add-on will be disabled after you restart " + gApp + ".", "Pending message should be correct"); + + info("Undoing"); + EventUtils.synthesizeMouseAtCenter(get_node(addon, "undo-btn"), {}, gManagerWindow); + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); + is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + + is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); + + info("Addon 2"); + addon = items["Test add-on 2"]; + addon.parentNode.ensureElementIsVisible(addon); + is(get_node(addon, "name").value, "Test add-on 2", "Name should be correct"); + is_element_visible(get_node(addon, "version"), "Version should be visible"); + is(get_node(addon, "version").value, "2.0", "Version should be correct"); + is_element_hidden(get_node(addon, "description"), "Description should be hidden"); + is_element_visible(get_class_node(addon, "disabled-postfix"), "Disabled postfix should be visible"); + is_element_hidden(get_class_node(addon, "update-postfix"), "Update postfix should be hidden"); + is(get_node(addon, "date-updated").value, "Unknown", "Date should be correct"); + + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); + is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + + is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_visible(get_node(addon, "pending"), "Pending message should be visible"); + is(get_node(addon, "pending").textContent, "Test add-on 2 will be enabled after you restart " + gApp + ".", "Pending message should be correct"); + + info("Undoing"); + EventUtils.synthesizeMouseAtCenter(get_node(addon, "undo-btn"), {}, gManagerWindow); + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_visible(get_node(addon, "enable-btn"), "Enable button should be visible"); + is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + + is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); + + info("Addon 4"); + addon = items["Test add-on 4"]; + addon.parentNode.ensureElementIsVisible(addon); + is(get_node(addon, "name").value, "Test add-on 4", "Name should be correct"); + + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); + is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + + is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_visible(get_node(addon, "pending"), "Pending message should be visible"); + is(get_node(addon, "pending").textContent, "Test add-on 4 will be enabled after you restart " + gApp + ".", "Pending message should be correct"); + + info("Undoing"); + EventUtils.synthesizeMouseAtCenter(get_node(addon, "undo-btn"), {}, gManagerWindow); + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_visible(get_node(addon, "enable-btn"), "Enable button should be visible"); + is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + + is_element_visible(get_node(addon, "warning"), "Warning message should be visible"); + is(get_node(addon, "warning").textContent, "Test add-on 4 is known to cause security or stability issues.", "Warning message should be correct"); + is_element_visible(get_node(addon, "warning-link"), "Warning link should be visible"); + is(get_node(addon, "warning-link").value, "More Information", "Warning link text should be correct"); + is(get_node(addon, "warning-link").href, "http://example.com/addon4@tests.mozilla.org", "Warning link should be correct"); + is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); + + info("Addon 6"); + addon = items["Test add-on 6"]; + addon.parentNode.ensureElementIsVisible(addon); + is(get_node(addon, "name").value, "Test add-on 6", "Name should be correct"); + is_element_visible(get_class_node(addon, "disabled-postfix"), "Disabled postfix should be visible"); + + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_visible(get_node(addon, "enable-btn"), "Enable button should be visible"); + is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + + is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_hidden(get_node(addon, "error"), "Error message should be visible"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); + + info("Enabling"); + EventUtils.synthesizeMouseAtCenter(get_node(addon, "enable-btn"), {}, gManagerWindow); + is_element_hidden(get_class_node(addon, "disabled-postfix"), "Disabled postfix should be hidden"); + + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); + is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + + is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_hidden(get_node(addon, "error"), "Error message should be visible"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); + + info("Addon 7"); + addon = items["Test add-on 7"]; + addon.parentNode.ensureElementIsVisible(addon); + is(get_node(addon, "name").value, "Test add-on 7", "Name should be correct"); + + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_visible(get_node(addon, "enable-btn"), "Enable button should be visible"); + is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + + is_element_hidden(get_node(addon, "warning"), "Warning message should be visible"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_visible(get_node(addon, "pending"), "Pending message should be visible"); + is(get_node(addon, "pending").textContent, "Test add-on 7 will be disabled after you restart " + gApp + ".", "Pending message should be correct"); + + info("Undoing"); + EventUtils.synthesizeMouseAtCenter(get_node(addon, "undo-btn"), {}, gManagerWindow); + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); + is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + + is_element_visible(get_node(addon, "warning"), "Warning message should be hidden"); + is(get_node(addon, "warning").textContent, "An important update is available for Test add-on 7.", "Warning message should be correct"); + is_element_visible(get_node(addon, "warning-link"), "Warning link should be visible"); + is(get_node(addon, "warning-link").value, "Update Now", "Warning link text should be correct"); + is(get_node(addon, "warning-link").href, gPluginURL, "Warning link should be correct"); + is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); + + run_next_test(); + }); + }); }); // Check the add-ons are now in the right state -add_task(function*() { - let [a1, a2, a4] = yield promiseAddonsByIDs(["addon1@tests.mozilla.org", - "addon2@tests.mozilla.org", - "addon4@tests.mozilla.org"]); - - is(a1.pendingOperations, 0, "Add-on 1 should not have any pending operations"); - is(a2.pendingOperations, 0, "Add-on 1 should not have any pending operations"); - is(a4.pendingOperations, 0, "Add-on 1 should not have any pending operations"); +add_test(function() { + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon4@tests.mozilla.org"], + function([a1, a2, a4]) { + is(a1.pendingOperations, 0, "Add-on 1 should not have any pending operations"); + is(a2.pendingOperations, 0, "Add-on 1 should not have any pending operations"); + is(a4.pendingOperations, 0, "Add-on 1 should not have any pending operations"); + + run_next_test(); + }); }); // Check that upgrades with onExternalInstall take effect immediately -add_task(function*() { +add_test(function() { gProvider.createAddons([{ id: "addon1@tests.mozilla.org", name: "Test add-on replacement", @@ -691,21 +613,16 @@ add_task(function*() { description: "A test add-on with a new description", updateDate: gDate, operationsRequiringRestart: AddonManager.OP_NEEDS_RESTART_NONE - }, { - id: "addon14@tests.mozilla.org", - name: "Test add-on 14", - hidden: true, }]); let items = get_test_items(); - is(Object.keys(items).length, EXPECTED_ADDONS, "Should be the right number of add-ons installed"); + is(Object.keys(items).length, 9, "Should be nine add-ons installed"); let addon = items["Test add-on replacement"]; addon.parentNode.ensureElementIsVisible(addon); - let { name, version } = yield get_tooltip_info(addon); is(get_node(addon, "name").value, "Test add-on replacement", "Name should be correct"); - is(name, "Test add-on replacement", "Tooltip name should be correct"); - is(version, "2.0", "Tooltip version should be correct"); + is_element_visible(get_node(addon, "version"), "Version should be visible"); + is(get_node(addon, "version").value, "2.0", "Version should be correct"); is_element_visible(get_node(addon, "description"), "Description should be visible"); is(get_node(addon, "description").value, "A test add-on with a new description", "Description should be correct"); is_element_hidden(get_class_node(addon, "disabled-postfix"), "Disabled postfix should be hidden"); @@ -722,10 +639,12 @@ add_task(function*() { is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); + + run_next_test(); }); // Check that focus changes correctly move around the selected list item -add_task(function*() { +add_test(function() { function is_node_in_list(aNode) { var list = gManagerWindow.document.getElementById("addon-list"); @@ -746,7 +665,6 @@ add_task(function*() { getService(Ci.nsIFocusManager); let addon = items["Test add-on 6"]; - addon.parentNode.ensureElementIsVisible(addon); EventUtils.synthesizeMouseAtCenter(addon, { }, gManagerWindow); is(fm.focusedElement, addon.parentNode, "Focus should have moved to the list"); @@ -779,178 +697,64 @@ add_task(function*() { Services.prefs.clearUserPref("accessibility.tabfocus_applies_to_xul"); } catch (e) { } + + run_next_test(); }); -add_task(function*() { +add_test(function() { info("Enabling lightweight theme"); LightweightThemeManager.currentTheme = gLWTheme; - + gManagerWindow.loadView("addons://list/theme"); - yield new Promise(resolve => wait_for_view_load(gManagerWindow, resolve)); + wait_for_view_load(gManagerWindow, function() { + var addon = get_addon_element(gManagerWindow, "4@personas.mozilla.org"); - var addon = get_addon_element(gManagerWindow, "4@personas.mozilla.org"); - - is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); - is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); - is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); - is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); + is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); - info("Disabling lightweight theme"); - LightweightThemeManager.currentTheme = null; + info("Disabling lightweight theme"); + LightweightThemeManager.currentTheme = null; - is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); - is_element_visible(get_node(addon, "enable-btn"), "Enable button should be hidden"); - is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be visible"); - is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_visible(get_node(addon, "enable-btn"), "Enable button should be hidden"); + is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be visible"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); - let [aAddon] = yield promiseAddonsByIDs(["4@personas.mozilla.org"]); - aAddon.uninstall(); + AddonManager.getAddonByID("4@personas.mozilla.org", function(aAddon) { + aAddon.uninstall(); + run_next_test(); + }); + }); }); // Check that onPropertyChanges for appDisabled updates the UI -add_task(function*() { +add_test(function() { info("Checking that onPropertyChanges for appDisabled updates the UI"); - let [aAddon] = yield promiseAddonsByIDs(["addon2@tests.mozilla.org"]); - aAddon.userDisabled = true; - aAddon.isCompatible = true; - aAddon.appDisabled = false; + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(aAddon) { + aAddon.userDisabled = true; + aAddon.isCompatible = true; + aAddon.appDisabled = false; - gManagerWindow.loadView("addons://list/extension"); - yield new Promise(resolve => wait_for_view_load(gManagerWindow, resolve)); - var el = get_addon_element(gManagerWindow, "addon2@tests.mozilla.org"); + gManagerWindow.loadView("addons://list/extension"); + wait_for_view_load(gManagerWindow, function() { + var el = get_addon_element(gManagerWindow, "addon2@tests.mozilla.org"); - is(el.getAttribute("active"), "false", "Addon should not be marked as active"); - is_element_hidden(get_node(el, "warning"), "Warning message should not be visible"); - - info("Making addon incompatible and appDisabled"); - aAddon.isCompatible = false; - aAddon.appDisabled = true; - - is(el.getAttribute("active"), "false", "Addon should not be marked as active"); - is_element_visible(get_node(el, "warning"), "Warning message should be visible"); - is(get_node(el, "warning").textContent, "Test add-on 2 is incompatible with " + gApp + " " + gVersion + ".", "Warning message should be correct"); -}); + is(el.getAttribute("active"), "false", "Addon should not be marked as active"); + is_element_hidden(get_node(el, "warning"), "Warning message should not be visible"); -// Check that the list displays correctly when signing is required -add_task(function*() { - yield close_manager(gManagerWindow); - Services.prefs.setBoolPref("xpinstall.signatures.required", true); - gManagerWindow = yield open_manager(null); - gCategoryUtilities = new CategoryUtilities(gManagerWindow); + info("Making addon incompatible and appDisabled"); + aAddon.isCompatible = false; + aAddon.appDisabled = true; - yield gCategoryUtilities.openType("extension"); - let items = get_test_items(); - is(Object.keys(items).length, EXPECTED_ADDONS, "Should be the right number of add-ons installed"); - - info("Addon 10"); - let addon = items["Test add-on 10"]; - addon.parentNode.ensureElementIsVisible(addon); - let { name, version } = yield get_tooltip_info(addon); - is(get_node(addon, "name").value, "Test add-on 10", "Name should be correct"); - is(name, "Test add-on 10", "Tooltip name should be correct"); - - is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); - is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); - is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); - is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); - - is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); - is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); - is_element_visible(get_node(addon, "error"), "Error message should be visible"); - is(get_node(addon, "error").textContent, "Test add-on 10 could not be verified for use in " + gApp + " and has been disabled.", "Error message should be correct"); - is_element_visible(get_node(addon, "error-link"), "Error link should be visible"); - is(get_node(addon, "error-link").value, "More Information", "Error link text should be correct"); - is(get_node(addon, "error-link").href, infoURL, "Error link should be correct"); - - info("Addon 11"); - addon = items["Test add-on 11"]; - addon.parentNode.ensureElementIsVisible(addon); - ({ name, version } = yield get_tooltip_info(addon)); - is(get_node(addon, "name").value, "Test add-on 11", "Name should be correct"); - is(name, "Test add-on 11", "Tooltip name should be correct"); - - is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); - is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); - is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden"); - is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); - - is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); - is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); - is_element_visible(get_node(addon, "error"), "Error message should be visible"); - is(get_node(addon, "error").textContent, "Test add-on 11 could not be verified for use in " + gApp + " and has been disabled.", "Error message should be correct"); - is_element_visible(get_node(addon, "error-link"), "Error link should be visible"); - is(get_node(addon, "error-link").value, "More Information", "Error link text should be correct"); - is(get_node(addon, "error-link").href, infoURL, "Error link should be correct"); - - info("Addon 12"); - addon = items["Test add-on 12"]; - addon.parentNode.ensureElementIsVisible(addon); - ({ name, version } = yield get_tooltip_info(addon)) - is(get_node(addon, "name").value, "Test add-on 12", "Name should be correct"); - is(name, "Test add-on 12", "Tooltip name should be correct"); - - is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); - is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); - is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); - is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); - - is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); - is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); - is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); - is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); - - info("Addon 13"); - addon = items["Test add-on 13"]; - addon.parentNode.ensureElementIsVisible(addon); - ({ name, version } = yield get_tooltip_info(addon)); - is(get_node(addon, "name").value, "Test add-on 13", "Name should be correct"); - is(name, "Test add-on 13", "Tooltip name should be correct"); - - is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); - is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); - is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); - is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); - - is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); - is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); - is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); - - info("Filter for disabled unsigned extensions"); - let filterButton = gManagerWindow.document.getElementById("show-disabled-unsigned-extensions"); - let showAllButton = gManagerWindow.document.getElementById("show-all-extensions"); - let signingInfoUI = gManagerWindow.document.getElementById("disabled-unsigned-addons-info"); - is_element_visible(filterButton, "Button for showing disabled unsigned extensions should be visible"); - is_element_hidden(showAllButton, "Button for showing all extensions should be hidden"); - is_element_hidden(signingInfoUI, "Signing info UI should be hidden"); - - filterButton.click(); - - yield new Promise(resolve => wait_for_view_load(gManagerWindow, resolve)); - - is_element_hidden(filterButton, "Button for showing disabled unsigned extensions should be hidden"); - is_element_visible(showAllButton, "Button for showing all extensions should be visible"); - is_element_visible(signingInfoUI, "Signing info UI should be visible"); - - items = get_test_items(); - is(Object.keys(items).length, 2, "Two add-ons should be shown"); - is(Object.keys(items)[0], "Test add-on 10", "The disabled unsigned extension should be shown"); - is(Object.keys(items)[1], "Test add-on 11", "The disabled unsigned extension should be shown"); - - showAllButton.click(); - - yield new Promise(resolve => wait_for_view_load(gManagerWindow, resolve)); - - items = get_test_items(); - is(Object.keys(items).length, EXPECTED_ADDONS, "All add-ons should be shown again"); - is_element_visible(filterButton, "Button for showing disabled unsigned extensions should be visible again"); - is_element_hidden(showAllButton, "Button for showing all extensions should be hidden again"); - is_element_hidden(signingInfoUI, "Signing info UI should be hidden again"); - - Services.prefs.setBoolPref("xpinstall.signatures.required", false); -}); + is(el.getAttribute("active"), "false", "Addon should not be marked as active"); + is_element_visible(get_node(el, "warning"), "Warning message should be visible"); + is(get_node(el, "warning").textContent, "Test add-on 2 is incompatible with " + gApp + " " + gVersion + ".", "Warning message should be correct"); -add_task(function*() { - return close_manager(gManagerWindow); + run_next_test(); + }); + }); }); diff --git a/toolkit/mozapps/extensions/test/browser/browser_manualupdates.js b/toolkit/mozapps/extensions/test/browser/browser_manualupdates.js index 0c5eb2da6..27a4a6cd8 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_manualupdates.js +++ b/toolkit/mozapps/extensions/test/browser/browser_manualupdates.js @@ -38,7 +38,7 @@ function end_test() { add_test(function() { gAvailableCategory = gManagerWindow.gCategories.get("addons://updates/available"); is(gCategoryUtilities.isVisible(gAvailableCategory), false, "Available Updates category should initially be hidden"); - + gProvider.createAddons([{ id: "addon2@tests.mozilla.org", name: "manually updating addon", @@ -47,7 +47,7 @@ add_test(function() { blocklistState: Ci.nsIBlocklistService.STATE_BLOCKED, applyBackgroundUpdates: AddonManager.AUTOUPDATE_DISABLE }]); - + is(gCategoryUtilities.isVisible(gAvailableCategory), false, "Available Updates category should still be hidden"); run_next_test(); @@ -55,17 +55,11 @@ add_test(function() { add_test(function() { - let finished = 0; - function maybeRunNext() { - if (++finished == 2) - run_next_test(); - } - gAvailableCategory.addEventListener("CategoryBadgeUpdated", function() { gAvailableCategory.removeEventListener("CategoryBadgeUpdated", arguments.callee, false); is(gCategoryUtilities.isVisible(gAvailableCategory), true, "Available Updates category should now be visible"); is(gAvailableCategory.badgeCount, 1, "Badge for Available Updates should now be 1"); - maybeRunNext(); + run_next_test(); }, false); gCategoryUtilities.openType("extension", function() { @@ -77,10 +71,7 @@ add_test(function() { }]); var item = get_addon_element(gManagerWindow, "addon2@tests.mozilla.org"); - get_tooltip_info(item).then(({ version }) => { - is(version, "1.0", "Should still show the old version in the tooltip"); - maybeRunNext(); - }); + is(item._version.value, "1.0", "Should still show the old version in the normal list"); }); }); @@ -100,62 +91,67 @@ add_test(function() { is(list.itemCount, 1, "Should be 1 available update listed"); var item = list.firstChild; is(item.mAddon.id, "addon2@tests.mozilla.org", "Update item should be for the manually updating addon"); - - // The item in the list will be checking for update information asynchronously - // so we have to wait for it to complete. Doing the same async request should - // make our callback be called later. - AddonManager.getAllInstalls(run_next_test); + + // for manual update items, update-related properties are updated asynchronously, + // so we poll for one of the expected changes to know when its done + function waitForAsyncInit() { + if (item._version.value == "1.1") { + run_next_test(); + return; + } + info("Update item not initialized yet, checking again in 100ms"); + setTimeout(waitForAsyncInit, 100); + } + waitForAsyncInit(); }); add_test(function() { var list = gManagerWindow.document.getElementById("updates-list"); var item = list.firstChild; - get_tooltip_info(item).then(({ version }) => { - is(version, "1.1", "Update item should have version number of the update"); - var postfix = gManagerWindow.document.getAnonymousElementByAttribute(item, "class", "update-postfix"); - is_element_visible(postfix, "'Update' postfix should be visible"); - is_element_visible(item._updateAvailable, ""); - is_element_visible(item._relNotesToggle, "Release notes toggle should be visible"); - is_element_hidden(item._warning, "Incompatible warning should be hidden"); - is_element_hidden(item._error, "Blocklist error should be hidden"); - - info("Opening release notes"); + is(item._version.value, "1.1", "Update item should have version number of the update"); + var postfix = gManagerWindow.document.getAnonymousElementByAttribute(item, "class", "update-postfix"); + is_element_visible(postfix, "'Update' postfix should be visible"); + is_element_visible(item._updateAvailable, ""); + is_element_visible(item._relNotesToggle, "Release notes toggle should be visible"); + is_element_hidden(item._warning, "Incompatible warning should be hidden"); + is_element_hidden(item._error, "Blocklist error should be hidden"); + + info("Opening release notes"); + item.addEventListener("RelNotesToggle", function() { + item.removeEventListener("RelNotesToggle", arguments.callee, false); + info("Release notes now open"); + + is_element_hidden(item._relNotesLoading, "Release notes loading message should be hidden"); + is_element_visible(item._relNotesError, "Release notes error message should be visible"); + is(item._relNotes.childElementCount, 0, "Release notes should be empty"); + + info("Closing release notes"); item.addEventListener("RelNotesToggle", function() { item.removeEventListener("RelNotesToggle", arguments.callee, false); - info("Release notes now open"); - - is_element_hidden(item._relNotesLoading, "Release notes loading message should be hidden"); - is_element_visible(item._relNotesError, "Release notes error message should be visible"); - is(item._relNotes.childElementCount, 0, "Release notes should be empty"); + info("Release notes now closed"); + info("Setting Release notes URI to something that should load"); + gProvider.installs[0].releaseNotesURI = Services.io.newURI(TESTROOT + "releaseNotes.xhtml", null, null) - info("Closing release notes"); + info("Re-opening release notes"); item.addEventListener("RelNotesToggle", function() { item.removeEventListener("RelNotesToggle", arguments.callee, false); - info("Release notes now closed"); - info("Setting Release notes URI to something that should load"); - gProvider.installs[0].releaseNotesURI = Services.io.newURI(TESTROOT + "releaseNotes.xhtml", null, null) - - info("Re-opening release notes"); - item.addEventListener("RelNotesToggle", function() { - item.removeEventListener("RelNotesToggle", arguments.callee, false); - info("Release notes now open"); - - is_element_hidden(item._relNotesLoading, "Release notes loading message should be hidden"); - is_element_hidden(item._relNotesError, "Release notes error message should be hidden"); - isnot(item._relNotes.childElementCount, 0, "Release notes should have been inserted into container"); - run_next_test(); + info("Release notes now open"); - }, false); - EventUtils.synthesizeMouseAtCenter(item._relNotesToggle, { }, gManagerWindow); - is_element_visible(item._relNotesLoading, "Release notes loading message should be visible"); + is_element_hidden(item._relNotesLoading, "Release notes loading message should be hidden"); + is_element_hidden(item._relNotesError, "Release notes error message should be hidden"); + isnot(item._relNotes.childElementCount, 0, "Release notes should have been inserted into container"); + run_next_test(); }, false); EventUtils.synthesizeMouseAtCenter(item._relNotesToggle, { }, gManagerWindow); + is_element_visible(item._relNotesLoading, "Release notes loading message should be visible"); }, false); EventUtils.synthesizeMouseAtCenter(item._relNotesToggle, { }, gManagerWindow); - is_element_visible(item._relNotesLoading, "Release notes loading message should be visible"); - }); + + }, false); + EventUtils.synthesizeMouseAtCenter(item._relNotesToggle, { }, gManagerWindow); + is_element_visible(item._relNotesLoading, "Release notes loading message should be visible"); }); diff --git a/toolkit/mozapps/extensions/test/browser/browser_metadataTimeout.js b/toolkit/mozapps/extensions/test/browser/browser_metadataTimeout.js index 98be4b7f8..e2aae6c13 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_metadataTimeout.js +++ b/toolkit/mozapps/extensions/test/browser/browser_metadataTimeout.js @@ -13,14 +13,14 @@ const PREF_METADATA_LASTUPDATE = "extensions.getAddons.cache.lastUpdate"; Components.utils.import("resource://gre/modules/Promise.jsm"); -var repo = {}; -var ARContext = Components.utils.import("resource://gre/modules/addons/AddonRepository.jsm", repo); +let repo = {}; +let ARContext = Components.utils.import("resource://gre/modules/addons/AddonRepository.jsm", repo); // Mock out the XMLHttpRequest factory for AddonRepository so // we can reply with a timeout -var pXHRStarted = Promise.defer(); -var oldXHRConstructor = ARContext.ServiceRequest; -ARContext.ServiceRequest = function() { +let pXHRStarted = Promise.defer(); +let oldXHRConstructor = ARContext.XHRequest; +ARContext.XHRequest = function() { this._handlers = new Map(); this.mozBackgroundRequest = false; this.timeout = undefined; @@ -108,7 +108,7 @@ add_task(function* amo_ping_timeout() { xhr._handlers.get("timeout")(); // Put the old XHR constructor back - ARContext.ServiceRequest = oldXHRConstructor; + ARContext.XHRequest = oldXHRConstructor; // The window should close without further interaction yield promise_window_close(compatWindow); }); diff --git a/toolkit/mozapps/extensions/test/browser/browser_newaddon.js b/toolkit/mozapps/extensions/test/browser/browser_newaddon.js index d450828ba..a460d79d8 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_newaddon.js +++ b/toolkit/mozapps/extensions/test/browser/browser_newaddon.js @@ -6,16 +6,13 @@ var gProvider; -function loadPage(aURL, aCallback, aBackground = false) { - let tab = gBrowser.addTab(); - if (!aBackground) - gBrowser.selectedTab = tab; - let browser = tab.linkedBrowser; - browser.loadURI(aURL); - browser.addEventListener("AddonDisplayed", function(event) { - browser.removeEventListener("AddonDisplayed", arguments.callee, false); - - aCallback(tab); +function loadPage(aURL, aCallback) { + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(aURL); + gBrowser.addEventListener("AddonDisplayed", function(event) { + gBrowser.removeEventListener("AddonDisplayed", arguments.callee, false); + + aCallback(gBrowser.selectedTab); }); } @@ -29,15 +26,13 @@ function test() { name: "Test 1", version: "5.3", userDisabled: true, - seen: false, operationsRequiringRestart: AddonManager.OP_NEEDS_RESTART_NONE }, { id: "addon2@tests.mozilla.org", name: "Test 2", version: "7.1", creator: "Dave Townsend", - userDisabled: true, - seen: false + userDisabled: true }]); run_next_test(); @@ -59,19 +54,16 @@ add_test(function() { is(doc.getElementById("buttonDeck").selectedPanel, doc.getElementById("continuePanel"), "Should be showing the right buttons"); - AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) { - ok(aAddon.seen, "Add-on should have been marked as seen"); + EventUtils.synthesizeMouseAtCenter(doc.getElementById("continue-button"), + {}, aTab.linkedBrowser.contentWindow); - EventUtils.synthesizeMouseAtCenter(doc.getElementById("continue-button"), - {}, aTab.linkedBrowser.contentWindow); - - is(gBrowser.tabs.length, 1, "Page should have been closed"); + is(gBrowser.tabs.length, 1, "Page should have been closed"); + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) { ok(aAddon.userDisabled, "Add-on should not have been enabled"); ok(!aAddon.isActive, "Add-on should not be running"); - aAddon.seen = false; run_next_test(); }); }); @@ -89,23 +81,19 @@ add_test(function() { is(doc.getElementById("buttonDeck").selectedPanel, doc.getElementById("continuePanel"), "Should be showing the right buttons"); - AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) { - ok(aAddon.seen, "Add-on should have been marked as seen"); + EventUtils.synthesizeMouseAtCenter(doc.getElementById("allow"), + {}, aTab.linkedBrowser.contentWindow); - EventUtils.synthesizeMouseAtCenter(doc.getElementById("allow"), - {}, aTab.linkedBrowser.contentWindow); + EventUtils.synthesizeMouseAtCenter(doc.getElementById("continue-button"), + {}, aTab.linkedBrowser.contentWindow); - EventUtils.synthesizeMouseAtCenter(doc.getElementById("continue-button"), - {}, aTab.linkedBrowser.contentWindow); - - is(gBrowser.tabs.length, 1, "Page should have been closed"); + is(gBrowser.tabs.length, 1, "Page should have been closed"); + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) { ok(!aAddon.userDisabled, "Add-on should now have been enabled"); ok(aAddon.isActive, "Add-on should now be running"); - aAddon.userDisabled = true; - aAddon.seen = false; run_next_test(); }); }); @@ -124,19 +112,16 @@ add_test(function() { is(doc.getElementById("buttonDeck").selectedPanel, doc.getElementById("continuePanel"), "Should be showing the right buttons"); - AddonManager.getAddonByID("addon2@tests.mozilla.org", function(aAddon) { - ok(aAddon.seen, "Add-on should have been marked as seen"); - - EventUtils.synthesizeMouseAtCenter(doc.getElementById("continue-button"), - {}, aTab.linkedBrowser.contentWindow); + EventUtils.synthesizeMouseAtCenter(doc.getElementById("continue-button"), + {}, aTab.linkedBrowser.contentWindow); - is(gBrowser.tabs.length, 1, "Page should have been closed"); + is(gBrowser.tabs.length, 1, "Page should have been closed"); + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(aAddon) { ok(aAddon.userDisabled, "Add-on should not have been enabled"); ok(!aAddon.isActive, "Add-on should not be running"); - aAddon.seen = false; run_next_test(); }); }); @@ -155,18 +140,16 @@ add_test(function() { is(doc.getElementById("buttonDeck").selectedPanel, doc.getElementById("continuePanel"), "Should be showing the right buttons"); - AddonManager.getAddonByID("addon2@tests.mozilla.org", function(aAddon) { - ok(aAddon.seen, "Add-on should have been marked as seen"); - - EventUtils.synthesizeMouseAtCenter(doc.getElementById("allow"), - {}, aTab.linkedBrowser.contentWindow); + EventUtils.synthesizeMouseAtCenter(doc.getElementById("allow"), + {}, aTab.linkedBrowser.contentWindow); - EventUtils.synthesizeMouseAtCenter(doc.getElementById("continue-button"), - {}, aTab.linkedBrowser.contentWindow); + EventUtils.synthesizeMouseAtCenter(doc.getElementById("continue-button"), + {}, aTab.linkedBrowser.contentWindow); - is(doc.getElementById("buttonDeck").selectedPanel, doc.getElementById("restartPanel"), - "Should be showing the right buttons"); + is(doc.getElementById("buttonDeck").selectedPanel, doc.getElementById("restartPanel"), + "Should be showing the right buttons"); + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(aAddon) { ok(!aAddon.userDisabled, "Add-on should now have been enabled"); ok(!aAddon.isActive, "Add-on should not be running"); @@ -197,36 +180,7 @@ add_test(function() { is(gBrowser.tabs.length, 1, "Page should have been closed"); - aAddon.seen = false; run_next_test(); }); }); }); - -// Tests that opening the page in the background doesn't mark as seen -add_test(function() { - loadPage("about:newaddon?id=addon1@tests.mozilla.org", function(aTab) { - var doc = aTab.linkedBrowser.contentDocument; - is(doc.getElementById("name").value, "Test 1 5.3", "Should say the right name"); - - is_element_hidden(doc.getElementById("author"), "Should be no author displayed"); - is_element_hidden(doc.getElementById("location"), "Should be no location displayed"); - - is(doc.getElementById("buttonDeck").selectedPanel, doc.getElementById("continuePanel"), - "Should be showing the right buttons"); - - AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) { - ok(!aAddon.seen, "Add-on should not have been marked as seen."); - - gBrowser.selectedTab = aTab; - - waitForFocus(function() { - ok(aAddon.seen, "Add-on should have been marked as seen after focusing the tab."); - - gBrowser.removeTab(aTab); - - run_next_test(); - }, aTab.linkedBrowser.contentWindow); - }); - }, true); -}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_openDialog.js b/toolkit/mozapps/extensions/test/browser/browser_openDialog.js index f95365a4c..bdbe9caee 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_openDialog.js +++ b/toolkit/mozapps/extensions/test/browser/browser_openDialog.js @@ -5,7 +5,7 @@ // Tests the dialog open by the Options button for addons that provide a // custom chrome-like protocol for optionsURL. -var CustomChromeProtocol = { +let CustomChromeProtocol = { scheme: "khrome", defaultPort: -1, protocolFlags: Ci.nsIProtocolHandler.URI_DANGEROUS_TO_LOAD | @@ -20,17 +20,20 @@ var CustomChromeProtocol = { return uri; }, - newChannel2: function CCP_newChannel2(aURI, aLoadInfo) { - let url = Services.io.newURI("chrome:" + aURI.path, null, null); - let ch = Services.io.newChannelFromURIWithLoadInfo(url, aLoadInfo); + newChannel: function CCP_newChannel(aURI) { + let url = "chrome:" + aURI.path; + let ch = NetUtil.newChannel2(url, + null, + null, + null, // aLoadingNode + Services.scriptSecurityManager.getSystemPrincipal(), + null, // aTriggeringPrincipal + Ci.nsILoadInfo.SEC_NORMAL, + Ci.nsIContentPolicy.TYPE_OTHER); ch.originalURI = aURI; return ch; }, - newChannel: function CCP_newChannel(aURI) { - return this.newChannel2(aURI, null); - }, - allowPort: function CCP_allowPort(aPort, aScheme) { return false; }, @@ -83,7 +86,7 @@ function test() { info("Registering custom chrome-like protocol."); CustomChromeProtocol.factory.register(); - registerCleanupFunction(() => CustomChromeProtocol.factory.unregister()); + registerCleanupFunction(function () CustomChromeProtocol.factory.unregister()); const ADDONS_LIST = [ { id: "test1@tests.mozilla.org", diff --git a/toolkit/mozapps/extensions/test/browser/browser_plugin_enabled_state_locked.js b/toolkit/mozapps/extensions/test/browser/browser_plugin_enabled_state_locked.js index a9c7be4bc..b32d74336 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_plugin_enabled_state_locked.js +++ b/toolkit/mozapps/extensions/test/browser/browser_plugin_enabled_state_locked.js @@ -4,23 +4,24 @@ // Tests that state menu is displayed correctly (enabled or disabled) in the add-on manager // when the preference is unlocked / locked -var {classes: Cc, interfaces: Ci} = Components; +const {classes: Cc, interfaces: Ci} = Components; const gIsWindows = ("@mozilla.org/windows-registry-key;1" in Cc); const gIsOSX = ("nsILocalFileMac" in Ci); const gIsLinux = ("@mozilla.org/gnome-gconf-service;1" in Cc) || ("@mozilla.org/gio-service;1" in Cc); -var gManagerWindow; -var gCategoryUtilities; -var gPluginElement; +let gManagerWindow; +let gCategoryUtilities; +let gPluginElement; function getTestPluginPref() { let prefix = "plugin.state."; if (gIsWindows) - return `${prefix}nptest`; - if (gIsLinux) - return `${prefix}libnptest`; - return `${prefix}test`; + return prefix + "nptest"; + else if (gIsLinux) + return prefix + "libnptest"; + else + return prefix + "test"; } registerCleanupFunction(() => { @@ -29,9 +30,9 @@ registerCleanupFunction(() => { }); function getPlugins() { - return new Promise(resolve => { - AddonManager.getAddonsByTypes(["plugin"], plugins => resolve(plugins)); - }); + let deferred = Promise.defer(); + AddonManager.getAddonsByTypes(["plugin"], plugins => deferred.resolve(plugins)); + return deferred.promise; } function getTestPlugin(aPlugins) { @@ -75,15 +76,15 @@ function checkStateMenuDetail(locked) { is_element_visible(details, "Details link should be visible."); EventUtils.synthesizeMouseAtCenter(details, {}, gManagerWindow); - return new Promise(resolve => { - wait_for_view_load(gManagerWindow, function() { - let menuList = gManagerWindow.document.getElementById("detail-state-menulist"); - is_element_visible(menuList, "Details state menu should be visible."); - Assert.equal(menuList.disabled, locked, - "Details state menu enabled state should be correct."); - resolve(); - }); + let deferred = Promise.defer(); + wait_for_view_load(gManagerWindow, function() { + let menuList = gManagerWindow.document.getElementById("detail-state-menulist"); + is_element_visible(menuList, "Details state menu should be visible."); + Assert.equal(menuList.disabled, locked, + "Details state menu enabled state should be correct."); + deferred.resolve(); }); + return deferred.promise; } add_task(function* initializeState() { diff --git a/toolkit/mozapps/extensions/test/browser/browser_purchase.js b/toolkit/mozapps/extensions/test/browser/browser_purchase.js index a815d10d5..bb30a1eb4 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_purchase.js +++ b/toolkit/mozapps/extensions/test/browser/browser_purchase.js @@ -121,7 +121,7 @@ add_test(function() { info("Changing sort order"); EventUtils.synthesizeMouseAtCenter(priceSorter, { }, gManagerWindow); - items = Array.filter(list.childNodes, function(e) { + var items = Array.filter(list.childNodes, function(e) { return e.tagName == "richlistitem"; }); @@ -136,24 +136,23 @@ add_test(function() { // Tests that clicking the buy button works from the list add_test(function() { - gBrowser.tabContainer.addEventListener("TabOpen", function listener(event) { - gBrowser.tabContainer.removeEventListener("TabOpen", listener, true); - function wantLoad(url) { - return url != "about:blank"; - } - BrowserTestUtils.browserLoaded(event.target.linkedBrowser, false, wantLoad).then(() => { - is(gBrowser.currentURI.spec, TESTROOT + "releaseNotes.xhtml?addon5", "Should have loaded the right page"); + gBrowser.addEventListener("load", function(event) { + if (!(event.target instanceof Document) || + event.target.location.href == "about:blank") + return; + gBrowser.removeEventListener("load", arguments.callee, true); - gBrowser.removeCurrentTab(); + is(gBrowser.currentURI.spec, TESTROOT + "releaseNotes.xhtml?addon5", "Should have loaded the right page"); - if (gUseInContentUI) { - is(gBrowser.currentURI.spec, "about:addons", "Should be back to the add-ons manager"); - run_next_test(); - } - else { - waitForFocus(run_next_test, gManagerWindow); - } - }); + gBrowser.removeCurrentTab(); + + if (gUseInContentUI) { + is(gBrowser.currentURI.spec, "about:addons", "Should be back to the add-ons manager"); + run_next_test(); + } + else { + waitForFocus(run_next_test, gManagerWindow); + } }, true); var list = gManagerWindow.document.getElementById("search-list"); @@ -162,24 +161,23 @@ add_test(function() { // Tests that clicking the buy button from the details view works add_test(function() { - gBrowser.tabContainer.addEventListener("TabOpen", function listener(event) { - gBrowser.tabContainer.removeEventListener("TabOpen", listener, true); - function wantLoad(url) { - return url != "about:blank"; - } - BrowserTestUtils.browserLoaded(event.target.linkedBrowser, false, wantLoad).then(() => { - is(gBrowser.currentURI.spec, TESTROOT + "releaseNotes.xhtml?addon4", "Should have loaded the right page"); + gBrowser.addEventListener("load", function(event) { + if (!(event.target instanceof Document) || + event.target.location.href == "about:blank") + return; + gBrowser.removeEventListener("load", arguments.callee, true); - gBrowser.removeCurrentTab(); + is(gBrowser.currentURI.spec, TESTROOT + "releaseNotes.xhtml?addon4", "Should have loaded the right page"); - if (gUseInContentUI) { - is(gBrowser.currentURI.spec, "about:addons", "Should be back to the add-ons manager"); - run_next_test(); - } - else { - waitForFocus(run_next_test, gManagerWindow); - } - }); + gBrowser.removeCurrentTab(); + + if (gUseInContentUI) { + is(gBrowser.currentURI.spec, "about:addons", "Should be back to the add-ons manager"); + run_next_test(); + } + else { + waitForFocus(run_next_test, gManagerWindow); + } }, true); var list = gManagerWindow.document.getElementById("search-list"); diff --git a/toolkit/mozapps/extensions/test/browser/browser_purchase.xml b/toolkit/mozapps/extensions/test/browser/browser_purchase.xml index 9d4b18880..470f47d28 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_purchase.xml +++ b/toolkit/mozapps/extensions/test/browser/browser_purchase.xml @@ -17,7 +17,7 @@ <compatible_applications> <application> <name>Firefox</name> - <appID>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</appID> + <appID>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</appID> <min_version>0</min_version> <max_version>*</max_version> </application> @@ -53,7 +53,7 @@ <compatible_applications> <application> <name>Firefox</name> - <appID>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</appID> + <appID>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</appID> <min_version>0</min_version> <max_version>*</max_version> </application> @@ -89,7 +89,7 @@ <compatible_applications> <application> <name>Firefox</name> - <appID>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</appID> + <appID>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</appID> <min_version>0</min_version> <max_version>*</max_version> </application> @@ -125,7 +125,7 @@ <compatible_applications> <application> <name>Firefox</name> - <appID>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</appID> + <appID>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</appID> <min_version>0</min_version> <max_version>*</max_version> </application> @@ -158,7 +158,7 @@ <compatible_applications> <application> <name>Firefox</name> - <appID>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</appID> + <appID>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</appID> <min_version>0</min_version> <max_version>*</max_version> </application> diff --git a/toolkit/mozapps/extensions/test/browser/browser_recentupdates.js b/toolkit/mozapps/extensions/test/browser/browser_recentupdates.js index 02007dbbf..1427d5eba 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_recentupdates.js +++ b/toolkit/mozapps/extensions/test/browser/browser_recentupdates.js @@ -30,7 +30,7 @@ function test() { version: "1.0", updateDate: new Date(Date.now() - (1000 * 60 * 60 * 25 * 30)) }]); - + open_manager("addons://list/extension", function(aWindow) { gManagerWindow = aWindow; gCategoryUtilities = new CategoryUtilities(gManagerWindow); diff --git a/toolkit/mozapps/extensions/test/browser/browser_searching.js b/toolkit/mozapps/extensions/test/browser/browser_searching.js index 907d9b105..9e03e8297 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_searching.js +++ b/toolkit/mozapps/extensions/test/browser/browser_searching.js @@ -175,7 +175,7 @@ function get_actual_results() { continue; } - let result = sourceURI.match(/^http:\/\/example\.com\/(.+)\.xpi$/); + var result = sourceURI.match(/^http:\/\/example\.com\/(.+)\.xpi$/); if (result != null) { is(item.mInstall.name.indexOf("PASS"), 0, "Install name should start with PASS"); results.push({name: result[1], item: item}); @@ -183,7 +183,7 @@ function get_actual_results() { } } else if (item.mAddon) { - let result = item.mAddon.id.match(/^(.+)@tests\.mozilla\.org$/); + var result = item.mAddon.id.match(/^(.+)@tests\.mozilla\.org$/); if (result != null) { is(item.mAddon.name.indexOf("PASS"), 0, "Addon name should start with PASS"); results.push({name: result[1], item: item}); @@ -212,21 +212,21 @@ function get_expected_results(aSortBy, aLocalExpected) { var expectedOrder = null, unknownOrder = null; switch (aSortBy) { case "relevancescore": - expectedOrder = [ "addon2", "remote1", "install2", "addon1", - "install1", "remote2", "remote3", "remote4" ]; + expectedOrder = [ "addon2" , "remote1", "install2", "addon1", + "install1", "remote2", "remote3" , "remote4" ]; unknownOrder = []; break; case "name": // Defaults to ascending order - expectedOrder = [ "install1", "remote1", "addon2", "remote2", - "remote3", "addon1", "install2", "remote4" ]; + expectedOrder = [ "install1", "remote1", "addon2" , "remote2", + "remote3" , "addon1" , "install2", "remote4" ]; unknownOrder = []; break; case "dateUpdated": expectedOrder = [ "addon1", "addon2" ]; // Updated date not available for installs and remote add-ons unknownOrder = [ "install1", "install2", "remote1", - "remote2", "remote3", "remote4" ]; + "remote2" , "remote3" , "remote4" ]; break; default: ok(false, "Should recognize sortBy when checking the order of items"); @@ -269,9 +269,9 @@ function check_results(aQuery, aSortBy, aReverseOrder, aShowLocal) { try { xpinstall_enabled = Services.prefs.getBoolPref(PREF_XPI_ENABLED); } - catch (e) {} + catch (e) {}; - // When XPI Instalation is disabled, those buttons are hidden and unused + // When XPI Instalation is disabled, those buttons are hidden and unused if (xpinstall_enabled) { var localFilterSelected = gManagerWindow.document.getElementById("search-filter-local").selected; var remoteFilterSelected = gManagerWindow.document.getElementById("search-filter-remote").selected; @@ -286,7 +286,7 @@ function check_results(aQuery, aSortBy, aReverseOrder, aShowLocal) { // Get actual order of results var actualResults = get_actual_results(); - var actualOrder = actualResults.map(result => result.name); + var actualOrder = [result.name for each(result in actualResults)]; // Reverse array of actual results if supposed to be in reverse order. // Reverse actualOrder instead of expectedOrder so can always check @@ -617,7 +617,7 @@ add_test(function() { // Tests that compatible-by-default addons are shown if strict compatibility checking is disabled add_test(function() { - restart_manager(gManagerWindow, "addons://list/extension", function(aWindow) { + restart_manager(gManagerWindow, null, function(aWindow) { gManagerWindow = aWindow; gCategoryUtilities = new CategoryUtilities(gManagerWindow); @@ -626,10 +626,10 @@ add_test(function() { var item = get_addon_item("remote5"); is_element_visible(item, "Incompatible addon should be visible"); isnot(item.getAttribute("notification"), "warning", "Compatibility warning should not be shown"); - - item = get_addon_item("remote6"); + + var item = get_addon_item("remote6"); is(item, null, "Addon incompatible with the product should not be visible"); - + Services.prefs.setBoolPref(PREF_STRICT_COMPAT, true); run_next_test(); }); @@ -649,16 +649,13 @@ add_test(function() { // Installed add-on is considered local on new search gAddonInstalled = true; - // Switch over to extensions list so we can do a new search - gCategoryUtilities.openType("extension", function() { - search(QUERY, false, function() { - check_filtered_results(QUERY, "relevancescore", false); + search(QUERY, false, function() { + check_filtered_results(QUERY, "relevancescore", false); - var installBtn = get_install_button(get_addon_item(REMOTE_TO_INSTALL)); - is(installBtn.hidden, true, "Install button should be hidden for installed item"); + var installBtn = get_install_button(get_addon_item(REMOTE_TO_INSTALL)); + is(installBtn.hidden, true, "Install button should be hidden for installed item"); - run_next_test(); - }); + run_next_test(); }); }); }); diff --git a/toolkit/mozapps/extensions/test/browser/browser_searching.xml b/toolkit/mozapps/extensions/test/browser/browser_searching.xml index a3537b269..e88db289e 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_searching.xml +++ b/toolkit/mozapps/extensions/test/browser/browser_searching.xml @@ -17,7 +17,7 @@ <compatible_applications> <application> <name>Firefox</name> - <appID>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</appID> + <appID>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</appID> <min_version>0</min_version> <max_version>*</max_version> </application> @@ -48,7 +48,7 @@ <compatible_applications> <application> <name>Firefox</name> - <appID>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</appID> + <appID>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</appID> <min_version>0</min_version> <max_version>*</max_version> </application> @@ -79,7 +79,7 @@ <compatible_applications> <application> <name>Firefox</name> - <appID>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</appID> + <appID>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</appID> <min_version>0</min_version> <max_version>*</max_version> </application> @@ -110,7 +110,7 @@ <compatible_applications> <application> <name>Firefox</name> - <appID>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</appID> + <appID>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</appID> <min_version>0</min_version> <max_version>*</max_version> </application> @@ -141,7 +141,7 @@ <compatible_applications> <application> <name>Firefox</name> - <appID>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</appID> + <appID>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</appID> <min_version>0</min_version> <max_version>*</max_version> </application> @@ -172,7 +172,7 @@ <compatible_applications> <application> <name>Firefox</name> - <appID>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</appID> + <appID>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</appID> <min_version>0</min_version> <max_version>*</max_version> </application> @@ -203,7 +203,7 @@ <compatible_applications> <application> <name>Firefox</name> - <appID>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</appID> + <appID>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</appID> <min_version>0</min_version> <max_version>*</max_version> </application> @@ -234,7 +234,7 @@ <compatible_applications> <application> <name>Firefox</name> - <appID>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</appID> + <appID>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</appID> <min_version>0</min_version> <max_version>1</max_version> </application> diff --git a/toolkit/mozapps/extensions/test/browser/browser_select_compatoverrides.js b/toolkit/mozapps/extensions/test/browser/browser_select_compatoverrides.js new file mode 100644 index 000000000..747811e63 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_select_compatoverrides.js @@ -0,0 +1,116 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests that compatibility overrides are refreshed when showing the addon +// selection UI. + +const PREF_GETADDONS_BYIDS = "extensions.getAddons.get.url"; +const PREF_MIN_PLATFORM_COMPAT = "extensions.minCompatiblePlatformVersion"; + +var gTestAddon = null; +var gWin; + +function waitForView(aView, aCallback) { + var view = gWin.document.getElementById(aView); + if (view.parentNode.selectedPanel == view) { + aCallback(); + return; + } + + view.addEventListener("ViewChanged", function() { + view.removeEventListener("ViewChanged", arguments.callee, false); + aCallback(); + }, false); +} + +function install_test_addon(aCallback) { + AddonManager.getInstallForURL(TESTROOT + "addons/browser_select_compatoverrides_1.xpi", function(aInstall) { + var listener = { + onInstallEnded: function() { + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(addon) { + gTestAddon = addon; + executeSoon(aCallback); + }); + } + }; + aInstall.addListener(listener); + aInstall.install(); + }, "application/x-xpinstall"); +} + +registerCleanupFunction(function() { + if (gWin) + gWin.close(); + if (gTestAddon) + gTestAddon.uninstall(); + + Services.prefs.clearUserPref(PREF_MIN_PLATFORM_COMPAT); +}); + +function end_test() { + finish(); +} + + +function test() { + waitForExplicitFinish(); + Services.prefs.setCharPref(PREF_UPDATEURL, TESTROOT + "missing.rdf"); + Services.prefs.setBoolPref(PREF_STRICT_COMPAT, false); + Services.prefs.setCharPref(PREF_MIN_PLATFORM_COMPAT, "0"); + + install_test_addon(run_next_test); +} + +add_test(function() { + gWin = Services.ww.openWindow(null, + "chrome://mozapps/content/extensions/selectAddons.xul", + "", + "chrome,centerscreen,dialog,titlebar", + null); + waitForFocus(function() { + waitForView("select", run_next_test); + }, gWin); +}); + +add_test(function() { + for (var row = gWin.document.getElementById("select-rows").firstChild; row; row = row.nextSibling) { + if (row.localName == "separator") + continue; + if (row.id.substr(-18) != "@tests.mozilla.org") + continue; + + is(row.id, "addon1@tests.mozilla.org", "Should get expected addon"); + isnot(row.action, "incompatible", "Addon should not be incompatible"); + + gWin.close(); + gWin = null; + run_next_test(); + } +}); + +add_test(function() { + Services.prefs.setCharPref(PREF_GETADDONS_BYIDS, TESTROOT + "browser_select_compatoverrides.xml"); + Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true); + + gWin = Services.ww.openWindow(null, + "chrome://mozapps/content/extensions/selectAddons.xul", + "", + "chrome,centerscreen,dialog,titlebar", + null); + waitForFocus(function() { + waitForView("select", run_next_test); + }, gWin); +}); + +add_test(function() { + for (var row = gWin.document.getElementById("select-rows").firstChild; row; row = row.nextSibling) { + if (row.localName == "separator") + continue; + if (row.id.substr(-18) != "@tests.mozilla.org") + continue; + is(row.id, "addon1@tests.mozilla.org", "Should get expected addon"); + is(row.action, "incompatible", "Addon should be incompatible"); + run_next_test(); + } +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_select_compatoverrides.xml b/toolkit/mozapps/extensions/test/browser/browser_select_compatoverrides.xml new file mode 100644 index 000000000..76d00aa2c --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_select_compatoverrides.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8" ?> +<searchresults total_results="1"> + <addon_compatibility hosted="false"> + <guid>addon1@tests.mozilla.org</guid> + <name>Addon1</name> + <version_ranges> + <version_range type="incompatible"> + <min_version>1.0</min_version> + <max_version>2.0</max_version> + <compatible_applications> + <application> + <min_version>0.1</min_version> + <max_version>999.0</max_version> + <appID>toolkit@mozilla.org</appID> + </application> + </compatible_applications> + </version_range> + </version_ranges> + </addon_compatibility> +</searchresults> diff --git a/toolkit/mozapps/extensions/test/browser/browser_select_confirm.js b/toolkit/mozapps/extensions/test/browser/browser_select_confirm.js new file mode 100644 index 000000000..1204777ce --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_select_confirm.js @@ -0,0 +1,181 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests the confirmation part of the post-app-update dialog + +var gProvider; +var gWin; + +function waitForView(aView, aCallback) { + var view = gWin.document.getElementById(aView); + if (view.parentNode.selectedPanel == view) { + aCallback(); + return; + } + + view.addEventListener("ViewChanged", function() { + view.removeEventListener("ViewChanged", arguments.callee, false); + try { + aCallback(); + } + catch (e) { + ok(false, e); + } + }, false); +} + +/** + * Creates 4 test add-ons. Two are disabled and two enabled. + * + * @param aAppDisabled + * The appDisabled property for the test add-ons + * @param aUpdateAvailable + * True if the test add-ons should claim to have an update available + */ +function setupUI(aAppDisabled, aUpdateAvailable, aCallback) { + if (gProvider) + gProvider.unregister(); + + gProvider = new MockProvider(); + + for (var i = 1; i < 5; i++) { + var addon = new MockAddon("test" + i + "@tests.mozilla.org", + "Test Add-on " + i, "extension"); + addon.version = "1.0"; + addon.userDisabled = (i > 2); + addon.appDisabled = aAppDisabled; + addon.isActive = !addon.userDisabled && !addon.appDisabled; + + addon.findUpdates = function(aListener, aReason, aAppVersion, aPlatformVersion) { + if (aUpdateAvailable) { + var newAddon = new MockAddon(this.id, this.name, "extension"); + newAddon.version = "2.0"; + var install = new MockInstall(this.name, this.type, newAddon); + install.existingAddon = this; + aListener.onUpdateAvailable(this, install); + } + + aListener.onUpdateFinished(this, AddonManager.UPDATE_STATUS_NO_ERROR); + }; + + gProvider.addAddon(addon); + } + + gWin = Services.ww.openWindow(null, + "chrome://mozapps/content/extensions/selectAddons.xul", + "", + "chrome,centerscreen,dialog,titlebar", + null); + waitForFocus(function() { + waitForView("select", function() { + var row = gWin.document.getElementById("select-rows").firstChild.nextSibling; + while (row) { + if (!row.id || row.id.indexOf("@tests.mozilla.org") < 0) { + // not a test add-on + row = row.nextSibling; + continue; + } + + if (row.id == "test2@tests.mozilla.org" || + row.id == "test4@tests.mozilla.org") { + row.disable(); + } + else { + row.keep(); + } + row = row.nextSibling; + } + + waitForView("confirm", aCallback); + EventUtils.synthesizeMouseAtCenter(gWin.document.getElementById("next"), {}, gWin); + }); + }, gWin); +} + +function test() { + waitForExplicitFinish(); + + run_next_test(); +} + +function end_test() { + finish(); +} + +// Test for disabling +add_test(function disabling_test() { + setupUI(false, false, function() { + ok(gWin.document.getElementById("incompatible-list").hidden, "Incompatible list should be hidden"); + ok(gWin.document.getElementById("update-list").hidden, "Update list should be hidden"); + + var list = gWin.document.getElementById("disable-list"); + ok(!list.hidden, "Disable list should be visible"); + is(list.childNodes.length, 2, "Should be one add-on getting disabled (plus the header)"); + is(list.childNodes[1].id, "test2@tests.mozilla.org", "Should be the right add-on ID"); + is(list.childNodes[1].getAttribute("name"), "Test Add-on 2", "Should be the right add-on name"); + + var list = gWin.document.getElementById("enable-list"); + ok(!list.hidden, "Enable list should be visible"); + is(list.childNodes.length, 2, "Should be one add-on getting disabled (plus the header)"); + is(list.childNodes[1].id, "test3@tests.mozilla.org", "Should be the right add-on ID"); + is(list.childNodes[1].getAttribute("name"), "Test Add-on 3", "Should be the right add-on name"); + + ok(gWin.document.getElementById("next").hidden, "Next button should be hidden"); + ok(!gWin.document.getElementById("done").hidden, "Done button should be visible"); + gWin.close(); + + run_next_test(); + }); +}); + +// Test for incompatible +add_test(function incompatible_test() { + setupUI(true, false, function() { + ok(gWin.document.getElementById("update-list").hidden, "Update list should be hidden"); + ok(gWin.document.getElementById("disable-list").hidden, "Disable list should be hidden"); + ok(gWin.document.getElementById("enable-list").hidden, "Enable list should be hidden"); + + var list = gWin.document.getElementById("incompatible-list"); + ok(!list.hidden, "Incompatible list should be visible"); + is(list.childNodes.length, 3, "Should be two add-ons waiting to be compatible (plus the header)"); + is(list.childNodes[1].id, "test1@tests.mozilla.org", "Should be the right add-on ID"); + is(list.childNodes[1].getAttribute("name"), "Test Add-on 1", "Should be the right add-on name"); + is(list.childNodes[2].id, "test3@tests.mozilla.org", "Should be the right add-on ID"); + is(list.childNodes[2].getAttribute("name"), "Test Add-on 3", "Should be the right add-on name"); + + ok(gWin.document.getElementById("next").hidden, "Next button should be hidden"); + ok(!gWin.document.getElementById("done").hidden, "Done button should be visible"); + gWin.close(); + + run_next_test(); + }); +}); + +// Test for updates +add_test(function update_test() { + setupUI(false, true, function() { + ok(gWin.document.getElementById("incompatible-list").hidden, "Incompatible list should be hidden"); + ok(gWin.document.getElementById("enable-list").hidden, "Enable list should be hidden"); + + var list = gWin.document.getElementById("update-list"); + ok(!list.hidden, "Update list should be visible"); + is(list.childNodes.length, 3, "Should be two add-ons waiting to be updated (plus the header)"); + is(list.childNodes[1].id, "test1@tests.mozilla.org", "Should be the right add-on ID"); + is(list.childNodes[1].getAttribute("name"), "Test Add-on 1", "Should be the right add-on name"); + is(list.childNodes[2].id, "test3@tests.mozilla.org", "Should be the right add-on ID"); + is(list.childNodes[2].getAttribute("name"), "Test Add-on 3", "Should be the right add-on name"); + + list = gWin.document.getElementById("disable-list"); + ok(!list.hidden, "Disable list should be visible"); + is(list.childNodes.length, 2, "Should be one add-on getting disabled (plus the header)"); + is(list.childNodes[1].id, "test2@tests.mozilla.org", "Should be the right add-on ID"); + is(list.childNodes[1].getAttribute("name"), "Test Add-on 2", "Should be the right add-on name"); + + ok(!gWin.document.getElementById("next").hidden, "Next button should be visible"); + ok(gWin.document.getElementById("done").hidden, "Done button should be hidden"); + gWin.close(); + + run_next_test(); + }); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_select_selection.js b/toolkit/mozapps/extensions/test/browser/browser_select_selection.js new file mode 100644 index 000000000..cf83e7c1e --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_select_selection.js @@ -0,0 +1,268 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests the selection part of the post-app-update dialog + +var gProvider; +var gWin; + +const PROFILE = AddonManager.SCOPE_PROFILE; +const USER = AddonManager.SCOPE_USER; +const APP = AddonManager.SCOPE_APPLICATION; +const SYSTEM = AddonManager.SCOPE_SYSTEM; +const DIST = -1; + +// The matrix of testcases for the selection part of the UI +// Note that the isActive flag has the value it had when the previous version +// of the application ran with this add-on. +var ADDONS = [ + //userDisabled wasAppDisabled isAppDisabled isActive hasUpdate autoUpdate scope defaultKeep position keepString disableString + [false, true, false, false, false, true, PROFILE, true, 42, "enabled", ""], // 0 + [false, true, false, false, true, true, PROFILE, true, 43, "enabled", ""], // 1 + [false, true, false, false, true, false, PROFILE, true, 52, "unneededupdate", ""], // 2 + [false, false, false, true, false, true, PROFILE, true, 53, "", "disabled"], // 3 + [false, false, false, true, true, true, PROFILE, true, 54, "", "disabled"], // 4 + [false, false, false, true, true, false, PROFILE, true, 55, "unneededupdate", "disabled"], // 5 + [false, true, true, false, false, true, PROFILE, true, 56, "incompatible", ""], // 6 + [false, true, true, false, true, true, PROFILE, true, 57, "autoupdate", ""], // 7 + [false, true, true, false, true, false, PROFILE, true, 58, "neededupdate", ""], // 8 + [false, false, true, true, false, true, PROFILE, true, 59, "incompatible", "disabled"], // 9 + [false, true, true, true, true, true, PROFILE, true, 44, "autoupdate", "disabled"], // 10 + [false, true, true, true, true, false, PROFILE, true, 45, "neededupdate", "disabled"], // 11 + [true, false, false, false, false, true, PROFILE, false, 46, "enabled", ""], // 12 + [true, false, false, false, true, true, PROFILE, false, 47, "enabled", ""], // 13 + [true, false, false, false, true, false, PROFILE, false, 48, "unneededupdate", ""], // 14 + + // userDisabled and isActive cannot be true on startup + + [true, true, true, false, false, true, PROFILE, false, 49, "incompatible", ""], // 15 + [true, true, true, false, true, true, PROFILE, false, 50, "autoupdate", ""], // 16 + [true, true, true, false, true, false, PROFILE, false, 51, "neededupdate", ""], // 17 + + // userDisabled and isActive cannot be true on startup + + // Being in a different scope should make little difference except no updates are possible so don't exhaustively test each + [false, false, false, true, true, false, USER, false, 0, "", "disabled"], // 18 + [true, true, false, false, true, false, USER, false, 1, "enabled", ""], // 19 + [false, true, true, true, true, false, USER, false, 2, "incompatible", "disabled"], // 20 + [true, true, true, false, true, false, USER, false, 3, "incompatible", ""], // 21 + [false, false, false, true, true, false, SYSTEM, false, 4, "", "disabled"], // 22 + [true, true, false, false, true, false, SYSTEM, false, 5, "enabled", ""], // 23 + [false, true, true, true, true, false, SYSTEM, false, 6, "incompatible", "disabled"], // 24 + [true, true, true, false, true, false, SYSTEM, false, 7, "incompatible", ""], // 25 + [false, false, false, true, true, false, APP, false, 8, "", "disabled"], // 26 + [true, true, false, false, true, false, APP, false, 9, "enabled", ""], // 27 + [false, true, true, true, true, false, APP, false, 10, "incompatible", "disabled"], // 28 + [true, true, true, false, true, false, APP, false, 11, "incompatible", ""], // 29 +]; + +function waitForView(aView, aCallback) { + var view = gWin.document.getElementById(aView); + if (view.parentNode.selectedPanel == view) { + aCallback(); + return; + } + + view.addEventListener("ViewChanged", function() { + view.removeEventListener("ViewChanged", arguments.callee, false); + aCallback(); + }, false); +} + +function getString(aName) { + if (!aName) + return ""; + + var strings = Services.strings.createBundle("chrome://mozapps/locale/extensions/selectAddons.properties"); + return strings.GetStringFromName("action." + aName); +} + +function getSourceString(aSource) { + if (!aSource) + return ""; + + var strings = Services.strings.createBundle("chrome://mozapps/locale/extensions/selectAddons.properties"); + switch (aSource) { + case PROFILE: + return strings.GetStringFromName("source.profile"); + case DIST: + return strings.GetStringFromName("source.bundled"); + default: + return strings.GetStringFromName("source.other"); + } +} + +function test() { + waitForExplicitFinish(); + + gProvider = new MockProvider(); + + // Set prefs for Distributed Extension Source tests. + Services.prefs.setBoolPref("extensions.installedDistroAddon.test3@tests.mozilla.org", true); + Services.prefs.setBoolPref("extensions.installedDistroAddon.test12@tests.mozilla.org", true); + Services.prefs.setBoolPref("extensions.installedDistroAddon.test15@tests.mozilla.org", true); + + for (let pos in ADDONS) { + let addonItem = ADDONS[pos]; + let addon = new MockAddon("test" + pos + "@tests.mozilla.org", + "Test Add-on " + pos, "extension"); + addon.version = "1.0"; + addon.userDisabled = addonItem[0]; + addon.appDisabled = addonItem[1]; + addon.isActive = addonItem[3]; + addon.applyBackgroundUpdates = addonItem[5] ? AddonManager.AUTOUPDATE_ENABLE + : AddonManager.AUTOUPDATE_DISABLE; + addon.scope = addonItem[6]; + + // Remove the upgrade permission from non-profile add-ons + if (addon.scope != AddonManager.SCOPE_PROFILE) + addon._permissions -= AddonManager.PERM_CAN_UPGRADE; + + addon.findUpdates = function(aListener, aReason, aAppVersion, aPlatformVersion) { + addon.appDisabled = addonItem[2]; + addon.isActive = addon.shouldBeActive; + + if (addonItem[4]) { + var newAddon = new MockAddon(this.id, this.name, "extension"); + newAddon.version = "2.0"; + var install = new MockInstall(this.name, this.type, newAddon); + install.existingAddon = this; + aListener.onUpdateAvailable(this, install); + } + + aListener.onUpdateFinished(this, AddonManager.UPDATE_STATUS_NO_ERROR); + }; + + gProvider.addAddon(addon); + } + + gWin = Services.ww.openWindow(null, + "chrome://mozapps/content/extensions/selectAddons.xul", + "", + "chrome,centerscreen,dialog,titlebar", + null); + waitForFocus(function() { + waitForView("select", run_next_test); + }, gWin); +} + +function end_test() { + gWin.close(); + finish(); +} + +// Minimal test for the checking UI +add_test(function checking_test() { + // By the time we're here the progress bar should be full + var progress = gWin.document.getElementById("checking-progress"); + is(progress.mode, "determined", "Should be a determined progress bar"); + is(progress.value, progress.max, "Should be at full progress"); + + run_next_test(); +}); + +// Tests that the selection UI behaves correctly +add_test(function selection_test() { + function check_state() { + var str = addon[keep.checked ? 9 : 10]; + var expected = getString(str); + var showCheckbox = str == "neededupdate" || str == "unneededupdate"; + is(action.textContent, expected, "Action message should have the right text"); + is(!is_hidden(update), showCheckbox, "Checkbox should have the right visibility"); + is(is_hidden(action), showCheckbox, "Message should have the right visibility"); + if (showCheckbox) + ok(update.checked, "Optional update checkbox should be checked"); + + if (keep.checked) { + is(row.hasAttribute("active"), !addon[2] || hasUpdate, + "Add-on will be active if it isn't appDisabled or an update is available"); + + if (showCheckbox) { + info("Flipping update checkbox"); + EventUtils.synthesizeMouseAtCenter(update, { }, gWin); + is(row.hasAttribute("active"), str == "unneededupdate", + "If the optional update isn't needed then the add-on will still be active"); + + info("Flipping update checkbox"); + EventUtils.synthesizeMouseAtCenter(update, { }, gWin); + is(row.hasAttribute("active"), !addon[2] || hasUpdate, + "Add-on will be active if it isn't appDisabled or an update is available"); + } + } + else { + ok(!row.hasAttribute("active"), "Add-on won't be active when not keeping"); + + if (showCheckbox) { + info("Flipping update checkbox"); + EventUtils.synthesizeMouseAtCenter(update, { }, gWin); + ok(!row.hasAttribute("active"), + "Unchecking the update checkbox shouldn't make the add-on active"); + + info("Flipping update checkbox"); + EventUtils.synthesizeMouseAtCenter(update, { }, gWin); + ok(!row.hasAttribute("active"), + "Re-checking the update checkbox shouldn't make the add-on active"); + } + } + } + + is(gWin.document.getElementById("view-deck").selectedPanel.id, "select", + "Should be on the right view"); + + var pos = 0; + var scrollbox = gWin.document.getElementById("select-scrollbox"); + var scrollBoxObject = scrollbox.boxObject; + for (var row = gWin.document.getElementById("select-rows").firstChild; row; row = row.nextSibling) { + // Ignore separators but increase the position by a large amount so we + // can verify they were in the right place + if (row.localName == "separator") { + pos += 30; + continue; + } + + is(row._addon.type, "extension", "Should only be listing extensions"); + + // Ignore non-test add-ons that may be present + if (row.id.substr(-18) != "@tests.mozilla.org") + continue; + + var id = parseInt(row.id.substring(4, row.id.length - 18)); + var addon = ADDONS[id]; + + info("Testing add-on " + id); + scrollBoxObject.ensureElementIsVisible(row); + var keep = gWin.document.getAnonymousElementByAttribute(row, "anonid", "keep"); + var action = gWin.document.getAnonymousElementByAttribute(row, "class", "addon-action-message"); + var update = gWin.document.getAnonymousElementByAttribute(row, "anonid", "update"); + var source = gWin.document.getAnonymousElementByAttribute(row, "class", "addon-source"); + + if (id == 3 || id == 12 || id == 15) { + // Distro Installed To Profile + is(source.textContent, getSourceString(DIST), "Source message should have the right text for Distributed Addons"); + } else { + is(source.textContent, getSourceString(addon[6]), "Source message should have the right text"); + } + + // Non-profile add-ons don't appear to have updates since we won't install + // them + var hasUpdate = addon[4] && addon[6] == PROFILE; + + is(pos, addon[8], "Should have been in the right position"); + is(keep.checked, addon[7], "Keep checkbox should be in the right state"); + + check_state(); + + info("Flipping keep"); + EventUtils.synthesizeMouseAtCenter(keep, { }, gWin); + is(keep.checked, !addon[7], "Keep checkbox should be in the right state"); + + check_state(); + + pos++; + } + + is(pos, 60, "Should have seen the right number of add-ons"); + + run_next_test(); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_select_update.js b/toolkit/mozapps/extensions/test/browser/browser_select_update.js new file mode 100644 index 000000000..58f1de687 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_select_update.js @@ -0,0 +1,181 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests the update part of the post-app-update dialog + +var gProvider; +var gWin; + +function waitForView(aView, aCallback) { + var view = gWin.document.getElementById(aView); + if (view.parentNode.selectedPanel == view) { + aCallback(); + return; + } + + view.addEventListener("ViewChanged", function() { + view.removeEventListener("ViewChanged", arguments.callee, false); + aCallback(); + }, false); +} + +function waitForClose(aCallback) { + gWin.addEventListener("unload", function() { + gWin.removeEventListener("unload", arguments.callee, false); + + aCallback(); + }, false); +} + +/** + * Creates 4 test add-ons. Two are disabled and two enabled. + */ +function setupUI(aFailDownloads, aFailInstalls, aCallback) { + if (gProvider) + gProvider.unregister(); + + gProvider = new MockProvider(); + + for (var i = 1; i < 5; i++) { + var addon = new MockAddon("test" + i + "@tests.mozilla.org", + "Test Add-on " + i, "extension"); + addon.version = "1.0"; + addon.userDisabled = (i > 2); + addon.appDisabled = false; + addon.isActive = !addon.userDisabled && !addon.appDisabled; + + addon.findUpdates = function(aListener, aReason, aAppVersion, aPlatformVersion) { + var newAddon = new MockAddon(this.id, this.name, "extension"); + newAddon.version = "2.0"; + var install = new MockInstall(this.name, this.type, newAddon); + install.existingAddon = this; + + install.install = function() { + this.state = AddonManager.STATE_DOWNLOADING; + this.callListeners("onDownloadStarted"); + + var self = this; + executeSoon(function() { + if (aFailDownloads) { + self.state = AddonManager.STATE_DOWNLOAD_FAILED; + self.callListeners("onDownloadFailed"); + return; + } + + self.type = self._type; + self.addon = new MockAddon(self.existingAddon.id, self.name, self.type); + self.addon.version = self.version; + self.addon.pendingOperations = AddonManager.PENDING_INSTALL; + self.addon.install = self; + + self.existingAddon.pendingUpgrade = self.addon; + self.existingAddon.pendingOperations |= AddonManager.PENDING_UPGRADE; + + self.state = AddonManager.STATE_DOWNLOADED; + self.callListeners("onDownloadEnded"); + + self.state = AddonManager.STATE_INSTALLING; + self.callListeners("onInstallStarted"); + + if (aFailInstalls) { + self.state = AddonManager.STATE_INSTALL_FAILED; + self.callListeners("onInstallFailed"); + return; + } + + self.state = AddonManager.STATE_INSTALLED; + self.callListeners("onInstallEnded"); + }); + } + + aListener.onUpdateAvailable(this, install); + + aListener.onUpdateFinished(this, AddonManager.UPDATE_STATUS_NO_ERROR); + }; + + gProvider.addAddon(addon); + } + + gWin = Services.ww.openWindow(null, + "chrome://mozapps/content/extensions/selectAddons.xul", + "", + "chrome,centerscreen,dialog,titlebar", + null); + waitForFocus(function() { + waitForView("select", function() { + var row = gWin.document.getElementById("select-rows").firstChild.nextSibling; + while (row) { + if (!row.id || row.id.indexOf("@tests.mozilla.org") < 0) { + // not a test add-on + row = row.nextSibling; + continue; + } + + if (row.id == "test2@tests.mozilla.org" || + row.id == "test4@tests.mozilla.org") { + row.disable(); + } + else { + row.keep(); + } + row = row.nextSibling; + } + + waitForView("confirm", function() { + waitForView("update", aCallback); + EventUtils.synthesizeMouseAtCenter(gWin.document.getElementById("next"), {}, gWin); + }); + EventUtils.synthesizeMouseAtCenter(gWin.document.getElementById("next"), {}, gWin); + }); + }, gWin); +} + +function test() { + waitForExplicitFinish(); + run_next_test(); +} + +function end_test() { + finish(); +} + +// Test for working updates +add_test(function working_test() { + setupUI(false, false, function() { + waitForClose(function() { + is(gWin.document.getElementById("update-progress").value, 2, "Should have finished 2 downloads"); + run_next_test(); + }); + + EventUtils.synthesizeMouseAtCenter(gWin.document.getElementById("next"), {}, gWin); + }); +}); + +// Test for failed updates +add_test(function working_test() { + setupUI(true, false, function() { + waitForView("errors", function() { + is(gWin.document.getElementById("update-progress").value, 2, "Should have finished 2 downloads"); + gWin.close(); + + run_next_test(); + }); + + EventUtils.synthesizeMouseAtCenter(gWin.document.getElementById("next"), {}, gWin); + }); +}); + +// Test for failed updates +add_test(function working_test() { + setupUI(false, true, function() { + waitForView("errors", function() { + is(gWin.document.getElementById("update-progress").value, 2, "Should have finished 2 downloads"); + gWin.close(); + + run_next_test(); + }); + + EventUtils.synthesizeMouseAtCenter(gWin.document.getElementById("next"), {}, gWin); + }); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_sorting.js b/toolkit/mozapps/extensions/test/browser/browser_sorting.js index b57e7a6f7..7bf697b36 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_sorting.js +++ b/toolkit/mozapps/extensions/test/browser/browser_sorting.js @@ -21,15 +21,15 @@ function test() { id: "test1@tests.mozilla.org", name: "Test add-on", description: "foo", - updateDate: new Date(2010, 4, 2, 0, 0, 0), + updateDate: new Date(2010, 04, 02, 00, 00, 00), size: 1, pendingOperations: AddonManager.PENDING_NONE, }, { id: "test2@tests.mozilla.org", name: "a first add-on", description: "foo", - updateDate: new Date(2010, 4, 1, 23, 59, 59), - size: 265, + updateDate: new Date(2010, 04, 01, 23, 59, 59), + size: 0265, pendingOperations: AddonManager.PENDING_UPGRADE, isActive: true, isCompatible: false, @@ -37,21 +37,21 @@ function test() { id: "test3@tests.mozilla.org", name: "\u010Cesk\u00FD slovn\u00EDk", // Český slovník description: "foo", - updateDate: new Date(2010, 4, 2, 0, 0, 1), + updateDate: new Date(2010, 04, 02, 00, 00, 01), size: 12, pendingOperations: AddonManager.PENDING_INSTALL, isActive: false, }, { id: "test4@tests.mozilla.org", name: "canadian dictionary", - updateDate: new Date(1970, 0, 1, 0, 0, 0), + updateDate: new Date(1970, 0, 01, 00, 00, 00), description: "foo", isActive: true, }, { id: "test5@tests.mozilla.org", name: "croatian dictionary", description: "foo", - updateDate: new Date(2012, 12, 12, 0, 0, 0), + updateDate: new Date(2012, 12, 12, 00, 00, 00), size: 5, pendingOperations: AddonManager.PENDING_ENABLE, isActive: false, @@ -61,7 +61,7 @@ function test() { id: "test6@tests.mozilla.org", name: "orange Add-on", description: "foo", - updateDate: new Date(2010, 4, 2, 0, 0, 0), + updateDate: new Date(2010, 04, 02, 00, 00, 00), size: 142, isCompatible: false, isActive: true, @@ -70,7 +70,7 @@ function test() { id: "test7@tests.mozilla.org", name: "Blue Add-on", description: "foo", - updateDate: new Date(2010, 4, 1, 23, 59, 59), + updateDate: new Date(2010, 04, 01, 23, 59, 59), size: 65, isActive: true, pendingOperations: AddonManager.PENDING_DISABLE, @@ -78,13 +78,13 @@ function test() { id: "test8@tests.mozilla.org", name: "Green Add-on", description: "foo", - updateDate: new Date(2010, 4, 3, 0, 0, 1), + updateDate: new Date(2010, 04, 03, 00, 00, 01), size: 125, pendingOperations: AddonManager.PENDING_DISABLE, }, { id: "test9@tests.mozilla.org", name: "red Add-on", - updateDate: new Date(2011, 4, 1, 0, 0, 0), + updateDate: new Date(2011, 04, 01, 00, 00, 00), description: "foo", isCompatible: false, pendingOperations: AddonManager.PENDING_DISABLE, @@ -92,7 +92,7 @@ function test() { id: "test10@tests.mozilla.org", name: "Purple Add-on", description: "foo", - updateDate: new Date(2012, 12, 12, 0, 0, 0), + updateDate: new Date(2012, 12, 12, 00, 00, 00), size: 56, isCompatible: false, pendingOperations: AddonManager.PENDING_DISABLE, @@ -102,7 +102,7 @@ function test() { id: "test11@tests.mozilla.org", name: "amber Add-on", description: "foo", - updateDate: new Date(1978, 4, 2, 0, 0, 0), + updateDate: new Date(1978, 04, 02, 00, 00, 00), size: 142, isActive: false, appDisabled: true, @@ -111,7 +111,7 @@ function test() { id: "test12@tests.mozilla.org", name: "Salmon Add-on - pending disable", description: "foo", - updateDate: new Date(2054, 4, 1, 23, 59, 59), + updateDate: new Date(2054, 04, 01, 23, 59, 59), size: 65, isActive: true, pendingOperations: AddonManager.PENDING_UNINSTALL, @@ -119,7 +119,7 @@ function test() { id: "test13@tests.mozilla.org", name: "rose Add-on", description: "foo", - updateDate: new Date(2010, 4, 2, 0, 0, 1), + updateDate: new Date(2010, 04, 02, 00, 00, 01), size: 125, isActive: false, userDisabled: true, @@ -127,7 +127,7 @@ function test() { }, { id: "test14@tests.mozilla.org", name: "Violet Add-on", - updateDate: new Date(2010, 5, 1, 0, 0, 0), + updateDate: new Date(2010, 05, 01, 00, 00, 00), description: "foo", isActive: false, appDisabled: true, @@ -136,7 +136,7 @@ function test() { id: "test15@tests.mozilla.org", name: "white Add-on", description: "foo", - updateDate: new Date(2010, 4, 12, 0, 0, 0), + updateDate: new Date(2010, 04, 12, 00, 00, 00), size: 56, isActive: false, userDisabled: true, @@ -149,7 +149,7 @@ function test() { id: "test16@tests.mozilla.org", name: "grimsby Add-on", description: "foo", - updateDate: new Date(2010, 4, 1, 0, 0, 0), + updateDate: new Date(2010, 04, 01, 00, 00, 00), size: 142, isActive: false, appDisabled: true, @@ -157,7 +157,7 @@ function test() { id: "test17@tests.mozilla.org", name: "beamsville Add-on", description: "foo", - updateDate: new Date(2010, 4, 8, 23, 59, 59), + updateDate: new Date(2010, 04, 8, 23, 59, 59), size: 65, isActive: false, userDisabled: true, @@ -165,7 +165,7 @@ function test() { id: "test18@tests.mozilla.org", name: "smithville Add-on", description: "foo", - updateDate: new Date(2010, 4, 3, 0, 0, 1), + updateDate: new Date(2010, 04, 03, 00, 00, 01), size: 125, isActive: false, userDisabled: true, @@ -173,7 +173,7 @@ function test() { }, { id: "test19@tests.mozilla.org", name: "dunnville Add-on", - updateDate: new Date(2010, 4, 2, 0, 0, 0), + updateDate: new Date(2010, 04, 02, 00, 00, 00), description: "foo", isActive: false, appDisabled: true, @@ -183,7 +183,7 @@ function test() { id: "test20@tests.mozilla.org", name: "silverdale Add-on", description: "foo", - updateDate: new Date(2010, 4, 12, 0, 0, 0), + updateDate: new Date(2010, 04, 12, 00, 00, 00), size: 56, isActive: false, appDisabled: true, diff --git a/toolkit/mozapps/extensions/test/browser/browser_system_addons_are_e10s.js b/toolkit/mozapps/extensions/test/browser/browser_system_addons_are_e10s.js deleted file mode 100644 index 37ab76542..000000000 --- a/toolkit/mozapps/extensions/test/browser/browser_system_addons_are_e10s.js +++ /dev/null @@ -1,13 +0,0 @@ -"use strict"; - -add_task(function* test_enabled() { - let addons = yield new Promise(resolved => AddonManager.getAllAddons(resolved)); - for (let addon of addons) { - if (addon.isSystem) { - ok(addon.multiprocessCompatible, - `System addon ${addon.id} is not marked as multiprocess compatible`); - ok(!addon.unpack, - `System add-on ${addon.id} isn't a packed add-on.`); - } - } -}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_uninstalling.js b/toolkit/mozapps/extensions/test/browser/browser_uninstalling.js index a9329e496..9fcb9de66 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_uninstalling.js +++ b/toolkit/mozapps/extensions/test/browser/browser_uninstalling.js @@ -117,7 +117,7 @@ add_test(function() { ok(!!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should be pending uninstall"); - button = gDocument.getAnonymousElementByAttribute(item, "anonid", "restart-btn"); + var button = gDocument.getAnonymousElementByAttribute(item, "anonid", "restart-btn"); isnot(button, null, "Should have a restart button"); ok(!button.hidden, "Restart button should not be hidden"); button = gDocument.getAnonymousElementByAttribute(item, "anonid", "undo-btn"); @@ -128,7 +128,7 @@ add_test(function() { // Force XBL to apply item.clientTop; - ok(!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should not be pending uninstall"); + ok(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL, "Add-on should be pending uninstall"); button = gDocument.getAnonymousElementByAttribute(item, "anonid", "remove-btn"); isnot(button, null, "Should have a remove button"); ok(!button.disabled, "Button should not be disabled"); @@ -166,10 +166,10 @@ add_test(function() { is(item.getAttribute("pending"), "uninstall", "Add-on should be uninstalling"); - ok(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL, "Add-on should be pending uninstall"); + ok(!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should not be pending uninstall"); ok(!aAddon.isActive, "Add-on should be inactive"); - button = gDocument.getAnonymousElementByAttribute(item, "anonid", "restart-btn"); + var button = gDocument.getAnonymousElementByAttribute(item, "anonid", "restart-btn"); isnot(button, null, "Should have a restart button"); ok(button.hidden, "Restart button should be hidden"); button = gDocument.getAnonymousElementByAttribute(item, "anonid", "undo-btn"); @@ -224,7 +224,7 @@ add_test(function() { ok(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL, "Add-on should be pending uninstall"); ok(!aAddon.isActive, "Add-on should be inactive"); - button = gDocument.getAnonymousElementByAttribute(item, "anonid", "restart-btn"); + var button = gDocument.getAnonymousElementByAttribute(item, "anonid", "restart-btn"); isnot(button, null, "Should have a restart button"); ok(button.hidden, "Restart button should be hidden"); button = gDocument.getAnonymousElementByAttribute(item, "anonid", "undo-btn"); @@ -285,7 +285,7 @@ add_test(function() { ok(!!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should be pending uninstall"); - button = gDocument.getAnonymousElementByAttribute(item, "anonid", "restart-btn"); + var button = gDocument.getAnonymousElementByAttribute(item, "anonid", "restart-btn"); isnot(button, null, "Should have a restart button"); ok(!button.hidden, "Restart button should not be hidden"); button = gDocument.getAnonymousElementByAttribute(item, "anonid", "undo-btn"); @@ -345,7 +345,7 @@ add_test(function() { ok(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL, "Add-on should be pending uninstall"); ok(!aAddon.isActive, "Add-on should be inactive"); - button = gDocument.getAnonymousElementByAttribute(item, "anonid", "restart-btn"); + var button = gDocument.getAnonymousElementByAttribute(item, "anonid", "restart-btn"); isnot(button, null, "Should have a restart button"); ok(button.hidden, "Restart button should be hidden"); button = gDocument.getAnonymousElementByAttribute(item, "anonid", "undo-btn"); @@ -408,7 +408,7 @@ add_test(function() { ok(!!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should be pending uninstall"); ok(!aAddon.isActive, "Add-on should be inactive"); - button = gDocument.getAnonymousElementByAttribute(item, "anonid", "restart-btn"); + var button = gDocument.getAnonymousElementByAttribute(item, "anonid", "restart-btn"); isnot(button, null, "Should have a restart button"); ok(button.hidden, "Restart button should be hidden"); button = gDocument.getAnonymousElementByAttribute(item, "anonid", "undo-btn"); @@ -452,7 +452,7 @@ add_test(function() { EventUtils.synthesizeMouseAtCenter(item, { clickCount: 1 }, gManagerWindow); EventUtils.synthesizeMouseAtCenter(item, { clickCount: 2 }, gManagerWindow); wait_for_view_load(gManagerWindow, function() { - is(get_current_view(gManagerWindow).id, "detail-view", "Should be in the detail view"); + is(gDocument.getElementById("view-port").selectedPanel.id, "detail-view", "Should be in the detail view"); var button = gDocument.getElementById("detail-uninstall-btn"); isnot(button, null, "Should have a remove button"); @@ -516,7 +516,7 @@ add_test(function() { EventUtils.synthesizeMouseAtCenter(item, { clickCount: 1 }, gManagerWindow); EventUtils.synthesizeMouseAtCenter(item, { clickCount: 2 }, gManagerWindow); wait_for_view_load(gManagerWindow, function() { - is(get_current_view(gManagerWindow).id, "detail-view", "Should be in the detail view"); + is(gDocument.getElementById("view-port").selectedPanel.id, "detail-view", "Should be in the detail view"); var button = gDocument.getElementById("detail-uninstall-btn"); isnot(button, null, "Should have a remove button"); @@ -583,7 +583,7 @@ add_test(function() { EventUtils.synthesizeMouseAtCenter(item, { clickCount: 1 }, gManagerWindow); EventUtils.synthesizeMouseAtCenter(item, { clickCount: 2 }, gManagerWindow); wait_for_view_load(gManagerWindow, function() { - is(get_current_view(gManagerWindow).id, "detail-view", "Should be in the detail view"); + is(gDocument.getElementById("view-port").selectedPanel.id, "detail-view", "Should be in the detail view"); var button = gDocument.getElementById("detail-uninstall-btn"); isnot(button, null, "Should have a remove button"); @@ -659,7 +659,7 @@ add_test(function() { ok(!!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should be pending uninstall"); - button = gDocument.getAnonymousElementByAttribute(item, "anonid", "restart-btn"); + var button = gDocument.getAnonymousElementByAttribute(item, "anonid", "restart-btn"); isnot(button, null, "Should have a restart button"); ok(!button.hidden, "Restart button should not be hidden"); button = gDocument.getAnonymousElementByAttribute(item, "anonid", "undo-btn"); @@ -808,6 +808,7 @@ add_test(function() { item.clientTop; is(item.getAttribute("pending"), "uninstall", "Add-on should be uninstalling"); + ok(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL, "Add-on should be pending uninstall"); ok(!aAddon.isActive, "Add-on should be inactive"); @@ -1048,7 +1049,7 @@ add_test(function() { ok(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL, "Add-on should be pending uninstall"); ok(!aAddon.isActive, "Add-on should be inactive"); - button = gDocument.getAnonymousElementByAttribute(item, "anonid", "restart-btn"); + var button = gDocument.getAnonymousElementByAttribute(item, "anonid", "restart-btn"); isnot(button, null, "Should have a restart button"); ok(button.hidden, "Restart button should be hidden"); button = gDocument.getAnonymousElementByAttribute(item, "anonid", "undo-btn"); @@ -1068,7 +1069,7 @@ add_test(function() { is(aAddon, null, "Add-on should no longer be installed"); is(aAddon2, null, "Second add-on should no longer be installed"); - open_manager("addons://list/extension", function(aWindow) { + open_manager(null, function(aWindow) { gManagerWindow = aWindow; gDocument = gManagerWindow.document; gCategoryUtilities = new CategoryUtilities(gManagerWindow); diff --git a/toolkit/mozapps/extensions/test/browser/browser_update.js b/toolkit/mozapps/extensions/test/browser/browser_update.js deleted file mode 100644 index 09ceb1240..000000000 --- a/toolkit/mozapps/extensions/test/browser/browser_update.js +++ /dev/null @@ -1,53 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -// Tests that updates correctly flush caches and that new files gets updated. - -function test() { - requestLongerTimeout(2); - waitForExplicitFinish(); - - Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); - - run_next_test(); -} - -// Install a first version -add_test(function() { - AddonManager.getInstallForURL(TESTROOT + "addons/browser_update1_1.xpi", - function(aInstall) { - aInstall.install(); - }, "application/x-xpinstall"); - - Services.ppmm.addMessageListener("my-addon-1", function messageListener() { - Services.ppmm.removeMessageListener("my-addon-1", messageListener); - ok(true, "first version sent frame script message"); - run_next_test(); - }); -}); - -// Update to a second version and verify that content gets updated -add_test(function() { - AddonManager.getInstallForURL(TESTROOT + "addons/browser_update1_2.xpi", - function(aInstall) { - aInstall.install(); - }, "application/x-xpinstall"); - - Services.ppmm.addMessageListener("my-addon-2", function messageListener() { - Services.ppmm.removeMessageListener("my-addon-2", messageListener); - ok(true, "second version sent frame script message"); - run_next_test(); - }); -}); - -// Finally, cleanup things -add_test(function() { - Services.prefs.setBoolPref("xpinstall.signatures.required", true); - - AddonManager.getAddonByID("update1@tests.mozilla.org", function(aAddon) { - aAddon.uninstall(); - - finish(); - }); -}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_updateid.js b/toolkit/mozapps/extensions/test/browser/browser_updateid.js index 0fe3eeec5..a6672e825 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_updateid.js +++ b/toolkit/mozapps/extensions/test/browser/browser_updateid.js @@ -49,20 +49,16 @@ add_test(function() { gProvider.installs[0]._addonToInstall = newAddon; var item = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); + is(item._version.value, "1.0", "Should still show the old version in the normal list"); var name = gManagerWindow.document.getAnonymousElementByAttribute(item, "anonid", "name"); is(name.value, "manually updating addon", "Should show the old name in the list"); - get_tooltip_info(item).then(({ name, version }) => { - is(name, "manually updating addon", "Should show the old name in the tooltip"); - is(version, "1.0", "Should still show the old version in the tooltip"); + var update = gManagerWindow.document.getAnonymousElementByAttribute(item, "anonid", "update-btn"); + is_element_visible(update, "Update button should be visible"); - var update = gManagerWindow.document.getAnonymousElementByAttribute(item, "anonid", "update-btn"); - is_element_visible(update, "Update button should be visible"); + item = get_addon_element(gManagerWindow, "addon2@tests.mozilla.org"); + is(item, null, "Should not show the new version in the list"); - item = get_addon_element(gManagerWindow, "addon2@tests.mozilla.org"); - is(item, null, "Should not show the new version in the list"); - - run_next_test(); - }); + run_next_test(); }); }); diff --git a/toolkit/mozapps/extensions/test/browser/browser_updatessl.js b/toolkit/mozapps/extensions/test/browser/browser_updatessl.js index 8b816c927..7a9149aa5 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_updatessl.js +++ b/toolkit/mozapps/extensions/test/browser/browser_updatessl.js @@ -2,9 +2,9 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -var tempScope = {}; +let tempScope = {}; Components.utils.import("resource://gre/modules/addons/AddonUpdateChecker.jsm", tempScope); -var AddonUpdateChecker = tempScope.AddonUpdateChecker; +let AddonUpdateChecker = tempScope.AddonUpdateChecker; const updaterdf = RELATIVE_DIR + "browser_updatessl.rdf"; const redirect = RELATIVE_DIR + "redirect.sjs?"; diff --git a/toolkit/mozapps/extensions/test/browser/browser_webapi.js b/toolkit/mozapps/extensions/test/browser/browser_webapi.js deleted file mode 100644 index ca8e41aad..000000000 --- a/toolkit/mozapps/extensions/test/browser/browser_webapi.js +++ /dev/null @@ -1,106 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -const TESTPAGE = `${SECURE_TESTROOT}webapi_checkavailable.html`; - -Services.prefs.setBoolPref("extensions.webapi.testing", true); -registerCleanupFunction(() => { - Services.prefs.clearUserPref("extensions.webapi.testing"); -}); - -function testWithAPI(task) { - return function*() { - yield BrowserTestUtils.withNewTab(TESTPAGE, task); - } -} - -let gProvider = new MockProvider(); - -let addons = gProvider.createAddons([{ - id: "addon1@tests.mozilla.org", - name: "Test add-on 1", - version: "2.1", - description: "Short description", - type: "extension", - userDisabled: false, - isActive: true, -}, { - id: "addon2@tests.mozilla.org", - name: "Test add-on 2", - version: "5.3.7ab", - description: null, - type: "theme", - userDisabled: false, - isActive: false, -}, { - id: "addon3@tests.mozilla.org", - name: "Test add-on 3", - version: "1", - description: "Longer description", - type: "extension", - userDisabled: true, - isActive: false, -}, { - id: "addon4@tests.mozilla.org", - name: "Test add-on 4", - version: "1", - description: "Longer description", - type: "extension", - userDisabled: false, - isActive: true, -}]); - -addons[3].permissions &= ~AddonManager.PERM_CAN_UNINSTALL; - -function API_getAddonByID(browser, id) { - return ContentTask.spawn(browser, id, function*(id) { - let addon = yield content.navigator.mozAddonManager.getAddonByID(id); - - // We can't send native objects back so clone its properties. - let result = {}; - for (let prop in addon) { - result[prop] = addon[prop]; - } - - return result; - }); -} - -add_task(testWithAPI(function*(browser) { - function compareObjects(web, real) { - for (let prop of Object.keys(web)) { - let webVal = web[prop]; - let realVal = real[prop]; - - switch (prop) { - case "isEnabled": - realVal = !real.userDisabled; - break; - - case "canUninstall": - realVal = Boolean(real.permissions & AddonManager.PERM_CAN_UNINSTALL); - break; - } - - // null and undefined don't compare well so stringify them first - if (realVal === null || realVal === undefined) { - realVal = `${realVal}`; - webVal = `${webVal}`; - } - - is(webVal, realVal, `Property ${prop} should have the right value in add-on ${real.id}`); - } - } - - let [a1, a2, a3] = yield promiseAddonsByIDs(["addon1@tests.mozilla.org", - "addon2@tests.mozilla.org", - "addon3@tests.mozilla.org"]); - let w1 = yield API_getAddonByID(browser, "addon1@tests.mozilla.org"); - let w2 = yield API_getAddonByID(browser, "addon2@tests.mozilla.org"); - let w3 = yield API_getAddonByID(browser, "addon3@tests.mozilla.org"); - - compareObjects(w1, a1); - compareObjects(w2, a2); - compareObjects(w3, a3); -})); diff --git a/toolkit/mozapps/extensions/test/browser/browser_webapi_access.js b/toolkit/mozapps/extensions/test/browser/browser_webapi_access.js deleted file mode 100644 index f4b1dc745..000000000 --- a/toolkit/mozapps/extensions/test/browser/browser_webapi_access.js +++ /dev/null @@ -1,127 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -registerCleanupFunction(() => { - Services.prefs.clearUserPref("extensions.webapi.testing"); -}); - -function check_frame_availability(browser) { - return ContentTask.spawn(browser, null, function*() { - let frame = content.document.getElementById("frame"); - return frame.contentWindow.document.getElementById("result").textContent == "true"; - }); -} - -function check_availability(browser) { - return ContentTask.spawn(browser, null, function*() { - return content.document.getElementById("result").textContent == "true"; - }); -} - -// Test that initially the API isn't available in the test domain -add_task(function* test_not_available() { - yield BrowserTestUtils.withNewTab(`${SECURE_TESTROOT}webapi_checkavailable.html`, - function* test_not_available(browser) { - let available = yield check_availability(browser); - ok(!available, "API should not be available."); - }) -}); - -// Test that with testing on the API is available in the test domain -add_task(function* test_available() { - Services.prefs.setBoolPref("extensions.webapi.testing", true); - - yield BrowserTestUtils.withNewTab(`${SECURE_TESTROOT}webapi_checkavailable.html`, - function* test_not_available(browser) { - let available = yield check_availability(browser); - ok(available, "API should be available."); - }) -}); - -// Test that the API is not available in a bad domain -add_task(function* test_bad_domain() { - yield BrowserTestUtils.withNewTab(`${SECURE_TESTROOT2}webapi_checkavailable.html`, - function* test_not_available(browser) { - let available = yield check_availability(browser); - ok(!available, "API should not be available."); - }) -}); - -// Test that the API is only available in https sites -add_task(function* test_not_available_http() { - yield BrowserTestUtils.withNewTab(`${TESTROOT}webapi_checkavailable.html`, - function* test_not_available(browser) { - let available = yield check_availability(browser); - ok(!available, "API should not be available."); - }) -}); - -// Test that the API is available when in a frame of the test domain -add_task(function* test_available_framed() { - yield BrowserTestUtils.withNewTab(`${SECURE_TESTROOT}webapi_checkframed.html`, - function* test_available(browser) { - let available = yield check_frame_availability(browser); - ok(available, "API should be available."); - }) -}); - -// Test that if the external frame is http then the inner frame doesn't have -// the API -add_task(function* test_not_available_http_framed() { - yield BrowserTestUtils.withNewTab(`${TESTROOT}webapi_checkframed.html`, - function* test_not_available(browser) { - let available = yield check_frame_availability(browser); - ok(!available, "API should not be available."); - }) -}); - -// Test that if the external frame is a bad domain then the inner frame doesn't -// have the API -add_task(function* test_not_available_framed() { - yield BrowserTestUtils.withNewTab(`${SECURE_TESTROOT2}webapi_checkframed.html`, - function* test_not_available(browser) { - let available = yield check_frame_availability(browser); - ok(!available, "API should not be available."); - }) -}); - -// Test that a window navigated to a bad domain doesn't allow access to the API -add_task(function* test_navigated_window() { - yield BrowserTestUtils.withNewTab(`${SECURE_TESTROOT2}webapi_checknavigatedwindow.html`, - function* test_available(browser) { - let tabPromise = BrowserTestUtils.waitForNewTab(gBrowser); - - yield ContentTask.spawn(browser, null, function*() { - yield content.wrappedJSObject.openWindow(); - }); - - // Should be a new tab open - let tab = yield tabPromise; - let loadPromise = BrowserTestUtils.browserLoaded(gBrowser.getBrowserForTab(tab)); - - ContentTask.spawn(browser, null, function*() { - content.wrappedJSObject.navigate(); - }); - - yield loadPromise; - - let available = yield ContentTask.spawn(browser, null, function*() { - return content.wrappedJSObject.check(); - }); - - ok(!available, "API should not be available."); - - gBrowser.removeTab(tab); - }) -}); - -// Check that if a page is embedded in a chrome content UI that it can still -// access the API. -add_task(function* test_chrome_frame() { - yield BrowserTestUtils.withNewTab(`${CHROMEROOT}webapi_checkchromeframe.xul`, - function* test_available(browser) { - let available = yield check_frame_availability(browser); - ok(available, "API should be available."); - }) -}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_webapi_addon_listener.js b/toolkit/mozapps/extensions/test/browser/browser_webapi_addon_listener.js deleted file mode 100644 index b8049f13c..000000000 --- a/toolkit/mozapps/extensions/test/browser/browser_webapi_addon_listener.js +++ /dev/null @@ -1,174 +0,0 @@ -const TESTPAGE = `${SECURE_TESTROOT}webapi_addon_listener.html`; - -Services.prefs.setBoolPref("extensions.webapi.testing", true); -registerCleanupFunction(() => { - Services.prefs.clearUserPref("extensions.webapi.testing"); -}); - - -function* getListenerEvents(browser) { - let result = yield ContentTask.spawn(browser, null, function*() { - return content.document.getElementById("result").textContent; - }); - - return result.split('\n').map(JSON.parse); -} - -const RESTART_ID = "restart@tests.mozilla.org"; -const RESTART_DISABLED_ID = "restart_disabled@tests.mozilla.org"; -const RESTARTLESS_ID = "restartless@tests.mozilla.org"; -const INSTALL_ID = "install@tests.mozilla.org"; -const CANCEL_ID = "cancel@tests.mozilla.org"; - -let provider = new MockProvider(false); -provider.createAddons([ - { - id: RESTART_ID, - name: "Add-on that requires restart", - }, - { - id: RESTART_DISABLED_ID, - name: "Disabled add-on that requires restart", - userDisabled: true, - }, - { - id: RESTARTLESS_ID, - name: "Restartless add-on", - operationsRequiringRestart: AddonManager.OP_NEED_RESTART_NONE, - }, - { - id: CANCEL_ID, - name: "Add-on for uninstall cancel", - }, -]); - -// Test disable of add-on requiring restart -add_task(function* test_disable() { - yield BrowserTestUtils.withNewTab(TESTPAGE, function*(browser) { - let addon = yield promiseAddonByID(RESTART_ID); - is(addon.userDisabled, false, "addon is enabled"); - - // disable it - addon.userDisabled = true; - is(addon.userDisabled, true, "addon was disabled successfully"); - - let events = yield getListenerEvents(browser); - - // Just a single onDisabling since restart is needed to complete - let expected = [ - {id: RESTART_ID, needsRestart: true, event: "onDisabling"}, - ]; - Assert.deepEqual(events, expected, "Got expected disable event"); - }); -}); - -// Test enable of add-on requiring restart -add_task(function* test_enable() { - yield BrowserTestUtils.withNewTab(TESTPAGE, function*(browser) { - let addon = yield promiseAddonByID(RESTART_DISABLED_ID); - is(addon.userDisabled, true, "addon is disabled"); - - // enable it - addon.userDisabled = false; - is(addon.userDisabled, false, "addon was enabled successfully"); - - let events = yield getListenerEvents(browser); - - // Just a single onEnabling since restart is needed to complete - let expected = [ - {id: RESTART_DISABLED_ID, needsRestart: true, event: "onEnabling"}, - ]; - Assert.deepEqual(events, expected, "Got expected enable event"); - }); -}); - -// Test enable/disable events for restartless -add_task(function* test_restartless() { - yield BrowserTestUtils.withNewTab(TESTPAGE, function*(browser) { - let addon = yield promiseAddonByID(RESTARTLESS_ID); - is(addon.userDisabled, false, "addon is enabled"); - - // disable it - addon.userDisabled = true; - is(addon.userDisabled, true, "addon was disabled successfully"); - - // re-enable it - addon.userDisabled = false; - is(addon.userDisabled, false, "addon was re-enabled successfuly"); - - let events = yield getListenerEvents(browser); - let expected = [ - {id: RESTARTLESS_ID, needsRestart: false, event: "onDisabling"}, - {id: RESTARTLESS_ID, needsRestart: false, event: "onDisabled"}, - {id: RESTARTLESS_ID, needsRestart: false, event: "onEnabling"}, - {id: RESTARTLESS_ID, needsRestart: false, event: "onEnabled"}, - ]; - Assert.deepEqual(events, expected, "Got expected disable/enable events"); - }); -}); - -// Test install events -add_task(function* test_restartless() { - yield BrowserTestUtils.withNewTab(TESTPAGE, function*(browser) { - let addon = new MockAddon(INSTALL_ID, "installme", null, - AddonManager.OP_NEED_RESTART_NONE); - let install = new MockInstall(null, null, addon); - - let installPromise = new Promise(resolve => { - install.addTestListener({ - onInstallEnded: resolve, - }); - }); - - provider.addInstall(install); - install.install(); - - yield installPromise; - - let events = yield getListenerEvents(browser); - let expected = [ - {id: INSTALL_ID, needsRestart: false, event: "onInstalling"}, - {id: INSTALL_ID, needsRestart: false, event: "onInstalled"}, - ]; - Assert.deepEqual(events, expected, "Got expected install events"); - }); -}); - -// Test uninstall -add_task(function* test_uninstall() { - yield BrowserTestUtils.withNewTab(TESTPAGE, function*(browser) { - let addon = yield promiseAddonByID(RESTARTLESS_ID); - isnot(addon, null, "Found add-on for uninstall"); - - addon.uninstall(); - - let events = yield getListenerEvents(browser); - let expected = [ - {id: RESTARTLESS_ID, needsRestart: false, event: "onUninstalling"}, - {id: RESTARTLESS_ID, needsRestart: false, event: "onUninstalled"}, - ]; - Assert.deepEqual(events, expected, "Got expected uninstall events"); - }); -}); - -// Test cancel of uninstall. -add_task(function* test_cancel() { - yield BrowserTestUtils.withNewTab(TESTPAGE, function*(browser) { - let addon = yield promiseAddonByID(CANCEL_ID); - isnot(addon, null, "Found add-on for cancelling uninstall"); - - addon.uninstall(); - - let events = yield getListenerEvents(browser); - let expected = [ - {id: CANCEL_ID, needsRestart: true, event: "onUninstalling"}, - ]; - Assert.deepEqual(events, expected, "Got expected uninstalling event"); - - addon.cancelUninstall(); - events = yield getListenerEvents(browser); - expected.push({id: CANCEL_ID, needsRestart: false, event: "onOperationCancelled"}); - Assert.deepEqual(events, expected, "Got expected cancel event"); - }); -}); - diff --git a/toolkit/mozapps/extensions/test/browser/browser_webapi_enable.js b/toolkit/mozapps/extensions/test/browser/browser_webapi_enable.js deleted file mode 100644 index 27d8029c5..000000000 --- a/toolkit/mozapps/extensions/test/browser/browser_webapi_enable.js +++ /dev/null @@ -1,62 +0,0 @@ -const TESTPAGE = `${SECURE_TESTROOT}webapi_addon_listener.html`; - -Services.prefs.setBoolPref("extensions.webapi.testing", true); -registerCleanupFunction(() => { - Services.prefs.clearUserPref("extensions.webapi.testing"); -}); - -function* getListenerEvents(browser) { - let result = yield ContentTask.spawn(browser, null, function*() { - return content.document.getElementById("result").textContent; - }); - - return result.split('\n').map(JSON.parse); -} - -const ID = "test@tests.mozilla.org"; - -let provider = new MockProvider(false); -provider.createAddons([ - { - id: ID, - name: "Test add-on", - operationsRequiringRestart: AddonManager.OP_NEED_RESTART_NONE, - }, -]); - -// Test disable and enable from content -add_task(function* () { - yield BrowserTestUtils.withNewTab(TESTPAGE, function*(browser) { - let addon = yield promiseAddonByID(ID); - isnot(addon, null, "Test addon exists"); - is(addon.userDisabled, false, "addon is enabled"); - - // Disable the addon from content. - yield ContentTask.spawn(browser, null, function* () { - return content.navigator.mozAddonManager - .getAddonByID("test@tests.mozilla.org") - .then(addon => { addon.setEnabled(false); }); - }); - - let events = yield getListenerEvents(browser); - let expected = [ - {id: ID, needsRestart: false, event: "onDisabling"}, - {id: ID, needsRestart: false, event: "onDisabled"}, - ]; - Assert.deepEqual(events, expected, "Got expected disable events"); - - // Enable the addon from content. - yield ContentTask.spawn(browser, null, function* () { - return content.navigator.mozAddonManager - .getAddonByID("test@tests.mozilla.org") - .then(addon => { addon.setEnabled(true); }); - }); - - events = yield getListenerEvents(browser); - expected = expected.concat([ - {id: ID, needsRestart: false, event: "onEnabling"}, - {id: ID, needsRestart: false, event: "onEnabled"}, - ]); - Assert.deepEqual(events, expected, "Got expected enable events"); - }); -}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_webapi_install.js b/toolkit/mozapps/extensions/test/browser/browser_webapi_install.js deleted file mode 100644 index bc31c2331..000000000 --- a/toolkit/mozapps/extensions/test/browser/browser_webapi_install.js +++ /dev/null @@ -1,311 +0,0 @@ -const TESTPAGE = `${SECURE_TESTROOT}webapi_checkavailable.html`; -const XPI_URL = `${SECURE_TESTROOT}addons/browser_webapi_install.xpi`; -const XPI_SHA = "sha256:d4bab17ff9ba5f635e97c84021f4c527c502250d62ab7f6e6c9e8ee28822f772"; - -const ID = "webapi_install@tests.mozilla.org"; -// eh, would be good to just stat the real file instead of this... -const XPI_LEN = 4782; - -function waitForClear() { - const MSG = "WebAPICleanup"; - return new Promise(resolve => { - let listener = { - receiveMessage: function(msg) { - if (msg.name == MSG) { - Services.mm.removeMessageListener(MSG, listener); - resolve(); - } - } - }; - - Services.mm.addMessageListener(MSG, listener, true); - }); -} - -add_task(function* setup() { - yield SpecialPowers.pushPrefEnv({ - set: [["extensions.webapi.testing", true], - ["extensions.install.requireBuiltInCerts", false]], - }); - info("added preferences"); -}); - -// Wrapper around a common task to run in the content process to test -// the mozAddonManager API. Takes a URL for the XPI to install and an -// array of steps, each of which can either be an action to take -// (i.e., start or cancel the install) or an install event to wait for. -// Steps that look for a specific event may also include a "props" property -// with properties that the AddonInstall object is expected to have when -// that event is triggered. -function* testInstall(browser, args, steps, description) { - let success = yield ContentTask.spawn(browser, {args, steps}, function* (opts) { - let { args, steps } = opts; - let install = yield content.navigator.mozAddonManager.createInstall(args); - if (!install) { - yield Promise.reject("createInstall() did not return an install object"); - } - - // Check that the initial state of the AddonInstall is sane. - if (install.state != "STATE_AVAILABLE") { - yield Promise.reject("new install should be in STATE_AVAILABLE"); - } - if (install.error != null) { - yield Promise.reject("new install should have null error"); - } - - const events = [ - "onDownloadStarted", - "onDownloadProgress", - "onDownloadEnded", - "onDownloadCancelled", - "onDownloadFailed", - "onInstallStarted", - "onInstallEnded", - "onInstallCancelled", - "onInstallFailed", - ]; - let eventWaiter = null; - let receivedEvents = []; - let prevEvent = null; - events.forEach(event => { - install.addEventListener(event, e => { - receivedEvents.push({ - event, - state: install.state, - error: install.error, - progress: install.progress, - maxProgress: install.maxProgress, - }); - if (eventWaiter) { - eventWaiter(); - } - }); - }); - - // Returns a promise that is resolved when the given event occurs - // or rejects if a different event comes first or if props is supplied - // and properties on the AddonInstall don't match those in props. - function expectEvent(event, props) { - return new Promise((resolve, reject) => { - function check() { - let received = receivedEvents.shift(); - // Skip any repeated onDownloadProgress events. - while (received && - received.event == prevEvent && - prevEvent == "onDownloadProgress") { - received = receivedEvents.shift(); - } - // Wait for more events if we skipped all there were. - if (!received) { - eventWaiter = () => { - eventWaiter = null; - check(); - } - return; - } - prevEvent = received.event; - if (received.event != event) { - let err = new Error(`expected ${event} but got ${received.event}`); - reject(err); - } - if (props) { - for (let key of Object.keys(props)) { - if (received[key] != props[key]) { - throw new Error(`AddonInstall property ${key} was ${received[key]} but expected ${props[key]}`); - } - } - } - resolve(); - } - check(); - }); - } - - while (steps.length > 0) { - let nextStep = steps.shift(); - if (nextStep.action) { - if (nextStep.action == "install") { - yield install.install(); - } else if (nextStep.action == "cancel") { - yield install.cancel(); - } else { - throw new Error(`unknown action ${nextStep.action}`); - } - } else { - yield expectEvent(nextStep.event, nextStep.props); - } - } - - return true; - }); - - is(success, true, description); -} - -function makeInstallTest(task) { - return function*() { - // withNewTab() will close the test tab before returning, at which point - // the cleanup event will come from the content process. We need to see - // that event but don't want to race to install a listener for it after - // the tab is closed. So set up the listener now but don't yield the - // listening promise until below. - let clearPromise = waitForClear(); - - yield BrowserTestUtils.withNewTab(TESTPAGE, task); - - yield clearPromise; - is(AddonManager.webAPI.installs.size, 0, "AddonInstall was cleaned up"); - }; -} - -function makeRegularTest(options, what) { - return makeInstallTest(function* (browser) { - let steps = [ - {action: "install"}, - { - event: "onDownloadStarted", - props: {state: "STATE_DOWNLOADING"}, - }, - { - event: "onDownloadProgress", - props: {maxProgress: XPI_LEN}, - }, - { - event: "onDownloadEnded", - props: { - state: "STATE_DOWNLOADED", - progress: XPI_LEN, - maxProgress: XPI_LEN, - }, - }, - { - event: "onInstallStarted", - props: {state: "STATE_INSTALLING"}, - }, - { - event: "onInstallEnded", - props: {state: "STATE_INSTALLED"}, - }, - ]; - - yield testInstall(browser, options, steps, what); - - let version = Services.prefs.getIntPref("webapitest.active_version"); - is(version, 1, "the install really did work"); - - // Sanity check to ensure that the test in makeInstallTest() that - // installs.size == 0 means we actually did clean up. - ok(AddonManager.webAPI.installs.size > 0, "webAPI is tracking the AddonInstall"); - - let addons = yield promiseAddonsByIDs([ID]); - isnot(addons[0], null, "Found the addon"); - - yield addons[0].uninstall(); - - addons = yield promiseAddonsByIDs([ID]); - is(addons[0], null, "Addon was uninstalled"); - }); -} - -add_task(makeRegularTest({url: XPI_URL}, "a basic install works")); -add_task(makeRegularTest({url: XPI_URL, hash: null}, "install with hash=null works")); -add_task(makeRegularTest({url: XPI_URL, hash: ""}, "install with empty string for hash works")); -add_task(makeRegularTest({url: XPI_URL, hash: XPI_SHA}, "install with hash works")); - -add_task(makeInstallTest(function* (browser) { - let steps = [ - {action: "cancel"}, - { - event: "onDownloadCancelled", - props: { - state: "STATE_CANCELLED", - error: null, - }, - } - ]; - - yield testInstall(browser, {url: XPI_URL}, steps, "canceling an install works"); - - let addons = yield promiseAddonsByIDs([ID]); - is(addons[0], null, "The addon was not installed"); - - ok(AddonManager.webAPI.installs.size > 0, "webAPI is tracking the AddonInstall"); -})); - -add_task(makeInstallTest(function* (browser) { - let steps = [ - {action: "install"}, - { - event: "onDownloadStarted", - props: {state: "STATE_DOWNLOADING"}, - }, - {event: "onDownloadProgress"}, - { - event: "onDownloadFailed", - props: { - state: "STATE_DOWNLOAD_FAILED", - error: "ERROR_NETWORK_FAILURE", - }, - } - ]; - - yield testInstall(browser, {url: XPI_URL + "bogus"}, steps, "install of a bad url fails"); - - let addons = yield promiseAddonsByIDs([ID]); - is(addons[0], null, "The addon was not installed"); - - ok(AddonManager.webAPI.installs.size > 0, "webAPI is tracking the AddonInstall"); -})); - -add_task(makeInstallTest(function* (browser) { - let steps = [ - {action: "install"}, - { - event: "onDownloadStarted", - props: {state: "STATE_DOWNLOADING"}, - }, - {event: "onDownloadProgress"}, - { - event: "onDownloadFailed", - props: { - state: "STATE_DOWNLOAD_FAILED", - error: "ERROR_INCORRECT_HASH", - }, - } - ]; - - yield testInstall(browser, {url: XPI_URL, hash: "sha256:bogus"}, steps, "install with bad hash fails"); - - let addons = yield promiseAddonsByIDs([ID]); - is(addons[0], null, "The addon was not installed"); - - ok(AddonManager.webAPI.installs.size > 0, "webAPI is tracking the AddonInstall"); -})); - -add_task(function* test_permissions() { - function testBadUrl(url, pattern, successMessage) { - return BrowserTestUtils.withNewTab(TESTPAGE, function* (browser) { - let result = yield ContentTask.spawn(browser, {url, pattern}, function (opts) { - return new Promise(resolve => { - content.navigator.mozAddonManager.createInstall({url: opts.url}) - .then(() => { - resolve({success: false, message: "createInstall should not have succeeded"}); - }, err => { - if (err.message.match(new RegExp(opts.pattern))) { - resolve({success: true}); - } - resolve({success: false, message: `Wrong error message: ${err.message}`}); - }); - }); - }); - is(result.success, true, result.message || successMessage); - }); - } - - yield testBadUrl("i am not a url", "NS_ERROR_MALFORMED_URI", - "Installing from an unparseable URL fails"); - - yield testBadUrl("https://addons.not-really-mozilla.org/impostor.xpi", - "not permitted", - "Installing from non-approved URL fails"); -}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_webapi_uninstall.js b/toolkit/mozapps/extensions/test/browser/browser_webapi_uninstall.js deleted file mode 100644 index 724f6fefe..000000000 --- a/toolkit/mozapps/extensions/test/browser/browser_webapi_uninstall.js +++ /dev/null @@ -1,51 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -const TESTPAGE = `${SECURE_TESTROOT}webapi_checkavailable.html`; - -Services.prefs.setBoolPref("extensions.webapi.testing", true); -registerCleanupFunction(() => { - Services.prefs.clearUserPref("extensions.webapi.testing"); -}); - -function testWithAPI(task) { - return function*() { - yield BrowserTestUtils.withNewTab(TESTPAGE, task); - } -} - -function API_uninstallByID(browser, id) { - return ContentTask.spawn(browser, id, function*(id) { - let addon = yield content.navigator.mozAddonManager.getAddonByID(id); - - let result = yield addon.uninstall(); - return result; - }); -} - -add_task(testWithAPI(function*(browser) { - const ID1 = "addon1@tests.mozilla.org"; - const ID2 = "addon2@tests.mozilla.org"; - - let provider = new MockProvider(); - - provider.addAddon(new MockAddon(ID1, "Test add-on 1", "extension", 0)); - provider.addAddon(new MockAddon(ID2, "Test add-on 2", "extension", 0)); - - let [a1, a2] = yield promiseAddonsByIDs([ID1, ID2]); - isnot(a1, null, "addon1 is installed"); - isnot(a2, null, "addon2 is installed"); - - let result = yield API_uninstallByID(browser, ID1); - is(result, true, "uninstall of addon1 succeeded"); - - [a1, a2] = yield promiseAddonsByIDs([ID1, ID2]); - is(a1, null, "addon1 is uninstalled"); - isnot(a2, null, "addon2 is still installed"); - - result = yield API_uninstallByID(browser, ID2); - is(result, true, "uninstall of addon2 succeeded"); - [a2] = yield promiseAddonsByIDs([ID2]); - is(a2, null, "addon2 is uninstalled"); -})); diff --git a/toolkit/mozapps/extensions/test/browser/browser_webext_options.js b/toolkit/mozapps/extensions/test/browser/browser_webext_options.js deleted file mode 100644 index b13213f0b..000000000 --- a/toolkit/mozapps/extensions/test/browser/browser_webext_options.js +++ /dev/null @@ -1,70 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -// Wrapper to run a test that consists of: -// 1. opening the add-ons manager viewing the list of extensions -// 2. installing an extension (using the provider installer callable) -// 3. opening the preferences panel for the new extension and verifying -// that it opens cleanly -function* runTest(installer) { - let mgrWindow = yield open_manager("addons://list/extension"); - - let {addon, id} = yield* installer(); - isnot(addon, null, "Extension is installed"); - - let element = get_addon_element(mgrWindow, id); - element.parentNode.ensureElementIsVisible(element); - - let button = mgrWindow.document.getAnonymousElementByAttribute(element, "anonid", "preferences-btn"); - is_element_visible(button, "Preferences button should be visible"); - - EventUtils.synthesizeMouseAtCenter(button, {clickCount: 1}, mgrWindow); - - yield TestUtils.topicObserved(AddonManager.OPTIONS_NOTIFICATION_DISPLAYED, - (subject, data) => data == id); - - is(mgrWindow.gViewController.currentViewId, - `addons://detail/${encodeURIComponent(id)}/preferences`, - "Current view should scroll to preferences"); - - var browser = mgrWindow.document.querySelector("#detail-grid > rows > .inline-options-browser"); - var rows = browser.parentNode; - - ok(browser, "Grid should have a browser child"); - is(browser.localName, "browser", "Grid should have a browser child"); - is(browser.currentURI.spec, element.mAddon.optionsURL, "Browser has the expected options URL loaded") - - is(browser.clientWidth, rows.clientWidth, - "Browser should be the same width as its parent node"); - - button = mgrWindow.document.getElementById("detail-prefs-btn"); - is_element_hidden(button, "Preferences button should not be visible"); - - yield close_manager(mgrWindow); - - addon.uninstall(); -} - -// Test that deferred handling of optionsURL works for a signed webextension -add_task(function* test_options_signed() { - yield* runTest(function*() { - // The extension in-tree is signed with this ID: - const ID = "{9792932b-32b2-4567-998c-e7bf6c4c5e35}"; - - yield install_addon("addons/options_signed.xpi"); - let addon = yield promiseAddonByID(ID); - - return {addon, id: ID}; - }); -}); - -add_task(function* test_options_temporary() { - yield* runTest(function*() { - let dir = get_addon_file_url("options_signed").file; - let addon = yield AddonManager.installTemporaryAddon(dir); - isnot(addon, null, "Extension is installed (temporarily)"); - - return {addon, id: addon.id}; - }); -}); diff --git a/toolkit/mozapps/extensions/test/browser/discovery_frame.html b/toolkit/mozapps/extensions/test/browser/discovery_frame.html index 8ec722812..ca0223a9c 100644 --- a/toolkit/mozapps/extensions/test/browser/discovery_frame.html +++ b/toolkit/mozapps/extensions/test/browser/discovery_frame.html @@ -2,5 +2,5 @@ <html> <body> -<iframe id="frame" width="100%" height="100%" src="https://example.com/browser/toolkit/mozapps/extensions/test/browser/discovery_install.html"></iframe> +<iframe id="frame" width="100%" height="100%" src="https://test1.example.com/browser/toolkit/mozapps/extensions/test/browser/discovery_install.html"></iframe> </body> diff --git a/toolkit/mozapps/extensions/test/browser/discovery_install.html b/toolkit/mozapps/extensions/test/browser/discovery_install.html index c6499ec03..3832adff6 100644 --- a/toolkit/mozapps/extensions/test/browser/discovery_install.html +++ b/toolkit/mozapps/extensions/test/browser/discovery_install.html @@ -1,11 +1,10 @@ <html> <head> <script type="text/javascript"> -/* globals InstallTrigger */ function install() { InstallTrigger.install({ "Test Add-on": { - URL: "https://example.com/browser/toolkit/mozapps/extensions/test/xpinstall/amosigned.xpi" + URL: "https://example.com/browser/toolkit/mozapps/extensions/test/xpinstall/unsigned.xpi" } }); } @@ -13,7 +12,7 @@ function install() { </head> <body> <h1>Test page for the discovery pane</h1> - <p><a id="install-direct" href="https://example.com/browser/toolkit/mozapps/extensions/test/xpinstall/amosigned.xpi">Direct install</a></p> + <p><a id="install-direct" href="https://example.com/browser/toolkit/mozapps/extensions/test/xpinstall/unsigned.xpi">Direct install</a></p> <p><a id="install-js" href="javascript:install()">JS install</a></p> </body> </html> diff --git a/toolkit/mozapps/extensions/test/browser/head.js b/toolkit/mozapps/extensions/test/browser/head.js index 5a749099d..8e96b9b3f 100644 --- a/toolkit/mozapps/extensions/test/browser/head.js +++ b/toolkit/mozapps/extensions/test/browser/head.js @@ -1,16 +1,15 @@ /* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ -/* globals end_test*/ Components.utils.import("resource://gre/modules/NetUtil.jsm"); -var tmp = {}; +let tmp = {}; Components.utils.import("resource://gre/modules/AddonManager.jsm", tmp); Components.utils.import("resource://gre/modules/Log.jsm", tmp); -var AddonManager = tmp.AddonManager; -var AddonManagerPrivate = tmp.AddonManagerPrivate; -var Log = tmp.Log; +let AddonManager = tmp.AddonManager; +let AddonManagerPrivate = tmp.AddonManagerPrivate; +let Log = tmp.Log; var pathParts = gTestPath.split("/"); // Drop the test filename @@ -26,16 +25,13 @@ if (gTestInWindow) { const RELATIVE_DIR = pathParts.slice(4).join("/") + "/"; const TESTROOT = "http://example.com/" + RELATIVE_DIR; -const SECURE_TESTROOT = "https://example.com/" + RELATIVE_DIR; const TESTROOT2 = "http://example.org/" + RELATIVE_DIR; -const SECURE_TESTROOT2 = "https://example.org/" + RELATIVE_DIR; const CHROMEROOT = pathParts.join("/") + "/"; const PREF_DISCOVERURL = "extensions.webservice.discoverURL"; const PREF_DISCOVER_ENABLED = "extensions.getAddons.showPane"; const PREF_XPI_ENABLED = "xpinstall.enabled"; const PREF_UPDATEURL = "extensions.update.url"; const PREF_GETADDONS_CACHE_ENABLED = "extensions.getAddons.cache.enabled"; -const PREF_CUSTOM_XPINSTALL_CONFIRMATION_UI = "xpinstall.customConfirmationUI"; const PREF_UI_LASTCATEGORY = "extensions.ui.lastCategory"; const MANAGER_URI = "about:addons"; @@ -52,8 +48,7 @@ var PREF_CHECK_COMPATIBILITY; } catch (e) { } if (channel != "aurora" && channel != "beta" && - channel != "release" && - channel != "esr") { + channel != "release") { var version = "nightly"; } else { version = Services.appinfo.version.replace(/^([^\.]+\.[0-9]+[a-z]*).*/gi, "$1"); @@ -68,7 +63,6 @@ var gTestStart = null; var gUseInContentUI = !gTestInWindow && ("switchToTabHavingURI" in window); var gRestorePrefs = [{name: PREF_LOGGING_ENABLED}, - {name: PREF_CUSTOM_XPINSTALL_CONFIRMATION_UI}, {name: "extensions.webservice.discoverURL"}, {name: "extensions.update.url"}, {name: "extensions.update.background.url"}, @@ -80,6 +74,7 @@ var gRestorePrefs = [{name: PREF_LOGGING_ENABLED}, {name: "extensions.getAddons.search.url"}, {name: "extensions.getAddons.cache.enabled"}, {name: "devtools.chrome.enabled"}, + {name: "devtools.debugger.remote-enabled"}, {name: PREF_SEARCH_MAXRESULTS}, {name: PREF_STRICT_COMPAT}, {name: PREF_CHECK_COMPATIBILITY}]; @@ -101,8 +96,6 @@ for (let pref of gRestorePrefs) { // Turn logging on for all tests Services.prefs.setBoolPref(PREF_LOGGING_ENABLED, true); -Services.prefs.setBoolPref(PREF_CUSTOM_XPINSTALL_CONFIRMATION_UI, false); - // Helper to register test failures and close windows if any are left open function checkOpenWindows(aWindowID) { let windows = Services.wm.getEnumerator(aWindowID); @@ -120,16 +113,16 @@ function checkOpenWindows(aWindowID) { // Tools to disable and re-enable the background update and blocklist timers // so that tests can protect themselves from unwanted timer events. -var gCatMan = Components.classes["@mozilla.org/categorymanager;1"] +let gCatMan = Components.classes["@mozilla.org/categorymanager;1"] .getService(Components.interfaces.nsICategoryManager); // Default values from toolkit/mozapps/extensions/extensions.manifest, but disable*UpdateTimer() // records the actual value so we can put it back in enable*UpdateTimer() -var backgroundUpdateConfig = "@mozilla.org/addons/integration;1,getService,addon-background-update-timer,extensions.update.interval,86400"; -var blocklistUpdateConfig = "@mozilla.org/extensions/blocklist;1,getService,blocklist-background-update-timer,extensions.blocklist.interval,86400"; +let backgroundUpdateConfig = "@mozilla.org/addons/integration;1,getService,addon-background-update-timer,extensions.update.interval,86400"; +let blocklistUpdateConfig = "@mozilla.org/extensions/blocklist;1,getService,blocklist-background-update-timer,extensions.blocklist.interval,86400"; -var UTIMER = "update-timer"; -var AMANAGER = "addonManager"; -var BLOCKLIST = "nsBlocklistService"; +let UTIMER = "update-timer"; +let AMANAGER = "addonManager"; +let BLOCKLIST = "nsBlocklistService"; function disableBackgroundUpdateTimer() { info("Disabling " + UTIMER + " " + AMANAGER); @@ -230,50 +223,13 @@ function run_next_test() { executeSoon(() => log_exceptions(test)); } -var get_tooltip_info = Task.async(function*(addon) { - let managerWindow = addon.ownerDocument.defaultView; - - // The popup code uses a triggering event's target to set the - // document.tooltipNode property. - let nameNode = addon.ownerDocument.getAnonymousElementByAttribute(addon, "anonid", "name"); - let event = new managerWindow.CustomEvent("TriggerEvent"); - nameNode.dispatchEvent(event); - - let tooltip = managerWindow.document.getElementById("addonitem-tooltip"); - - let promise = BrowserTestUtils.waitForEvent(tooltip, "popupshown"); - tooltip.openPopup(nameNode, "after_start", 0, 0, false, false, event); - yield promise; - - let tiptext = tooltip.label; - - promise = BrowserTestUtils.waitForEvent(tooltip, "popuphidden"); - tooltip.hidePopup(); - yield promise; - - let expectedName = addon.getAttribute("name"); - ok(tiptext.substring(0, expectedName.length), expectedName, - "Tooltip should always start with the expected name"); - - if (expectedName.length == tiptext.length) { - return { - name: tiptext, - version: undefined - }; - } - return { - name: tiptext.substring(0, expectedName.length), - version: tiptext.substring(expectedName.length + 1) - }; -}); - function get_addon_file_url(aFilename) { try { var cr = Cc["@mozilla.org/chrome/chrome-registry;1"]. getService(Ci.nsIChromeRegistry); var fileurl = cr.convertChromeURL(makeURI(CHROMEROOT + "addons/" + aFilename)); return fileurl.QueryInterface(Ci.nsIFileURL); - } catch (ex) { + } catch(ex) { var jar = getJar(CHROMEROOT + "addons/" + aFilename); var tmpDir = extractJarToTmp(jar); tmpDir.append(aFilename); @@ -282,19 +238,10 @@ function get_addon_file_url(aFilename) { } } -function get_current_view(aManager) { - let view = aManager.document.getElementById("view-port").selectedPanel; - if (view.id == "headered-views") { - view = aManager.document.getElementById("headered-views-content").selectedPanel; - } - is(view, aManager.gViewController.displayedView, "view controller is tracking the displayed view correctly"); - return view; -} - function get_test_items_in_list(aManager) { var tests = "@tests.mozilla.org"; - let view = get_current_view(aManager); + let view = aManager.document.getElementById("view-port").selectedPanel; let listid = view.id == "search-view" ? "search-list" : "addon-list"; let item = aManager.document.getElementById(listid).firstChild; let items = []; @@ -315,7 +262,7 @@ function get_test_items_in_list(aManager) { function check_all_in_list(aManager, aIds, aIgnoreExtras) { var doc = aManager.document; - var view = get_current_view(aManager); + var view = doc.getElementById("view-port").selectedPanel; var listid = view.id == "search-view" ? "search-list" : "addon-list"; var list = doc.getElementById(listid); @@ -343,7 +290,7 @@ function check_all_in_list(aManager, aIds, aIgnoreExtras) { function get_addon_element(aManager, aId) { var doc = aManager.document; - var view = get_current_view(aManager); + var view = doc.getElementById("view-port").selectedPanel; var listid = "addon-list"; if (view.id == "search-view") listid = "search-list"; @@ -451,7 +398,7 @@ function close_manager(aManagerWindow, aCallback, aLongerTimeout) { dump("Manager window unload handler\n"); this.removeEventListener("unload", arguments.callee, false); resolve(); - } catch (e) { + } catch(e) { reject(e); } }, false); @@ -504,11 +451,14 @@ function get_string(aName, ...aArgs) { } function formatDate(aDate) { - const locale = Cc["@mozilla.org/chrome/chrome-registry;1"] - .getService(Ci.nsIXULChromeRegistry) - .getSelectedLocale("global", true); - const dtOptions = { year: 'numeric', month: 'long', day: 'numeric' }; - return aDate.toLocaleDateString(locale, dtOptions); + return Cc["@mozilla.org/intl/scriptabledateformat;1"] + .getService(Ci.nsIScriptableDateFormat) + .FormatDate("", + Ci.nsIScriptableDateFormat.dateFormatLong, + aDate.getFullYear(), + aDate.getMonth() + 1, + aDate.getDate() + ); } function is_hidden(aElement) { @@ -535,17 +485,6 @@ function is_element_hidden(aElement, aMsg) { ok(is_hidden(aElement), aMsg || (aElement + " should be hidden")); } -function promiseAddonByID(aId) { - return new Promise(resolve => { - AddonManager.getAddonByID(aId, resolve); - }); -} - -function promiseAddonsByIDs(aIDs) { - return new Promise(resolve => { - AddonManager.getAddonsByIDs(aIDs, resolve); - }); -} /** * Install an add-on and call a callback when complete. * @@ -684,7 +623,7 @@ function addCertOverride(host, bits) { } } -/** *** Mock Provider *****/ +/***** Mock Provider *****/ function MockProvider(aUseAsyncCallbacks, aTypes) { this.addons = []; @@ -719,7 +658,7 @@ MockProvider.prototype = { useAsyncCallbacks: null, types: null, - /** *** Utility functions *****/ + /***** Utility functions *****/ /** * Register this provider with the AddonManager @@ -745,10 +684,10 @@ MockProvider.prototype = { * The add-on to add */ addAddon: function MP_addAddon(aAddon) { - var oldAddons = this.addons.filter(aOldAddon => aOldAddon.id == aAddon.id); + var oldAddons = this.addons.filter(function(aOldAddon) aOldAddon.id == aAddon.id); var oldAddon = oldAddons.length > 0 ? oldAddons[0] : null; - this.addons = this.addons.filter(aOldAddon => aOldAddon.id != aAddon.id); + this.addons = this.addons.filter(function(aOldAddon) aOldAddon.id != aAddon.id); this.addons.push(aAddon); aAddon._provider = this; @@ -882,7 +821,7 @@ MockProvider.prototype = { return newInstalls; }, - /** *** AddonProvider implementation *****/ + /***** AddonProvider implementation *****/ /** * Called to initialize the provider. @@ -906,7 +845,7 @@ MockProvider.prototype = { info("Notifying timer set at " + (setAt || "unknown location")); timer.callback.notify(timer); timer.cancel(); - } catch (e) { + } catch(e) { info("Timer notify failed: " + e); } } @@ -1082,7 +1021,7 @@ MockProvider.prototype = { }, - /** *** Internal functions *****/ + /***** Internal functions *****/ /** * Delay calling a callback to fake a time-consuming async operation. @@ -1118,7 +1057,7 @@ MockProvider.prototype = { } }; -/** *** Mock Addon object for the Mock Provider *****/ +/***** Mock Addon object for the Mock Provider *****/ function MockAddon(aId, aName, aType, aOperationsRequiringRestart) { // Only set required attributes. @@ -1127,6 +1066,7 @@ function MockAddon(aId, aName, aType, aOperationsRequiringRestart) { this.type = aType || "extension"; this.version = ""; this.isCompatible = true; + this.isDebuggable = false; this.providesUpdatesSecurely = true; this.blocklistState = 0; this._appDisabled = false; @@ -1140,8 +1080,7 @@ function MockAddon(aId, aName, aType, aOperationsRequiringRestart) { AddonManager.PERM_CAN_ENABLE | AddonManager.PERM_CAN_DISABLE | AddonManager.PERM_CAN_UPGRADE; - this.operationsRequiringRestart = (aOperationsRequiringRestart != undefined) ? - aOperationsRequiringRestart : + this.operationsRequiringRestart = aOperationsRequiringRestart || (AddonManager.OP_NEEDS_RESTART_INSTALL | AddonManager.OP_NEEDS_RESTART_UNINSTALL | AddonManager.OP_NEEDS_RESTART_ENABLE | @@ -1149,12 +1088,6 @@ function MockAddon(aId, aName, aType, aOperationsRequiringRestart) { } MockAddon.prototype = { - get isCorrectlySigned() { - if (this.signedState === AddonManager.SIGNEDSTATE_NOT_REQUIRED) - return true; - return this.signedState > AddonManager.SIGNEDSTATE_MISSING; - }, - get shouldBeActive() { return !this.appDisabled && !this._userDisabled && !(this.pendingOperations & AddonManager.PENDING_UNINSTALL); @@ -1254,10 +1187,6 @@ MockAddon.prototype = { AddonManagerPrivate.callAddonListeners("onOperationCancelled", this); }, - markAsSeen: function() { - this.seen = true; - }, - _updateActiveState: function(currentActive, newActive) { if (currentActive == newActive) return; @@ -1267,7 +1196,7 @@ MockAddon.prototype = { AddonManagerPrivate.callAddonListeners("onOperationCancelled", this); } else if (newActive) { - let needsRestart = !!(this.operationsRequiringRestart & AddonManager.OP_NEEDS_RESTART_ENABLE); + var needsRestart = !!(this.operationsRequiringRestart & AddonManager.OP_NEEDS_RESTART_ENABLE); this.pendingOperations |= AddonManager.PENDING_ENABLE; AddonManagerPrivate.callAddonListeners("onEnabling", this, needsRestart); if (!needsRestart) { @@ -1277,7 +1206,7 @@ MockAddon.prototype = { } } else { - let needsRestart = !!(this.operationsRequiringRestart & AddonManager.OP_NEEDS_RESTART_DISABLE); + var needsRestart = !!(this.operationsRequiringRestart & AddonManager.OP_NEEDS_RESTART_DISABLE); this.pendingOperations |= AddonManager.PENDING_DISABLE; AddonManagerPrivate.callAddonListeners("onDisabling", this, needsRestart); if (!needsRestart) { @@ -1289,7 +1218,7 @@ MockAddon.prototype = { } }; -/** *** Mock AddonInstall object for the Mock Provider *****/ +/***** Mock AddonInstall object for the Mock Provider *****/ function MockInstall(aName, aType, aAddonToInstall) { this.name = aName || ""; @@ -1357,18 +1286,14 @@ MockInstall.prototype = { return; } - let needsRestart = (this.operationsRequiringRestart & AddonManager.OP_NEEDS_RESTART_INSTALL); - AddonManagerPrivate.callAddonListeners("onInstalling", this.addon, needsRestart); - if (!needsRestart) { - AddonManagerPrivate.callAddonListeners("onInstalled", this.addon); - } + AddonManagerPrivate.callAddonListeners("onInstalling", this.addon); this.state = AddonManager.STATE_INSTALLED; this.callListeners("onInstallEnded"); break; case AddonManager.STATE_DOWNLOADING: case AddonManager.STATE_CHECKING: - case AddonManager.STATE_INSTALLING: + case AddonManger.STATE_INSTALLING: // Installation is already running return; default: @@ -1394,21 +1319,21 @@ MockInstall.prototype = { addListener: function(aListener) { - if (!this.listeners.some(i => i == aListener)) + if (!this.listeners.some(function(i) i == aListener)) this.listeners.push(aListener); }, removeListener: function(aListener) { - this.listeners = this.listeners.filter(i => i != aListener); + this.listeners = this.listeners.filter(function(i) i != aListener); }, addTestListener: function(aListener) { - if (!this.testListeners.some(i => i == aListener)) + if (!this.testListeners.some(function(i) i == aListener)) this.testListeners.push(aListener); }, removeTestListener: function(aListener) { - this.testListeners = this.testListeners.filter(i => i != aListener); + this.testListeners = this.testListeners.filter(function(i) i != aListener); }, callListeners: function(aMethod) { diff --git a/toolkit/mozapps/extensions/test/browser/more_options.xul b/toolkit/mozapps/extensions/test/browser/more_options.xul index 28dbb0a2e..4c8474a79 100644 --- a/toolkit/mozapps/extensions/test/browser/more_options.xul +++ b/toolkit/mozapps/extensions/test/browser/more_options.xul @@ -17,7 +17,7 @@ <radiogroup> <radio label="India" value="india" /> <radio label="Juliet" value="juliet" /> - <radio label="Kilo ㎏" value="kilo ㎏" /> + <radio label="Kilo" value="kilo" /> </radiogroup> </setting> <setting pref="extensions.inlinesettings3.menulist" type="menulist" title="Menulist"> diff --git a/toolkit/mozapps/extensions/test/browser/moz.build b/toolkit/mozapps/extensions/test/browser/moz.build index af04aaeef..9acb42133 100644 --- a/toolkit/mozapps/extensions/test/browser/moz.build +++ b/toolkit/mozapps/extensions/test/browser/moz.build @@ -1,4 +1,4 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- # vim: set filetype=python: # 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 diff --git a/toolkit/mozapps/extensions/test/browser/signed_hotfix.rdf b/toolkit/mozapps/extensions/test/browser/signed_hotfix.rdf deleted file mode 100644 index 39bd936c9..000000000 --- a/toolkit/mozapps/extensions/test/browser/signed_hotfix.rdf +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> - -<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:em="http://www.mozilla.org/2004/em-rdf#"> - - <Description about="urn:mozilla:extension:hotfix@tests.mozilla.org"> - <em:updates> - <Seq> - <li> - <Description> - <em:version>1.0</em:version> - <em:targetApplication> - <Description> - <em:id>toolkit@mozilla.org</em:id> - <em:minVersion>0</em:minVersion> - <em:maxVersion>*</em:maxVersion> - <em:updateLink>https://example.com/browser/toolkit/mozapps/extensions/test/browser/signed_hotfix.xpi</em:updateLink> - </Description> - </em:targetApplication> - </Description> - </li> - </Seq> - </em:updates> - </Description> - -</RDF> diff --git a/toolkit/mozapps/extensions/test/browser/signed_hotfix.xpi b/toolkit/mozapps/extensions/test/browser/signed_hotfix.xpi Binary files differdeleted file mode 100644 index bd1890573..000000000 --- a/toolkit/mozapps/extensions/test/browser/signed_hotfix.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/browser/unsigned_hotfix.rdf b/toolkit/mozapps/extensions/test/browser/unsigned_hotfix.rdf deleted file mode 100644 index 2b4ba9362..000000000 --- a/toolkit/mozapps/extensions/test/browser/unsigned_hotfix.rdf +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> - -<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:em="http://www.mozilla.org/2004/em-rdf#"> - - <Description about="urn:mozilla:extension:hotfix@tests.mozilla.org"> - <em:updates> - <Seq> - <li> - <Description> - <em:version>1.0</em:version> - <em:targetApplication> - <Description> - <em:id>toolkit@mozilla.org</em:id> - <em:minVersion>0</em:minVersion> - <em:maxVersion>*</em:maxVersion> - <em:updateLink>https://example.com/browser/toolkit/mozapps/extensions/test/browser/unsigned_hotfix.xpi</em:updateLink> - </Description> - </em:targetApplication> - </Description> - </li> - </Seq> - </em:updates> - </Description> - -</RDF> diff --git a/toolkit/mozapps/extensions/test/browser/unsigned_hotfix.xpi b/toolkit/mozapps/extensions/test/browser/unsigned_hotfix.xpi Binary files differdeleted file mode 100644 index f2d475bd2..000000000 --- a/toolkit/mozapps/extensions/test/browser/unsigned_hotfix.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/browser/webapi_addon_listener.html b/toolkit/mozapps/extensions/test/browser/webapi_addon_listener.html deleted file mode 100644 index 56128fd9c..000000000 --- a/toolkit/mozapps/extensions/test/browser/webapi_addon_listener.html +++ /dev/null @@ -1,30 +0,0 @@ -<!DOCTYPE html> - -<html> -<head> - <meta charset="utf-8"> -</head> -<body> -<p id="result"></p> -<script type="text/javascript"> -let events = []; -let resultEl = document.getElementById("result"); -[ "onEnabling", - "onEnabled", - "onDisabling", - "onDisabled", - "onInstalling", - "onInstalled", - "onUninstalling", - "onUninstalled", - "onOperationCancelled", -].forEach(event => { - navigator.mozAddonManager.addEventListener(event, data => { - let obj = {event, id: data.id, needsRestart: data.needsRestart}; - events.push(JSON.stringify(obj)); - resultEl.textContent = events.join('\n'); - }); -}); -</script> -</body> -</html> diff --git a/toolkit/mozapps/extensions/test/browser/webapi_checkavailable.html b/toolkit/mozapps/extensions/test/browser/webapi_checkavailable.html deleted file mode 100644 index 141f09cc6..000000000 --- a/toolkit/mozapps/extensions/test/browser/webapi_checkavailable.html +++ /dev/null @@ -1,13 +0,0 @@ -<!DOCTYPE html> - -<html> -<head> - <meta charset="utf-8"> -</head> -<body> -<p id="result"></p> -<script type="text/javascript"> -document.getElementById("result").textContent = ("mozAddonManager" in window.navigator); -</script> -</body> -</html> diff --git a/toolkit/mozapps/extensions/test/browser/webapi_checkchromeframe.xul b/toolkit/mozapps/extensions/test/browser/webapi_checkchromeframe.xul deleted file mode 100644 index 76e642604..000000000 --- a/toolkit/mozapps/extensions/test/browser/webapi_checkchromeframe.xul +++ /dev/null @@ -1,6 +0,0 @@ -<?xml version="1.0"?> -<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> -<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> - <browser id="frame" disablehistory="true" flex="1" type="content" - src="https://example.com/browser/toolkit/mozapps/extensions/test/browser/webapi_checkavailable.html"/> -</window> diff --git a/toolkit/mozapps/extensions/test/browser/webapi_checkframed.html b/toolkit/mozapps/extensions/test/browser/webapi_checkframed.html deleted file mode 100644 index 146769978..000000000 --- a/toolkit/mozapps/extensions/test/browser/webapi_checkframed.html +++ /dev/null @@ -1,7 +0,0 @@ -<!DOCTYPE html> - -<html> -<body> -<iframe id="frame" height="200" width="200" src="https://example.com/browser/toolkit/mozapps/extensions/test/browser/webapi_checkavailable.html"> -</body> -</html> diff --git a/toolkit/mozapps/extensions/test/browser/webapi_checknavigatedwindow.html b/toolkit/mozapps/extensions/test/browser/webapi_checknavigatedwindow.html deleted file mode 100644 index ba3653310..000000000 --- a/toolkit/mozapps/extensions/test/browser/webapi_checknavigatedwindow.html +++ /dev/null @@ -1,28 +0,0 @@ -<!DOCTYPE html> - -<html> -<body> -<script type="text/javascript"> -var nav, win; - -function openWindow() { - return new Promise(resolve => { - win = window.open(window.location); - - win.addEventListener("load", function listener() { - nav = win.navigator; - resolve(); - }, false); - }); -} - -function navigate() { - win.location = "http://example.com/"; -} - -function check() { - return "mozAddonManager" in nav; -} -</script> -</body> -</html> diff --git a/toolkit/mozapps/extensions/test/mochitest/.eslintrc.js b/toolkit/mozapps/extensions/test/mochitest/.eslintrc.js deleted file mode 100644 index 383da0f41..000000000 --- a/toolkit/mozapps/extensions/test/mochitest/.eslintrc.js +++ /dev/null @@ -1,7 +0,0 @@ -"use strict"; - -module.exports = { // eslint-disable-line no-undef - "extends": [ - "../../../../../testing/mochitest/mochitest.eslintrc.js" - ] -}; diff --git a/toolkit/mozapps/extensions/test/mochitest/file_bug687194.xpi b/toolkit/mozapps/extensions/test/mochitest/file_bug687194.xpi Binary files differindex e215cffad..dfc035053 100644 --- a/toolkit/mozapps/extensions/test/mochitest/file_bug687194.xpi +++ b/toolkit/mozapps/extensions/test/mochitest/file_bug687194.xpi diff --git a/toolkit/mozapps/extensions/test/mochitest/mochitest.ini b/toolkit/mozapps/extensions/test/mochitest/mochitest.ini index b14cfe87a..375f619b4 100644 --- a/toolkit/mozapps/extensions/test/mochitest/mochitest.ini +++ b/toolkit/mozapps/extensions/test/mochitest/mochitest.ini @@ -1,4 +1,5 @@ [DEFAULT] +skip-if = buildapp == 'b2g' support-files = file_empty.html file_bug687194.xpi diff --git a/toolkit/mozapps/extensions/test/mochitest/test_bug887098.html b/toolkit/mozapps/extensions/test/mochitest/test_bug887098.html index 535799b27..2b2033a37 100644 --- a/toolkit/mozapps/extensions/test/mochitest/test_bug887098.html +++ b/toolkit/mozapps/extensions/test/mochitest/test_bug887098.html @@ -12,7 +12,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=887098 /** Test for Bug 887098 **/ SimpleTest.waitForExplicitFinish(); - /* globals $,evalRef */ function loaded() { var iwin = $('ifr').contentWindow; @@ -28,7 +27,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=887098 evalRef('InstallTrigger.install({URL: "chrome://global/skin/global.css"});'); ok(false, "Should have thrown when trying to install restricted URI from InstallTrigger"); } catch (e) { - // XXXgijs this test broke because of the switch to webidl. I'm told + //XXXgijs this test broke because of the switch to webidl. I'm told // it has to do with compartments and the fact that we eval in "about:". // Tracking in bug 1007671 todo(/permission/.test(e), "We should throw a security exception. Got: " + e); diff --git a/toolkit/mozapps/extensions/test/moz.build b/toolkit/mozapps/extensions/test/moz.build index 716659198..d74976bda 100644 --- a/toolkit/mozapps/extensions/test/moz.build +++ b/toolkit/mozapps/extensions/test/moz.build @@ -1,13 +1,14 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- # vim: set filetype=python: # 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/. -DIRS += ['browser'] +if CONFIG['MOZ_BUILD_APP'] != 'mobile': + DIRS += ['browser'] -BROWSER_CHROME_MANIFESTS += ['xpinstall/browser.ini'] -MOCHITEST_MANIFESTS += ['mochitest/mochitest.ini'] + BROWSER_CHROME_MANIFESTS += ['xpinstall/browser.ini'] + MOCHITEST_MANIFESTS += ['mochitest/mochitest.ini'] TESTING_JS_MODULES += [ 'AddonManagerTesting.jsm', diff --git a/toolkit/mozapps/extensions/test/xpcshell/.eslintrc.js b/toolkit/mozapps/extensions/test/xpcshell/.eslintrc.js deleted file mode 100644 index ba65517f9..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/.eslintrc.js +++ /dev/null @@ -1,7 +0,0 @@ -"use strict"; - -module.exports = { // eslint-disable-line no-undef - "extends": [ - "../../../../../testing/xpcshell/xpcshell.eslintrc.js" - ] -}; diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/BootstrapMonitor.jsm b/toolkit/mozapps/extensions/test/xpcshell/data/BootstrapMonitor.jsm deleted file mode 100644 index 7c1e4aa9d..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/BootstrapMonitor.jsm +++ /dev/null @@ -1,30 +0,0 @@ -Components.utils.import("resource://gre/modules/Services.jsm"); - -this.EXPORTED_SYMBOLS = [ "monitor" ]; - -function notify(event, originalMethod, data, reason) { - let info = { - event, - data: Object.assign({}, data, { - installPath: data.installPath.path, - resourceURI: data.resourceURI.spec, - }), - reason - }; - - let subject = {wrappedJSObject: {data}}; - - Services.obs.notifyObservers(subject, "bootstrapmonitor-event", JSON.stringify(info)); - - // If the bootstrap scope already declares a method call it - if (originalMethod) - originalMethod(data, reason); -} - -// Allows a simple one-line bootstrap script: -// Components.utils.import("resource://xpcshelldata/bootstrapmonitor.jsm").monitor(this); -this.monitor = function(scope) { - for (let event of ["install", "startup", "shutdown", "uninstall"]) { - scope[event] = notify.bind(null, event, scope[event]); - } -} diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/from_sources/bootstrap.js b/toolkit/mozapps/extensions/test/xpcshell/data/from_sources/bootstrap.js deleted file mode 100644 index 1666f2972..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/from_sources/bootstrap.js +++ /dev/null @@ -1 +0,0 @@ -Components.utils.import("resource://xpcshell-data/BootstrapMonitor.jsm").monitor(this); diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/pluginInfoURL_block.xml b/toolkit/mozapps/extensions/test/xpcshell/data/pluginInfoURL_block.xml index 75e252a46..6c6ce90ef 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/data/pluginInfoURL_block.xml +++ b/toolkit/mozapps/extensions/test/xpcshell/data/pluginInfoURL_block.xml @@ -7,39 +7,15 @@ <pluginItem blockID="test_plugin_wInfoURL"> <match name="name" exp="^test_with_infoURL"/> <match name="version" exp="^5"/> - <versionRange> - <targetApplication id="xpcshell@tests.mozilla.org"> - <versionRange minVersion="1" maxVersion="*"/> - </targetApplication> - </versionRange> <infoURL>http://test.url.com/</infoURL> </pluginItem> <pluginItem blockID="test_plugin_wAltInfoURL"> <match name="name" exp="^test_with_altInfoURL"/> <match name="version" exp="^5"/> - <versionRange> - <targetApplication id="xpcshell@tests.mozilla.org"> - <versionRange minVersion="1" maxVersion="*"/> - </targetApplication> - </versionRange> <infoURL>http://alt.test.url.com/</infoURL> </pluginItem> <pluginItem blockID="test_plugin_noInfoURL"> <match name="name" exp="^test_no_infoURL"/> - <versionRange> - <targetApplication id="xpcshell@tests.mozilla.org"> - <versionRange minVersion="1" maxVersion="*"/> - </targetApplication> - </versionRange> - </pluginItem> - <pluginItem blockID="test_plugin_newVersion"> - <match name="name" exp="^test_newVersion"/> - <infoURL>http://test.url2.com/</infoURL> - <versionRange minVersion="1" maxVersion="2"> - <targetApplication id="xpcshell@tests.mozilla.org"> - <versionRange minVersion="1" maxVersion="*"/> - </targetApplication> - </versionRange> </pluginItem> </pluginItems> </blocklist> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/productaddons/bad.txt b/toolkit/mozapps/extensions/test/xpcshell/data/productaddons/bad.txt deleted file mode 100644 index f17f98b15..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/productaddons/bad.txt +++ /dev/null @@ -1 +0,0 @@ -Not an xml file!
\ No newline at end of file diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/productaddons/bad.xml b/toolkit/mozapps/extensions/test/xpcshell/data/productaddons/bad.xml deleted file mode 100644 index 0e3d415c4..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/productaddons/bad.xml +++ /dev/null @@ -1,3 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<foobar></barfoo>
\ No newline at end of file diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/productaddons/bad2.xml b/toolkit/mozapps/extensions/test/xpcshell/data/productaddons/bad2.xml deleted file mode 100644 index 55ad1c7d5..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/productaddons/bad2.xml +++ /dev/null @@ -1,3 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<test></test> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/productaddons/empty.xml b/toolkit/mozapps/extensions/test/xpcshell/data/productaddons/empty.xml deleted file mode 100644 index 42cb20bd0..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/productaddons/empty.xml +++ /dev/null @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<updates> - <addons></addons> -</updates> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/productaddons/good.xml b/toolkit/mozapps/extensions/test/xpcshell/data/productaddons/good.xml deleted file mode 100644 index e1da86fa5..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/productaddons/good.xml +++ /dev/null @@ -1,11 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<updates> - <addons> - <addon id="test1" URL="http://example.com/test1.xpi"/> - <addon id="test2" URL="http://example.com/test2.xpi" hashFunction="md5" hashValue="djhfgsjdhf"/> - <addon id="test3" URL="http://example.com/test3.xpi" version="1.0" size="45"/> - <addon id="test4"/> - <addon URL="http://example.com/test5.xpi"/> - </addons> -</updates> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/productaddons/missing.xml b/toolkit/mozapps/extensions/test/xpcshell/data/productaddons/missing.xml deleted file mode 100644 index 8c9501478..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/productaddons/missing.xml +++ /dev/null @@ -1,3 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<updates></updates> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/productaddons/unsigned.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/productaddons/unsigned.xpi Binary files differdeleted file mode 100644 index 51b00475a..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/productaddons/unsigned.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/bootstrap_1/test.txt b/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/bootstrap_1/test.txt deleted file mode 100644 index 11686f61c..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/bootstrap_1/test.txt +++ /dev/null @@ -1 +0,0 @@ -This test file can be altered to break signing checks. diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/bootstrap_2/install.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/bootstrap_2/install.rdf deleted file mode 100644 index 0a345dd92..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/bootstrap_2/install.rdf +++ /dev/null @@ -1,24 +0,0 @@ -<?xml version="1.0"?> - -<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:em="http://www.mozilla.org/2004/em-rdf#"> - - <Description about="urn:mozilla:install-manifest"> - <em:id>test@tests.mozilla.org</em:id> - <em:version>2.0</em:version> - <em:bootstrap>true</em:bootstrap> - - <!-- Front End MetaData --> - <em:name>Test Add-on</em:name> - <em:updateURL>http://localhost:4444/update.rdf</em:updateURL> - - <em:targetApplication> - <Description> - <em:id>xpcshell@tests.mozilla.org</em:id> - <em:minVersion>4</em:minVersion> - <em:maxVersion>6</em:maxVersion> - </Description> - </em:targetApplication> - - </Description> -</RDF> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/bootstrap_2/test.txt b/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/bootstrap_2/test.txt deleted file mode 100644 index 11686f61c..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/bootstrap_2/test.txt +++ /dev/null @@ -1 +0,0 @@ -This test file can be altered to break signing checks. diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/hotfix_badid.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/hotfix_badid.xpi Binary files differdeleted file mode 100644 index 9d6f0c708..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/hotfix_badid.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/hotfix_broken.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/hotfix_broken.xpi Binary files differdeleted file mode 100644 index 4496a90cf..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/hotfix_broken.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/hotfix_good.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/hotfix_good.xpi Binary files differdeleted file mode 100644 index e61e3c721..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/hotfix_good.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/long_63_hash.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/long_63_hash.xpi Binary files differdeleted file mode 100644 index 1682a7506..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/long_63_hash.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/long_63_plain.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/long_63_plain.xpi Binary files differdeleted file mode 100644 index cd67e25fc..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/long_63_plain.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/long_64_hash.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/long_64_hash.xpi Binary files differdeleted file mode 100644 index e4040a274..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/long_64_hash.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/long_64_plain.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/long_64_plain.xpi Binary files differdeleted file mode 100644 index ca453b9d5..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/long_64_plain.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/long_65_hash.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/long_65_hash.xpi Binary files differdeleted file mode 100644 index 69579d2dc..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/long_65_hash.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/multi_badid.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/multi_badid.xpi Binary files differdeleted file mode 100644 index 6e23eb214..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/multi_badid.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/multi_broken.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/multi_broken.xpi Binary files differdeleted file mode 100644 index 0ba0f30d1..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/multi_broken.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/multi_signed.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/multi_signed.xpi Binary files differdeleted file mode 100644 index 33101f63c..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/multi_signed.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/multi_unsigned.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/multi_unsigned.xpi Binary files differdeleted file mode 100644 index 3146870d8..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/multi_unsigned.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/nonbootstrap_1/install.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/nonbootstrap_1/install.rdf deleted file mode 100644 index 97ae60988..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/nonbootstrap_1/install.rdf +++ /dev/null @@ -1,23 +0,0 @@ -<?xml version="1.0"?> - -<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:em="http://www.mozilla.org/2004/em-rdf#"> - - <Description about="urn:mozilla:install-manifest"> - <em:id>test@tests.mozilla.org</em:id> - <em:version>1.0</em:version> - - <!-- Front End MetaData --> - <em:name>Test Add-on</em:name> - <em:updateURL>http://localhost:4444/update.rdf</em:updateURL> - - <em:targetApplication> - <Description> - <em:id>xpcshell@tests.mozilla.org</em:id> - <em:minVersion>2</em:minVersion> - <em:maxVersion>5</em:maxVersion> - </Description> - </em:targetApplication> - - </Description> -</RDF> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/nonbootstrap_1/test.txt b/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/nonbootstrap_1/test.txt deleted file mode 100644 index 11686f61c..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/nonbootstrap_1/test.txt +++ /dev/null @@ -1 +0,0 @@ -This test file can be altered to break signing checks. diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/nonbootstrap_2/install.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/nonbootstrap_2/install.rdf deleted file mode 100644 index df2fd8081..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/nonbootstrap_2/install.rdf +++ /dev/null @@ -1,23 +0,0 @@ -<?xml version="1.0"?> - -<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:em="http://www.mozilla.org/2004/em-rdf#"> - - <Description about="urn:mozilla:install-manifest"> - <em:id>test@tests.mozilla.org</em:id> - <em:version>2.0</em:version> - - <!-- Front End MetaData --> - <em:name>Test Add-on</em:name> - <em:updateURL>http://localhost:4444/update.rdf</em:updateURL> - - <em:targetApplication> - <Description> - <em:id>xpcshell@tests.mozilla.org</em:id> - <em:minVersion>4</em:minVersion> - <em:maxVersion>6</em:maxVersion> - </Description> - </em:targetApplication> - - </Description> -</RDF> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/nonbootstrap_2/test.txt b/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/nonbootstrap_2/test.txt deleted file mode 100644 index 11686f61c..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/nonbootstrap_2/test.txt +++ /dev/null @@ -1 +0,0 @@ -This test file can be altered to break signing checks. diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/preliminary_bootstrap_2.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/preliminary_bootstrap_2.xpi Binary files differdeleted file mode 100644 index ec38fcc65..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/preliminary_bootstrap_2.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/signed_bootstrap_1.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/signed_bootstrap_1.xpi Binary files differdeleted file mode 100644 index fc2842399..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/signed_bootstrap_1.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/signed_bootstrap_2.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/signed_bootstrap_2.xpi Binary files differdeleted file mode 100644 index 327c8a187..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/signed_bootstrap_2.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/signed_bootstrap_badid_2.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/signed_bootstrap_badid_2.xpi Binary files differdeleted file mode 100644 index efad21d1b..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/signed_bootstrap_badid_2.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/signed_nonbootstrap_2.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/signed_nonbootstrap_2.xpi Binary files differdeleted file mode 100644 index d6ddbcec3..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/signed_nonbootstrap_2.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/signed_nonbootstrap_badid_2.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/signed_nonbootstrap_badid_2.xpi Binary files differdeleted file mode 100644 index 5898d83e4..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/signed_nonbootstrap_badid_2.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/unsigned_bootstrap_2.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/unsigned_bootstrap_2.xpi Binary files differdeleted file mode 100644 index 9d50f0825..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/unsigned_bootstrap_2.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/unsigned_nonbootstrap_2.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/unsigned_nonbootstrap_2.xpi Binary files differdeleted file mode 100644 index 6ba1efd72..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/unsigned_nonbootstrap_2.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/bootstrap.js b/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/bootstrap.js deleted file mode 100644 index 1666f2972..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/bootstrap.js +++ /dev/null @@ -1 +0,0 @@ -Components.utils.import("resource://xpcshell-data/BootstrapMonitor.jsm").monitor(this); diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system1_1.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system1_1.xpi Binary files differdeleted file mode 100644 index 2fc2fd189..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system1_1.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system1_1_badcert.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system1_1_badcert.xpi Binary files differdeleted file mode 100644 index e7e50c8ea..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system1_1_badcert.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system1_2.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system1_2.xpi Binary files differdeleted file mode 100644 index a858cf74a..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system1_2.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system2_1.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system2_1.xpi Binary files differdeleted file mode 100644 index 911632e49..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system2_1.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system2_2.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system2_2.xpi Binary files differdeleted file mode 100644 index 102a053bb..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system2_2.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system2_3.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system2_3.xpi Binary files differdeleted file mode 100644 index 295e77611..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system2_3.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system3_1.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system3_1.xpi Binary files differdeleted file mode 100644 index 954995619..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system3_1.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system3_2.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system3_2.xpi Binary files differdeleted file mode 100644 index dc8632aef..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system3_2.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system3_3.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system3_3.xpi Binary files differdeleted file mode 100644 index 3f818172a..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system3_3.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system4_1.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system4_1.xpi Binary files differdeleted file mode 100644 index 1f70b1a75..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system4_1.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system5_1.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system5_1.xpi Binary files differdeleted file mode 100644 index fc636e97f..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system5_1.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system6_1_unpack.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system6_1_unpack.xpi Binary files differdeleted file mode 100644 index ff620966d..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system6_1_unpack.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system6_2_notBootstrap.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system6_2_notBootstrap.xpi Binary files differdeleted file mode 100644 index e474dbd59..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system6_2_notBootstrap.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system6_3_notMultiprocess.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system6_3_notMultiprocess.xpi Binary files differdeleted file mode 100644 index 1ccde90c5..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system6_3_notMultiprocess.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system_delay_complete.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system_delay_complete.xpi Binary files differdeleted file mode 100644 index 94d9e47d2..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system_delay_complete.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system_delay_complete_2.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system_delay_complete_2.xpi Binary files differdeleted file mode 100644 index 28c8561c6..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system_delay_complete_2.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system_delay_defer.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system_delay_defer.xpi Binary files differdeleted file mode 100644 index daf55c0d4..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system_delay_defer.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system_delay_defer_2.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system_delay_defer_2.xpi Binary files differdeleted file mode 100644 index 75cacbbc8..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system_delay_defer_2.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system_delay_defer_also.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system_delay_defer_also.xpi Binary files differdeleted file mode 100644 index 2eb6b7fc9..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system_delay_defer_also.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system_delay_defer_also_2.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system_delay_defer_also_2.xpi Binary files differdeleted file mode 100644 index fb588b3e0..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system_delay_defer_also_2.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system_delay_ignore.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system_delay_ignore.xpi Binary files differdeleted file mode 100644 index 7a5eb265d..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system_delay_ignore.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system_delay_ignore_2.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system_delay_ignore_2.xpi Binary files differdeleted file mode 100644 index dc6749355..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system_delay_ignore_2.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system_failed_update.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system_failed_update.xpi Binary files differdeleted file mode 100644 index 3c673ac2e..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/system_failed_update.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_delay_update_complete/bootstrap.js b/toolkit/mozapps/extensions/test/xpcshell/data/test_delay_update_complete/bootstrap.js deleted file mode 100644 index a81c90bf0..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/test_delay_update_complete/bootstrap.js +++ /dev/null @@ -1,24 +0,0 @@ -Components.utils.import("resource://gre/modules/Services.jsm"); -Components.utils.import("resource://gre/modules/AddonManager.jsm"); - -const ADDON_ID = "test_delay_update_complete@tests.mozilla.org"; -const INSTALL_COMPLETE_PREF = "bootstraptest.install_complete_done"; - -function install(data, reason) {} - -// normally we would use BootstrapMonitor here, but we need a reference to -// the symbol inside `XPIProvider.jsm`. -function startup(data, reason) { - // apply update immediately - if (data.hasOwnProperty("instanceID") && data.instanceID) { - AddonManager.addUpgradeListener(data.instanceID, (upgrade) => { - upgrade.install(); - }); - } else { - throw Error("no instanceID passed to bootstrap startup"); - } -} - -function shutdown(data, reason) {} - -function uninstall(data, reason) {} diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_delay_update_defer/bootstrap.js b/toolkit/mozapps/extensions/test/xpcshell/data/test_delay_update_defer/bootstrap.js deleted file mode 100644 index 25ffd8565..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/test_delay_update_defer/bootstrap.js +++ /dev/null @@ -1,34 +0,0 @@ -Components.utils.import("resource://gre/modules/Services.jsm"); -Components.utils.import("resource://gre/modules/AddonManager.jsm"); - -const ADDON_ID = "test_delay_update_complete@tests.mozilla.org"; -const INSTALL_COMPLETE_PREF = "bootstraptest.install_complete_done"; - -// global reference to hold upgrade object -let gUpgrade; - -function install(data, reason) {} - -// normally we would use BootstrapMonitor here, but we need a reference to -// the symbol inside `XPIProvider.jsm`. -function startup(data, reason) { - // do not apply update immediately, hold on to for later - if (data.hasOwnProperty("instanceID") && data.instanceID) { - AddonManager.addUpgradeListener(data.instanceID, (upgrade) => { - gUpgrade = upgrade; - }); - } else { - throw Error("no instanceID passed to bootstrap startup"); - } - - // add a listener so the test can pass control back - AddonManager.addAddonListener({ - onFakeEvent: () => { - gUpgrade.install(); - } - }) -} - -function shutdown(data, reason) {} - -function uninstall(data, reason) {} diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_delay_update_ignore/bootstrap.js b/toolkit/mozapps/extensions/test/xpcshell/data/test_delay_update_ignore/bootstrap.js deleted file mode 100644 index 7693c9c2d..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/test_delay_update_ignore/bootstrap.js +++ /dev/null @@ -1,26 +0,0 @@ -Components.utils.import("resource://gre/modules/Services.jsm"); -Components.utils.import("resource://gre/modules/AddonManager.jsm"); - -const ADDON_ID = "test_delay_update_ignore@tests.mozilla.org"; -const TEST_IGNORE_PREF = "delaytest.ignore"; - -function install(data, reason) {} - -// normally we would use BootstrapMonitor here, but we need a reference to -// the symbol inside `XPIProvider.jsm`. -function startup(data, reason) { - Services.prefs.setBoolPref(TEST_IGNORE_PREF, false); - - // explicitly ignore update, will be queued for next restart - if (data.hasOwnProperty("instanceID") && data.instanceID) { - AddonManager.addUpgradeListener(data.instanceID, (upgrade) => { - Services.prefs.setBoolPref(TEST_IGNORE_PREF, true); - }); - } else { - throw Error("no instanceID passed to bootstrap startup"); - } -} - -function shutdown(data, reason) {} - -function uninstall(data, reason) {} diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_delay_updates_complete.json b/toolkit/mozapps/extensions/test/xpcshell/data/test_delay_updates_complete.json deleted file mode 100644 index cf3defdc7..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/test_delay_updates_complete.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "addons": { - "test_delay_update_complete_webext@tests.mozilla.org": { - "updates": [ - { "version": "2.0", - "update_link": "http://localhost:%PORT%/addons/test_delay_update_complete_webextension_v2.xpi" - } - ] - } - } -} diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_delay_updates_complete.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_delay_updates_complete.rdf deleted file mode 100644 index 8af39cb0e..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/test_delay_updates_complete.rdf +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:em="http://www.mozilla.org/2004/em-rdf#"> - - <Description about="urn:mozilla:extension:test_delay_update_complete@tests.mozilla.org"> - <em:updates> - <Seq> - <!-- app id compatible update available --> - <li> - <Description> - <em:version>2.0</em:version> - <em:targetApplication> - <Description> - <em:id>xpcshell@tests.mozilla.org</em:id> - <em:minVersion>1</em:minVersion> - <em:maxVersion>1</em:maxVersion> - <em:updateLink>http://localhost:%PORT%/addons/test_delay_update_complete_v2.xpi</em:updateLink> - </Description> - </em:targetApplication> - </Description> - </li> - </Seq> - </em:updates> - </Description> -</RDF> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_delay_updates_defer.json b/toolkit/mozapps/extensions/test/xpcshell/data/test_delay_updates_defer.json deleted file mode 100644 index 2fcab10b5..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/test_delay_updates_defer.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "addons": { - "test_delay_update_defer_webext@tests.mozilla.org": { - "updates": [ - { "version": "2.0", - "update_link": "http://localhost:%PORT%/addons/test_delay_update_defer_webextension_v2.xpi" - } - ] - } - } -} diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_delay_updates_defer.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_delay_updates_defer.rdf deleted file mode 100644 index d44d4880f..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/test_delay_updates_defer.rdf +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:em="http://www.mozilla.org/2004/em-rdf#"> - - <Description about="urn:mozilla:extension:test_delay_update_defer@tests.mozilla.org"> - <em:updates> - <Seq> - <!-- app id compatible update available --> - <li> - <Description> - <em:version>2.0</em:version> - <em:targetApplication> - <Description> - <em:id>xpcshell@tests.mozilla.org</em:id> - <em:minVersion>1</em:minVersion> - <em:maxVersion>1</em:maxVersion> - <em:updateLink>http://localhost:%PORT%/addons/test_delay_update_defer_v2.xpi</em:updateLink> - </Description> - </em:targetApplication> - </Description> - </li> - </Seq> - </em:updates> - </Description> -</RDF> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_delay_updates_ignore.json b/toolkit/mozapps/extensions/test/xpcshell/data/test_delay_updates_ignore.json deleted file mode 100644 index b7f48149d..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/test_delay_updates_ignore.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "addons": { - "test_delay_update_ignore_webext@tests.mozilla.org": { - "updates": [ - { "version": "2.0", - "update_link": "http://localhost:%PORT%/addons/test_delay_update_ignore_webextension_v2.xpi" - } - ] - } - } -} diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_delay_updates_ignore.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_delay_updates_ignore.rdf deleted file mode 100644 index 866884f8d..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/test_delay_updates_ignore.rdf +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:em="http://www.mozilla.org/2004/em-rdf#"> - - <Description about="urn:mozilla:extension:test_delay_update_ignore@tests.mozilla.org"> - <em:updates> - <Seq> - <!-- app id compatible update available --> - <li> - <Description> - <em:version>2.0</em:version> - <em:targetApplication> - <Description> - <em:id>xpcshell@tests.mozilla.org</em:id> - <em:minVersion>1</em:minVersion> - <em:maxVersion>1</em:maxVersion> - <em:updateLink>http://localhost:%PORT%/addons/test_delay_update_ignore_v2.xpi</em:updateLink> - </Description> - </em:targetApplication> - </Description> - </li> - </Seq> - </em:updates> - </Description> -</RDF> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_gfxBlacklist.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_gfxBlacklist.xml index d535d2c3f..639f2d20f 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/data/test_gfxBlacklist.xml +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_gfxBlacklist.xml @@ -2,7 +2,7 @@ <blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist"> <gfxItems> - <gfxBlacklistEntry blockID="g35"> + <gfxBlacklistEntry> <os>WINNT 6.1</os> <vendor>0xabcd</vendor> <devices> @@ -28,7 +28,7 @@ <driverVersion> 8.52.322.2202 </driverVersion> <driverVersionComparator> LESS_THAN </driverVersionComparator> </gfxBlacklistEntry> - <gfxBlacklistEntry blockID="g36"> + <gfxBlacklistEntry> <os>WINNT 6.1</os> <vendor>0xabab</vendor> <devices> @@ -55,7 +55,7 @@ <driverVersionComparator> EQUAL </driverVersionComparator> </gfxBlacklistEntry> <gfxBlacklistEntry> - <os>Darwin 13</os> + <os>Darwin 9</os> <vendor>0xabcd</vendor> <devices> <device>0x2783</device> @@ -124,7 +124,7 @@ <featureStatus> BLOCKED_DEVICE </featureStatus> </gfxBlacklistEntry> <gfxBlacklistEntry> - <os>Darwin 13</os> + <os>Darwin 9</os> <vendor>0xabcd</vendor> <devices> <device>0x6666</device> @@ -150,155 +150,5 @@ <feature> DIRECT2D </feature> <featureStatus> BLOCKED_DEVICE </featureStatus> </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>All</os> - <vendor>0xdcdc</vendor> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> DIRECT3D_11_LAYERS </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - <driverVersion> 8.52.322.1112 </driverVersion> - <driverVersionMax> 8.52.323.1000 </driverVersionMax> - <driverVersionComparator> BETWEEN_EXCLUSIVE </driverVersionComparator> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>All</os> - <vendor>0xdcdc</vendor> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> OPENGL_LAYERS </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - <driverVersion> 8.50.322.1000 </driverVersion> - <driverVersionMax> 8.52.322.1112 </driverVersionMax> - <driverVersionComparator> BETWEEN_EXCLUSIVE </driverVersionComparator> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>All</os> - <vendor>0xdcdc</vendor> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> DIRECT3D_11_ANGLE </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - <driverVersion> 8.52.322.1000 </driverVersion> - <driverVersionMax> 9.52.322.1000 </driverVersionMax> - <driverVersionComparator> BETWEEN_EXCLUSIVE </driverVersionComparator> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>All</os> - <vendor>0xdcdc</vendor> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> HARDWARE_VIDEO_DECODING </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - <driverVersion> 7.82.322.1000 </driverVersion> - <driverVersionMax> 9.25.322.1001 </driverVersionMax> - <driverVersionComparator> BETWEEN_INCLUSIVE </driverVersionComparator> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>All</os> - <vendor>0xdcdc</vendor> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> WEBRTC_HW_ACCELERATION </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - <driverVersion> 8.52.322.1112 </driverVersion> - <driverVersionMax> 9.52.322.1300 </driverVersionMax> - <driverVersionComparator> BETWEEN_INCLUSIVE </driverVersionComparator> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>All</os> - <vendor>0xdcdc</vendor> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> WEBRTC_HW_ACCELERATION_DECODE </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - <driverVersion> 8.52.322.1000 </driverVersion> - <driverVersionMax> 8.52.322.1112 </driverVersionMax> - <driverVersionComparator> BETWEEN_INCLUSIVE </driverVersionComparator> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>All</os> - <vendor>0xdcdc</vendor> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> WEBRTC_HW_ACCELERATION_ENCODE </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - <driverVersion> 8.52.322.1112 </driverVersion> - <driverVersionMax> 8.52.322.1200 </driverVersionMax> - <driverVersionComparator> BETWEEN_INCLUSIVE_START </driverVersionComparator> - </gfxBlacklistEntry> - <gfxBlacklistEntry> - <os>All</os> - <vendor>0xdcdc</vendor> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> WEBGL_MSAA </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - <driverVersion> 8.52.322.1000 </driverVersion> - <driverVersionMax> 8.52.322.1200 </driverVersionMax> - <driverVersionComparator> BETWEEN_INCLUSIVE_START </driverVersionComparator> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>All</os> - <vendor>0xdcdc</vendor> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> WEBGL_ANGLE </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - <driverVersion> 8.52.322.1000 </driverVersion> - <driverVersionMax> 8.52.322.1112 </driverVersionMax> - <driverVersionComparator> BETWEEN_INCLUSIVE_START </driverVersionComparator> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>All</os> - <vendor>0xdcdc</vendor> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> CANVAS2D_ACCELERATION </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - <driverVersion> 8.52.322.1000 </driverVersion> - <driverVersionMax> 9.52.322.1000 </driverVersionMax> - <driverVersionComparator> BETWEEN_EXCLUSIVE </driverVersionComparator> - </gfxBlacklistEntry> - </gfxItems> </blocklist> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_gfxBlacklist_AllOS.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_gfxBlacklist_AllOS.xml index f64676355..22af6f712 100755..100644 --- a/toolkit/mozapps/extensions/test/xpcshell/data/test_gfxBlacklist_AllOS.xml +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_gfxBlacklist_AllOS.xml @@ -2,399 +2,9 @@ <blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist"> <gfxItems> - - <gfxBlacklistEntry blockID="g1"> - <os>All</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="15.0" maxVersion="15.0"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> DIRECT2D </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry blockID="g2"> - <os>All</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="15.0" maxVersion="22.0a1"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> DIRECT3D_9_LAYERS </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>All</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="16.0a1"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> DIRECT3D_10_LAYERS</feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>All</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="16.0a1" maxVersion="22.0"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> DIRECT3D_10_1_LAYERS </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>All</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="12.0" maxVersion="16.0"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> OPENGL_LAYERS </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry blockID="g11"> - <os>All</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="14.0b2" maxVersion="15.0"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> WEBGL_OPENGL </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>All</os> - <vendor>0xabcd</vendor> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> WEBGL_ANGLE </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>All</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="12.0" maxVersion="16.0"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> WEBGL_MSAA </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>All</os> - <vendor>0xabcd</vendor> - <versionRange maxVersion="13.0"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> STAGEFRIGHT </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>All</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="42.0" maxVersion="13.0b2"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> WEBRTC_HW_ACCELERATION </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>All</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="42.0" maxVersion="13.0b2"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> WEBRTC_HW_ACCELERATION_ENCODE </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>All</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="42.0" maxVersion="13.0b2"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> WEBRTC_HW_ACCELERATION_DECODE </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>All</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="17.2a2" maxVersion="15.0"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> DIRECT3D_11_LAYERS </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>All</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="15.0" maxVersion="13.2"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> HARDWARE_VIDEO_DECODING </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - <gfxBlacklistEntry> <os>All</os> <vendor>0xabcd</vendor> - <versionRange minVersion="10.5" maxVersion="13.0"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> DIRECT3D_11_ANGLE </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry blockID="g1"> - <os>Darwin 13</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="15.0" maxVersion="15.0"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> DIRECT2D </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry blockID="g2"> - <os>Darwin 13</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="15.0" maxVersion="22.0a1"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> DIRECT3D_9_LAYERS </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>Darwin 13</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="16.0a1"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> DIRECT3D_10_LAYERS</feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>Darwin 13</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="16.0a1" maxVersion="22.0"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> DIRECT3D_10_1_LAYERS </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>Darwin 13</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="12.0" maxVersion="16.0"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> OPENGL_LAYERS </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry blockID="g11"> - <os>Darwin 13</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="14.0b2" maxVersion="15.0"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> WEBGL_OPENGL </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>Darwin 13</os> - <vendor>0xabcd</vendor> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> WEBGL_ANGLE </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>Darwin 13</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="12.0" maxVersion="16.0"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> WEBGL_MSAA </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>Darwin 13</os> - <vendor>0xabcd</vendor> - <versionRange maxVersion="13.0"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> STAGEFRIGHT </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>Darwin 13</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="42.0" maxVersion="13.0b2"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> WEBRTC_HW_ACCELERATION </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>Darwin 13</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="42.0" maxVersion="13.0b2"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> WEBRTC_HW_ACCELERATION_ENCODE </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>Darwin 13</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="42.0" maxVersion="13.0b2"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> WEBRTC_HW_ACCELERATION_DECODE </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>Darwin 13</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="17.2a2" maxVersion="15.0"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> DIRECT3D_11_LAYERS </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>Darwin 13</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="15.0" maxVersion="13.2"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> HARDWARE_VIDEO_DECODING </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>Darwin 13</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="10.5" maxVersion="13.0"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> DIRECT3D_11_ANGLE </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry blockID="g1"> - <os>Linux</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="15.0" maxVersion="15.0"/> <devices> <device>0x2783</device> <device>0x1234</device> @@ -402,206 +12,12 @@ </devices> <feature> DIRECT2D </feature> <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> + <driverVersion> 8.52.322.2202 </driverVersion> + <driverVersionComparator> LESS_THAN </driverVersionComparator> </gfxBlacklistEntry> - - <gfxBlacklistEntry blockID="g2"> - <os>Linux</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="15.0" maxVersion="22.0a1"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> DIRECT3D_9_LAYERS </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>Linux</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="16.0a1"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> DIRECT3D_10_LAYERS</feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>Linux</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="16.0a1" maxVersion="22.0"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> DIRECT3D_10_1_LAYERS </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>Linux</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="12.0" maxVersion="16.0"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> OPENGL_LAYERS </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry blockID="g11"> - <os>Linux</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="14.0b2" maxVersion="15.0"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> WEBGL_OPENGL </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>Linux</os> - <vendor>0xabcd</vendor> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> WEBGL_ANGLE </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>Linux</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="12.0" maxVersion="16.0"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> WEBGL_MSAA </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>Linux</os> - <vendor>0xabcd</vendor> - <versionRange maxVersion="13.0"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> STAGEFRIGHT </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>Linux</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="42.0" maxVersion="13.0b2"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> WEBRTC_HW_ACCELERATION </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>Linux</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="42.0" maxVersion="13.0b2"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> WEBRTC_HW_ACCELERATION_ENCODE </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - <gfxBlacklistEntry> - <os>Linux</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="42.0" maxVersion="13.0b2"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> WEBRTC_HW_ACCELERATION_DECODE </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>Linux</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="17.2a2" maxVersion="15.0"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> DIRECT3D_11_LAYERS </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>Linux</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="15.0" maxVersion="13.2"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> HARDWARE_VIDEO_DECODING </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>Linux</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="10.5" maxVersion="13.0"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> DIRECT3D_11_ANGLE </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry blockID="g1"> - <os>Android</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="15.0" maxVersion="15.0"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> DIRECT2D </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry blockID="g2"> - <os>Android</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="15.0" maxVersion="22.0a1"/> + <os>WINNT 6.0</os> + <vendor>0xdcba</vendor> <devices> <device>0x2783</device> <device>0x1234</device> @@ -609,175 +25,8 @@ </devices> <feature> DIRECT3D_9_LAYERS </feature> <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> + <driverVersion> 8.52.322.2202 </driverVersion> + <driverVersionComparator> LESS_THAN </driverVersionComparator> </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>Android</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="16.0a1"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> DIRECT3D_10_LAYERS</feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>Android</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="16.0a1" maxVersion="22.0"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> DIRECT3D_10_1_LAYERS </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>Android</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="12.0" maxVersion="16.0"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> OPENGL_LAYERS </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry blockID="g11"> - <os>Android</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="14.0b2" maxVersion="15.0"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> WEBGL_OPENGL </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>Android</os> - <vendor>0xabcd</vendor> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> WEBGL_ANGLE </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>Android</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="12.0" maxVersion="16.0"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> WEBGL_MSAA </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>Android</os> - <vendor>0xabcd</vendor> - <versionRange maxVersion="13.0"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> STAGEFRIGHT </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>Android</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="42.0" maxVersion="13.0b2"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> WEBRTC_HW_ACCELERATION </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>Android</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="42.0" maxVersion="13.0b2"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> WEBRTC_HW_ACCELERATION_ENCODE </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>Android</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="42.0" maxVersion="13.0b2"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> WEBRTC_HW_ACCELERATION_DECODE </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>Android</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="17.2a2" maxVersion="15.0"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> DIRECT3D_11_LAYERS </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>Android</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="15.0" maxVersion="13.2"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> HARDWARE_VIDEO_DECODING </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - - <gfxBlacklistEntry> - <os>Android</os> - <vendor>0xabcd</vendor> - <versionRange minVersion="10.5" maxVersion="13.0"/> - <devices> - <device>0x2783</device> - <device>0x1234</device> - <device>0x2782</device> - </devices> - <feature> DIRECT3D_11_ANGLE </feature> - <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> - </gfxBlacklistEntry> - </gfxItems> </blocklist> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_gfxBlacklist_OSVersion.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_gfxBlacklist_OSVersion.xml index 248868a2e..463207d14 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/data/test_gfxBlacklist_OSVersion.xml +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_gfxBlacklist_OSVersion.xml @@ -16,7 +16,7 @@ <driverVersionComparator> LESS_THAN </driverVersionComparator> </gfxBlacklistEntry> <gfxBlacklistEntry> - <os>Darwin 13</os> + <os>Darwin 12</os> <vendor>0xabcd</vendor> <devices> <device>0x2783</device> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_hotfix_1.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_hotfix_1.rdf deleted file mode 100644 index 016726021..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/test_hotfix_1.rdf +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> - -<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:em="http://www.mozilla.org/2004/em-rdf#"> - - <Description about="urn:mozilla:extension:hotfix@tests.mozilla.org"> - <em:updates> - <Seq> - <li> - <Description> - <em:version>1.0</em:version> - <em:targetApplication> - <Description> - <em:id>xpcshell@tests.mozilla.org</em:id> - <em:minVersion>1</em:minVersion> - <em:maxVersion>1</em:maxVersion> - <em:updateLink>http://localhost:%PORT%/addons/test_hotfix_1.xpi</em:updateLink> - </Description> - </em:targetApplication> - </Description> - </li> - </Seq> - </em:updates> - </Description> - -</RDF> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_hotfix_2.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_hotfix_2.rdf deleted file mode 100644 index 35a2befee..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/test_hotfix_2.rdf +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> - -<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:em="http://www.mozilla.org/2004/em-rdf#"> - - <Description about="urn:mozilla:extension:hotfix@tests.mozilla.org"> - <em:updates> - <Seq> - <li> - <Description> - <em:version>2.0</em:version> - <em:targetApplication> - <Description> - <em:id>xpcshell@tests.mozilla.org</em:id> - <em:minVersion>1</em:minVersion> - <em:maxVersion>1</em:maxVersion> - <em:updateLink>http://localhost:%PORT%/addons/test_hotfix_2.xpi</em:updateLink> - </Description> - </em:targetApplication> - </Description> - </li> - </Seq> - </em:updates> - </Description> - -</RDF> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_hotfix_3.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_hotfix_3.rdf deleted file mode 100644 index 7180da143..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/test_hotfix_3.rdf +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> - -<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:em="http://www.mozilla.org/2004/em-rdf#"> - - <Description about="urn:mozilla:extension:hotfix@tests.mozilla.org"> - <em:updates> - <Seq> - <li> - <Description> - <em:version>3.0</em:version> - <em:targetApplication> - <Description> - <em:id>xpcshell@tests.mozilla.org</em:id> - <em:minVersion>2</em:minVersion> - <em:maxVersion>2</em:maxVersion> - <em:updateLink>http://localhost:%PORT%/addons/test_hotfix_3.xpi</em:updateLink> - </Description> - </em:targetApplication> - </Description> - </li> - </Seq> - </em:updates> - </Description> - -</RDF> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_install.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_install.xml index 33f14a2fd..5f0aab75f 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/data/test_install.xml +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_install.xml @@ -17,7 +17,7 @@ <compatible_applications> <application> <name>Firefox</name> - <appID>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</appID> + <appID>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</appID> <min_version>0</min_version> <max_version>*</max_version> </application> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_no_update.json b/toolkit/mozapps/extensions/test/xpcshell/data/test_no_update.json deleted file mode 100644 index 2773c7f98..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/test_no_update.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "addons": { - "test_no_update_webext@tests.mozilla.org": { - "updates": [] - } - } -} diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_proxy/bootstrap.js b/toolkit/mozapps/extensions/test/xpcshell/data/test_proxy/bootstrap.js deleted file mode 100644 index 1666f2972..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/test_proxy/bootstrap.js +++ /dev/null @@ -1 +0,0 @@ -Components.utils.import("resource://xpcshell-data/BootstrapMonitor.jsm").monitor(this); diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_softblocked1.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_softblocked1.xml deleted file mode 100644 index a1d18470c..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/test_softblocked1.xml +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist"> - <emItems> - <emItem id="softblock1@tests.mozilla.org"> - <versionRange severity="1"/> - </emItem> - </emItems> -</blocklist> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_temporary/bootstrap.js b/toolkit/mozapps/extensions/test/xpcshell/data/test_temporary/bootstrap.js deleted file mode 100644 index 1666f2972..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/test_temporary/bootstrap.js +++ /dev/null @@ -1 +0,0 @@ -Components.utils.import("resource://xpcshell-data/BootstrapMonitor.jsm").monitor(this); diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_update.json b/toolkit/mozapps/extensions/test/xpcshell/data/test_update.json deleted file mode 100644 index 027a9b233..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/test_update.json +++ /dev/null @@ -1,215 +0,0 @@ -{ - "addons": { - "addon1@tests.mozilla.org": { - "updates": [ - { - "version": "1.0", - "applications": { - "gecko": { - "strict_min_version": "1", - "strict_min_version": "1" - } - } - }, - { - "version": "1.0", - "applications": { - "gecko": { - "strict_min_version": "2", - "strict_min_version": "2" - } - } - }, - { - "version": "2.0", - "update_link": "http://localhost:%PORT%/addons/test_update.xpi", - "update_info_url": "http://example.com/updateInfo.xhtml", - "applications": { - "gecko": { - "strict_min_version": "1", - "strict_min_version": "1" - } - } - } - ] - }, - - "addon2@tests.mozilla.org": { - "updates": [ - { - "version": "1.0", - "applications": { - "gecko": { - "strict_min_version": "0", - "advisory_max_version": "1" - } - } - } - ] - }, - - "addon2@tests.mozilla.org": { - "updates": [ - { - "version": "1.0", - "applications": { - "gecko": { - "strict_min_version": "0", - "advisory_max_version": "1" - } - } - } - ] - }, - - "addon3@tests.mozilla.org": { - "updates": [ - { - "version": "1.0", - "applications": { - "gecko": { - "strict_min_version": "3", - "advisory_max_version": "3" - } - } - } - ] - }, - - "addon4@tests.mozilla.org": { - "updates": [ - { - "version": "5.0", - "applications": { - "gecko": { - "strict_min_version": "0", - "advisory_max_version": "0" - } - } - } - ] - }, - - "addon7@tests.mozilla.org": { - "updates": [ - { - "version": "1.0", - "applications": { - "gecko": { - "strict_min_version": "0", - "advisory_max_version": "1" - } - } - } - ] - }, - - "addon8@tests.mozilla.org": { - "updates": [ - { - "version": "2.0", - "update_link": "http://localhost:%PORT%/addons/test_update8.xpi", - "applications": { - "gecko": { - "strict_min_version": "1", - "advisory_max_version": "1" - } - } - } - ] - }, - - "addon9@tests.mozilla.org": { - "updates": [ - { - "version": "2.0", - "update_link": "http://localhost:%PORT%/addons/test_update9_2.xpi", - "applications": { - "gecko": { - "strict_min_version": "1", - "advisory_max_version": "1" - } - } - }, - { - "_comment_": "Incompatible when strict compatibility is enabled", - "version": "3.0", - "update_link": "http://localhost:%PORT%/addons/test_update9_3.xpi", - "applications": { - "gecko": { - "strict_min_version": "0.9", - "advisory_max_version": "0.9" - } - } - }, - { - "_comment_": "Incompatible due to compatibility override", - "version": "4.0", - "update_link": "http://localhost:%PORT%/addons/test_update9_4.xpi", - "applications": { - "gecko": { - "strict_min_version": "0.9", - "advisory_max_version": "0.9" - } - } - }, - { - "_comment_": "Addon for future version of app", - "version": "4.0", - "update_link": "http://localhost:%PORT%/addons/test_update9_5.xpi", - "applications": { - "gecko": { - "strict_min_version": "5", - "advisory_max_version": "6" - } - } - } - ] - }, - - "addon10@tests.mozilla.org": { - "updates": [ - { - "version": "1.0", - "update_link": "http://localhost:%PORT%/addons/test_update10.xpi", - "applications": { - "gecko": { - "strict_min_version": "0.1", - "advisory_max_version": "0.4" - } - } - } - ] - }, - - "addon11@tests.mozilla.org": { - "updates": [ - { - "version": "2.0", - "update_link": "http://localhost:%PORT%/addons/test_update11.xpi", - "applications": { - "gecko": { - "strict_min_version": "0.1", - "strict_max_version": "0.2" - } - } - } - ] - }, - - "addon12@tests.mozilla.org": { - "updates": [ - { - "version": "2.0", - "update_link": "http://localhost:%PORT%/addons/test_update12.xpi", - "applications": { - "gecko": { - "strict_min_version": "1", - "advisory_max_version": "1" - } - } - } - ] - } - } -} diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_update_multi.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_update_multi.rdf deleted file mode 100644 index f28a3f26d..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/test_update_multi.rdf +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:em="http://www.mozilla.org/2004/em-rdf#"> - - <Description about="urn:mozilla:extension:updatemulti@tests.mozilla.org"> - <em:updates> - <Seq> - <li> - <Description> - <em:version>2.0</em:version> - <em:targetApplication> - <Description> - <em:id>xpcshell@tests.mozilla.org</em:id> - <em:minVersion>1</em:minVersion> - <em:maxVersion>1</em:maxVersion> - <em:updateLink>http://localhost:4444/addons/test_update_multi2.xpi</em:updateLink> - </Description> - </em:targetApplication> - </Description> - </li> - </Seq> - </em:updates> - </Description> - -</RDF> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_updatecheck.json b/toolkit/mozapps/extensions/test/xpcshell/data/test_updatecheck.json deleted file mode 100644 index 811e50158..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/test_updatecheck.json +++ /dev/null @@ -1,327 +0,0 @@ -{ - "addons": { - "updatecheck1@tests.mozilla.org": { - "updates": [ - { - "version": "1.0", - "update_link": "https://localhost:4444/addons/test1.xpi", - "applications": { - "gecko": { - "strict_min_version": "1", - "strict_max_version": "1" - } - } - }, - { - "_comment_": "This update is incompatible and so should not be considered a valid update", - "version": "2.0", - "update_link": "https://localhost:4444/addons/test2.xpi", - "applications": { - "gecko": { - "strict_min_version": "2", - "strict_max_version": "2" - } - } - }, - { - "version": "3.0", - "update_link": "https://localhost:4444/addons/test3.xpi", - "applications": { - "gecko": { - "strict_min_version": "1", - "strict_max_version": "1" - } - } - }, - { - "version": "2.0", - "update_link": "https://localhost:4444/addons/test2.xpi", - "applications": { - "gecko": { - "strict_min_version": "1", - "strict_max_version": "2" - } - } - }, - { - "_comment_": "This update is incompatible and so should not be considered a valid update", - "version": "4.0", - "update_link": "https://localhost:4444/addons/test4.xpi", - "applications": { - "gecko": { - "strict_min_version": "2", - "strict_max_version": "2" - } - } - } - ] - }, - - "test_bug378216_5@tests.mozilla.org": { - "_comment_": "An update which expects a signature. It will fail since signatures are ", - "_comment_": "supported in this format.", - "_comment_": "The updateLink will also be ignored since it is not secure and there ", - "_comment_": "is no updateHash.", - - "updates": [ - { - "version": "2.0", - "update_link": "http://localhost:4444/broken.xpi", - "applications": { - "gecko": { - "strict_min_version": "1", - "strict_max_version": "1" - } - } - } - ] - }, - - "test_bug378216_5@tests.mozilla.org": { - "updates": [ - { - "version": "2.0", - "update_link": "http://localhost:4444/broken.xpi", - "applications": { - "gecko": { - "strict_min_version": "1", - "strict_max_version": "1" - } - } - } - ] - }, - - "test_bug378216_7@tests.mozilla.org": { - "_comment_": "An update which expects a signature. It will fail since signatures are ", - "_comment_": "supported in this format.", - "_comment_": "The updateLink will also be ignored since it is not secure ", - "_comment_": "and there is no updateHash.", - - "updates": [ - { - "version": "2.0", - "update_link": "http://localhost:4444/broken.xpi", - "applications": { - "gecko": { - "strict_min_version": "1", - "strict_max_version": "2" - } - } - } - ] - }, - - "test_bug378216_8@tests.mozilla.org": { - "_comment_": "The updateLink will be ignored since it is not secure and ", - "_comment_": "there is no updateHash.", - - "updates": [ - { - "version": "2.0", - "update_link": "http://localhost:4444/broken.xpi", - "applications": { - "gecko": { - "strict_min_version": "1", - "strict_max_version": "1" - } - } - } - ] - }, - - "test_bug378216_9@tests.mozilla.org": { - "_comment_": "The updateLink will used since there is an updateHash to verify it.", - - "updates": [ - { - "version": "2.0", - "update_link": "http://localhost:4444/broken.xpi", - "update_hash": "sha256:78fc1d2887eda35b4ad2e3a0b60120ca271ce6e6", - "applications": { - "gecko": { - "strict_min_version": "1", - "strict_max_version": "1" - } - } - } - ] - }, - - "test_bug378216_10@tests.mozilla.org": { - "_comment_": "The updateLink will used since it is a secure URL.", - - "updates": [ - { - "version": "2.0", - "update_link": "https://localhost:4444/broken.xpi", - "applications": { - "gecko": { - "strict_min_version": "1", - "strict_max_version": "1" - } - } - } - ] - }, - - "test_bug378216_11@tests.mozilla.org": { - "_comment_": "The updateLink will used since it is a secure URL.", - - "updates": [ - { - "version": "2.0", - "update_link": "https://localhost:4444/broken.xpi", - "applications": { - "gecko": { - "strict_min_version": "1", - "strict_max_version": "1" - } - } - } - ] - }, - - "test_bug378216_12@tests.mozilla.org": { - "_comment_": "The updateLink will not be used since the updateHash ", - "_comment_": "verifying it is not strong enough.", - - "updates": [ - { - "version": "2.0", - "update_link": "http://localhost:4444/broken.xpi", - "update_hash": "sha1:78fc1d2887eda35b4ad2e3a0b60120ca271ce6e6", - "applications": { - "gecko": { - "strict_min_version": "1", - "strict_max_version": "1" - } - } - } - ] - }, - - "test_bug378216_13@tests.mozilla.org": { - "_comment_": "An update with a weak hash. The updateLink will used since it is ", - "_comment_": "a secure URL.", - - "updates": [ - { - "version": "2.0", - "update_link": "https://localhost:4444/broken.xpi", - "update_hash": "sha1:78fc1d2887eda35b4ad2e3a0b60120ca271ce6e6", - "applications": { - "gecko": { - "strict_min_version": "1", - "strict_max_version": "1" - } - } - } - ] - }, - - "_comment_": "There should be no information present for test_bug378216_14", - - "test_bug378216_15@tests.mozilla.org": { - "_comment_": "Invalid update JSON", - - "updates": "foo" - }, - - "ignore-compat@tests.mozilla.org": { - "_comment_": "Various updates available - one is not compatible, but compatibility checking is disabled", - - "updates": [ - { - "version": "1.0", - "update_link": "https://localhost:4444/addons/test1.xpi", - "applications": { - "gecko": { - "strict_min_version": "0.1", - "advisory_max_version": "0.2" - } - } - }, - { - "version": "2.0", - "update_link": "https://localhost:4444/addons/test2.xpi", - "applications": { - "gecko": { - "strict_min_version": "0.5", - "advisory_max_version": "0.6" - } - } - }, - { - "_comment_": "Update for future app versions - should never be compatible", - "version": "3.0", - "update_link": "https://localhost:4444/addons/test3.xpi", - "applications": { - "gecko": { - "strict_min_version": "2", - "advisory_max_version": "3" - } - } - } - ] - }, - - "compat-override@tests.mozilla.org": { - "_comment_": "Various updates available - one is not compatible, but compatibility checking is disabled", - - "updates": [ - { - "_comment_": "Has compatibility override, but it doesn't match this app version", - "version": "1.0", - "update_link": "https://localhost:4444/addons/test1.xpi", - "applications": { - "gecko": { - "strict_min_version": "0.1", - "advisory_max_version": "0.2" - } - } - }, - { - "_comment_": "Has compatibility override, so is incompaible", - "version": "2.0", - "update_link": "https://localhost:4444/addons/test2.xpi", - "applications": { - "gecko": { - "strict_min_version": "0.5", - "advisory_max_version": "0.6" - } - } - }, - { - "_comment_": "Update for future app versions - should never be compatible", - "version": "3.0", - "update_link": "https://localhost:4444/addons/test3.xpi", - "applications": { - "gecko": { - "strict_min_version": "2", - "advisory_max_version": "3" - } - } - } - ] - }, - - "compat-strict-optin@tests.mozilla.org": { - "_comment_": "Opt-in to strict compatibility checking", - - "updates": [ - { - "version": "1.0", - "update_link": "https://localhost:4444/addons/test1.xpi", - "_comment_": "strictCompatibility: true", - "applications": { - "gecko": { - "strict_min_version": "0.1", - "strict_max_version": "0.2" - } - } - } - ] - } - } -} diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_updatecheck.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_updatecheck.rdf index c5d97ada0..93c82886a 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/data/test_updatecheck.rdf +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_updatecheck.rdf @@ -236,7 +236,7 @@ A90eF5zy</em:signature> </RDF:Description> - <!-- An update with a valid signature. The updateLink will not be used since the + <!-- An update with a valid signature. The updateLink will used since the updateHash verifying it is not strong enough. --> <RDF:Description about="urn:mozilla:extension:test_bug378216_12@tests.mozilla.org"> <em:updates> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_updateid.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_updateid.rdf index c13928520..d59df9736 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/data/test_updateid.rdf +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_updateid.rdf @@ -14,7 +14,67 @@ <em:id>xpcshell@tests.mozilla.org</em:id> <em:minVersion>1</em:minVersion> <em:maxVersion>1</em:maxVersion> - <em:updateLink>http://localhost:4444/addons/test_updateid2.xpi</em:updateLink> + <em:updateLink>http://localhost:4444/addons/test_updateid2_2.xpi</em:updateLink> + </Description> + </em:targetApplication> + </Description> + </li> + </Seq> + </em:updates> + </Description> + + <Description about="urn:mozilla:extension:addon2@tests.mozilla.org"> + <em:updates> + <Seq> + <li> + <Description> + <em:version>3.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + <em:updateLink>http://localhost:4444/addons/test_updateid3_3.xpi</em:updateLink> + </Description> + </em:targetApplication> + </Description> + </li> + </Seq> + </em:updates> + </Description> + + <Description about="urn:mozilla:extension:addon3@tests.mozilla.org"> + <em:updates> + <Seq> + <li> + <Description> + <em:version>4.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + <em:updateLink>http://localhost:4444/addons/test_updateid4_4.xpi</em:updateLink> + </Description> + </em:targetApplication> + </Description> + </li> + </Seq> + </em:updates> + </Description> + + <Description about="urn:mozilla:extension:addon4@tests.mozilla.org"> + <em:updates> + <Seq> + <li> + <Description> + <em:version>5.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + <em:updateLink>http://localhost:4444/addons/test_updateid2_5.xpi</em:updateLink> </Description> </em:targetApplication> </Description> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/webext-implicit-id.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/webext-implicit-id.xpi Binary files differdeleted file mode 100644 index 6b4abaa69..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/webext-implicit-id.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpcshell/head_addons.js b/toolkit/mozapps/extensions/test/xpcshell/head_addons.js index 960caceeb..60259944e 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/head_addons.js +++ b/toolkit/mozapps/extensions/test/xpcshell/head_addons.js @@ -2,14 +2,11 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -var AM_Cc = Components.classes; -var AM_Ci = Components.interfaces; -var AM_Cu = Components.utils; +const AM_Cc = Components.classes; +const AM_Ci = Components.interfaces; -AM_Cu.importGlobalProperties(["TextEncoder"]); - -const CERTDB_CONTRACTID = "@mozilla.org/security/x509certdb;1"; -const CERTDB_CID = Components.ID("{fb0bbc5c-452e-4783-b32c-80124693d871}"); +const XULAPPINFO_CONTRACTID = "@mozilla.org/xre/app-info;1"; +const XULAPPINFO_CID = Components.ID("{c763b610-9d49-455a-bbd2-ede71682a1ac}"); const PREF_EM_CHECK_UPDATE_SECURITY = "extensions.checkUpdateSecurity"; const PREF_EM_STRICT_COMPATIBILITY = "extensions.strictCompatibility"; @@ -17,20 +14,10 @@ const PREF_EM_MIN_COMPAT_APP_VERSION = "extensions.minCompatibleAppVersion" const PREF_EM_MIN_COMPAT_PLATFORM_VERSION = "extensions.minCompatiblePlatformVersion"; const PREF_GETADDONS_BYIDS = "extensions.getAddons.get.url"; const PREF_GETADDONS_BYIDS_PERFORMANCE = "extensions.getAddons.getWithPerformance.url"; -const PREF_XPI_SIGNATURES_REQUIRED = "xpinstall.signatures.required"; // Forcibly end the test if it runs longer than 15 minutes const TIMEOUT_MS = 900000; -// Maximum error in file modification times. Some file systems don't store -// modification times exactly. As long as we are closer than this then it -// still passes. -const MAX_TIME_DIFFERENCE = 3000; - -// Time to reset file modified time relative to Date.now() so we can test that -// times are modified (10 hours old). -const MAKE_FILE_OLD_DIFFERENCE = 10 * 3600 * 1000; - Components.utils.import("resource://gre/modules/addons/AddonRepository.jsm"); Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); Components.utils.import("resource://gre/modules/FileUtils.jsm"); @@ -38,300 +25,41 @@ Components.utils.import("resource://gre/modules/Services.jsm"); Components.utils.import("resource://gre/modules/NetUtil.jsm"); Components.utils.import("resource://gre/modules/Promise.jsm"); Components.utils.import("resource://gre/modules/Task.jsm"); -const { OS } = Components.utils.import("resource://gre/modules/osfile.jsm", {}); +Components.utils.import("resource://gre/modules/osfile.jsm"); Components.utils.import("resource://gre/modules/AsyncShutdown.jsm"); -Components.utils.import("resource://testing-common/AddonTestUtils.jsm"); - -XPCOMUtils.defineLazyModuleGetter(this, "Extension", - "resource://gre/modules/Extension.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "ExtensionTestUtils", - "resource://testing-common/ExtensionXPCShellUtils.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "HttpServer", - "resource://testing-common/httpd.js"); -XPCOMUtils.defineLazyModuleGetter(this, "MockAsyncShutdown", - "resource://testing-common/AddonTestUtils.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "MockRegistrar", - "resource://testing-common/MockRegistrar.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "MockRegistry", - "resource://testing-common/MockRegistry.jsm"); - -const { - awaitPromise, - createAppInfo, - createInstallRDF, - createTempWebExtensionFile, - createUpdateRDF, - getFileForAddon, - manuallyInstall, - manuallyUninstall, - promiseAddonByID, - promiseAddonEvent, - promiseAddonsByIDs, - promiseAddonsWithOperationsByTypes, - promiseCompleteAllInstalls, - promiseConsoleOutput, - promiseFindAddonUpdates, - promiseInstallAllFiles, - promiseInstallFile, - promiseRestartManager, - promiseSetExtensionModifiedTime, - promiseShutdownManager, - promiseStartupManager, - promiseWriteProxyFileToDir, - registerDirectory, - setExtensionModifiedTime, - writeFilesToZip -} = AddonTestUtils; - -// WebExtension wrapper for ease of testing -ExtensionTestUtils.init(this); - -AddonTestUtils.init(this); -AddonTestUtils.overrideCertDB(); - -Object.defineProperty(this, "gAppInfo", { - get() { - return AddonTestUtils.appInfo; - }, -}); - -Object.defineProperty(this, "gExtensionsINI", { - get() { - return AddonTestUtils.extensionsINI.clone(); - }, -}); - -Object.defineProperty(this, "gInternalManager", { - get() { - return AddonTestUtils.addonIntegrationService.QueryInterface(AM_Ci.nsITimerCallback); - }, -}); - -Object.defineProperty(this, "gProfD", { - get() { - return AddonTestUtils.profileDir.clone(); - }, -}); - -Object.defineProperty(this, "gTmpD", { - get() { - return AddonTestUtils.tempDir.clone(); - }, -}); - -Object.defineProperty(this, "gUseRealCertChecks", { - get() { - return AddonTestUtils.useRealCertChecks; - }, - set(val) { - return AddonTestUtils.useRealCertChecks = val; - }, -}); - -Object.defineProperty(this, "TEST_UNPACKED", { - get() { - return AddonTestUtils.testUnpacked; - }, - set(val) { - return AddonTestUtils.testUnpacked = val; - }, -}); +Services.prefs.setBoolPref("toolkit.osfile.log", true); // We need some internal bits of AddonManager -var AMscope = Components.utils.import("resource://gre/modules/AddonManager.jsm", {}); -var { AddonManager, AddonManagerInternal, AddonManagerPrivate } = AMscope; - -var gPort = null; -var gUrlToFileMap = {}; - -// Map resource://xpcshell-data/ to the data directory -var resHandler = Services.io.getProtocolHandler("resource") - .QueryInterface(AM_Ci.nsISubstitutingProtocolHandler); -// Allow non-existent files because of bug 1207735 -var dataURI = NetUtil.newURI(do_get_file("data", true)); -resHandler.setSubstitution("xpcshell-data", dataURI); - -function isManifestRegistered(file) { - let manifests = Components.manager.getManifestLocations(); - for (let i = 0; i < manifests.length; i++) { - let manifest = manifests.queryElementAt(i, AM_Ci.nsIURI); - - // manifest is the url to the manifest file either in an XPI or a directory. - // We want the location of the XPI or directory itself. - if (manifest instanceof AM_Ci.nsIJARURI) { - manifest = manifest.JARFile.QueryInterface(AM_Ci.nsIFileURL).file; - } - else if (manifest instanceof AM_Ci.nsIFileURL) { - manifest = manifest.file.parent; - } - else { - continue; - } - - if (manifest.equals(file)) - return true; - } - return false; -} - -// Listens to messages from bootstrap.js telling us what add-ons were started -// and stopped etc. and performs some sanity checks that only installed add-ons -// are started etc. -this.BootstrapMonitor = { - inited: false, - - // Contain the current state of add-ons in the system - installed: new Map(), - started: new Map(), - - // Contain the last state of shutdown and uninstall calls for an add-on - stopped: new Map(), - uninstalled: new Map(), - - startupPromises: [], - installPromises: [], - - init() { - this.inited = true; - Services.obs.addObserver(this, "bootstrapmonitor-event", false); - }, - - shutdownCheck() { - if (!this.inited) - return; - - do_check_eq(this.started.size, 0); - }, - - clear(id) { - this.installed.delete(id); - this.started.delete(id); - this.stopped.delete(id); - this.uninstalled.delete(id); - }, - - promiseAddonStartup(id) { - return new Promise(resolve => { - this.startupPromises.push(resolve); - }); - }, - - promiseAddonInstall(id) { - return new Promise(resolve => { - this.installPromises.push(resolve); - }); - }, - - checkMatches(cached, current) { - do_check_neq(cached, undefined); - do_check_eq(current.data.version, cached.data.version); - do_check_eq(current.data.installPath, cached.data.installPath); - do_check_eq(current.data.resourceURI, cached.data.resourceURI); - }, - - checkAddonStarted(id, version = undefined) { - let started = this.started.get(id); - do_check_neq(started, undefined); - if (version != undefined) - do_check_eq(started.data.version, version); - - // Chrome should be registered by now - let installPath = new FileUtils.File(started.data.installPath); - let isRegistered = isManifestRegistered(installPath); - do_check_true(isRegistered); - }, - - checkAddonNotStarted(id) { - do_check_false(this.started.has(id)); - }, - - checkAddonInstalled(id, version = undefined) { - const installed = this.installed.get(id); - notEqual(installed, undefined); - if (version !== undefined) { - equal(installed.data.version, version); +let AMscope = Components.utils.import("resource://gre/modules/AddonManager.jsm"); +let AddonManager = AMscope.AddonManager; +let AddonManagerInternal = AMscope.AddonManagerInternal; +// Mock out AddonManager's reference to the AsyncShutdown module so we can shut +// down AddonManager from the test +let MockAsyncShutdown = { + hook: null, + status: null, + profileBeforeChange: { + addBlocker: function(aName, aBlocker, aOptions) { + do_print("Mock profileBeforeChange blocker for '" + aName + "'"); + MockAsyncShutdown.hook = aBlocker; + MockAsyncShutdown.status = aOptions.fetchState; } - return installed; }, + // We can use the real Barrier + Barrier: AsyncShutdown.Barrier +}; - checkAddonNotInstalled(id) { - do_check_false(this.installed.has(id)); - }, - - observe(subject, topic, data) { - let info = JSON.parse(data); - let id = info.data.id; - let installPath = new FileUtils.File(info.data.installPath); - - if (subject && subject.wrappedJSObject) { - // NOTE: in some of the new tests, we need to received the real objects instead of - // their JSON representations, but most of the current tests expect intallPath - // and resourceURI to have been converted to strings. - info.data = Object.assign({}, subject.wrappedJSObject.data, { - installPath: info.data.installPath, - resourceURI: info.data.resourceURI, - }); - } - - // If this is the install event the add-ons shouldn't already be installed - if (info.event == "install") { - this.checkAddonNotInstalled(id); - - this.installed.set(id, info); - - for (let resolve of this.installPromises) - resolve(); - this.installPromises = []; - } - else { - this.checkMatches(this.installed.get(id), info); - } - - // If this is the shutdown event than the add-on should already be started - if (info.event == "shutdown") { - this.checkMatches(this.started.get(id), info); - - this.started.delete(id); - this.stopped.set(id, info); - - // Chrome should still be registered at this point - let isRegistered = isManifestRegistered(installPath); - do_check_true(isRegistered); - - // XPIProvider doesn't bother unregistering chrome on app shutdown but - // since we simulate restarts we must do so manually to keep the registry - // consistent. - if (info.reason == 2 /* APP_SHUTDOWN */) - Components.manager.removeBootstrappedManifestLocation(installPath); - } - else { - this.checkAddonNotStarted(id); - } - - if (info.event == "uninstall") { - // Chrome should be unregistered at this point - let isRegistered = isManifestRegistered(installPath); - do_check_false(isRegistered); - - this.installed.delete(id); - this.uninstalled.set(id, info) - } - else if (info.event == "startup") { - this.started.set(id, info); +AMscope.AsyncShutdown = MockAsyncShutdown; - // Chrome should be registered at this point - let isRegistered = isManifestRegistered(installPath); - do_check_true(isRegistered); +var gInternalManager = null; +var gAppInfo = null; +var gAddonsList; - for (let resolve of this.startupPromises) - resolve(); - this.startupPromises = []; - } - } -} +var gPort = null; +var gUrlToFileMap = {}; -AddonTestUtils.on("addon-manager-shutdown", () => BootstrapMonitor.shutdownCheck()); +var TEST_UNPACKED = false; function isNightlyChannel() { var channel = "default"; @@ -343,6 +71,51 @@ function isNightlyChannel() { return channel != "aurora" && channel != "beta" && channel != "release" && channel != "esr"; } +function createAppInfo(id, name, version, platformVersion) { + gAppInfo = { + // nsIXULAppInfo + vendor: "Mozilla", + name: name, + ID: id, + version: version, + appBuildID: "2007010101", + platformVersion: platformVersion ? platformVersion : "1.0", + platformBuildID: "2007010101", + + // nsIXULRuntime + inSafeMode: false, + logConsoleErrors: true, + OS: "XPCShell", + XPCOMABI: "noarch-spidermonkey", + invalidateCachesOnRestart: function invalidateCachesOnRestart() { + // Do nothing + }, + + // nsICrashReporter + annotations: {}, + + annotateCrashReport: function(key, data) { + this.annotations[key] = data; + }, + + QueryInterface: XPCOMUtils.generateQI([AM_Ci.nsIXULAppInfo, + AM_Ci.nsIXULRuntime, + AM_Ci.nsICrashReporter, + AM_Ci.nsISupports]) + }; + + var XULAppInfoFactory = { + createInstance: function (outer, iid) { + if (outer != null) + throw Components.results.NS_ERROR_NO_AGGREGATION; + return gAppInfo.QueryInterface(iid); + } + }; + var registrar = Components.manager.QueryInterface(AM_Ci.nsIComponentRegistrar); + registrar.registerFactory(XULAPPINFO_CID, "XULAppInfo", + XULAPPINFO_CONTRACTID, XULAppInfoFactory); +} + /** * Tests that an add-on does appear in the crash report annotations, if * crash reporting is enabled. The test will fail if the add-on is not in the @@ -418,11 +191,11 @@ function do_get_file_hash(aFile, aAlgorithm) { crypto.updateFromStream(fis, aFile.fileSize); // return the two-digit hexadecimal code for a byte - let toHexString = charCode => ("0" + charCode.toString(16)).slice(-2); + function toHexString(charCode) + ("0" + charCode.toString(16)).slice(-2); let binary = crypto.finish(false); - let hash = Array.from(binary, c => toHexString(c.charCodeAt(0))); - return aAlgorithm + ":" + hash.join(""); + return aAlgorithm + ":" + [toHexString(binary.charCodeAt(i)) for (i in binary)].join("") } /** @@ -439,7 +212,9 @@ function do_get_addon_root_uri(aProfileDir, aId) { path.leafName += ".xpi"; return "jar:" + Services.io.newFileURI(path).spec + "!/"; } - return Services.io.newFileURI(path).spec; + else { + return Services.io.newFileURI(path).spec; + } } function do_get_expected_addon_name(aId) { @@ -601,8 +376,54 @@ function do_check_icons(aActual, aExpected) { } } +// Record the error (if any) from trying to save the XPI +// database at shutdown time +let gXPISaveError = null; + +/** + * Starts up the add-on manager as if it was started by the application. + * + * @param aAppChanged + * An optional boolean parameter to simulate the case where the + * application has changed version since the last run. If not passed it + * defaults to true + */ function startupManager(aAppChanged) { - promiseStartupManager(aAppChanged); + if (gInternalManager) + do_throw("Test attempt to startup manager that was already started."); + + if (aAppChanged || aAppChanged === undefined) { + if (gExtensionsINI.exists()) + gExtensionsINI.remove(true); + } + + gInternalManager = AM_Cc["@mozilla.org/addons/integration;1"]. + getService(AM_Ci.nsIObserver). + QueryInterface(AM_Ci.nsITimerCallback); + + gInternalManager.observe(null, "addons-startup", null); + + // Load the add-ons list as it was after extension registration + loadAddonsList(); +} + +/** + * Helper to spin the event loop until a promise resolves or rejects + */ +function loopUntilPromise(aPromise) { + let done = false; + aPromise.then( + () => done = true, + err => { + do_report_unexpected_exception(err); + done = true; + }); + + let thr = Services.tm.mainThread; + + while (!done) { + thr.processNextEvent(true); + } } /** @@ -614,36 +435,270 @@ function startupManager(aAppChanged) { * the application version has changed. */ function restartManager(aNewVersion) { - awaitPromise(promiseRestartManager(aNewVersion)); + loopUntilPromise(promiseRestartManager(aNewVersion)); +} + +function promiseRestartManager(aNewVersion) { + return promiseShutdownManager() + .then(null, err => do_report_unexpected_exception(err)) + .then(() => { + if (aNewVersion) { + gAppInfo.version = aNewVersion; + startupManager(true); + } + else { + startupManager(false); + } + }); } function shutdownManager() { - awaitPromise(promiseShutdownManager()); + loopUntilPromise(promiseShutdownManager()); +} + +function promiseShutdownManager() { + if (!gInternalManager) { + return Promise.resolve(false); + } + + let hookErr = null; + Services.obs.notifyObservers(null, "quit-application-granted", null); + return MockAsyncShutdown.hook() + .then(null, err => hookErr = err) + .then( () => { + gInternalManager = null; + + // Load the add-ons list as it was after application shutdown + loadAddonsList(); + + // Clear any crash report annotations + gAppInfo.annotations = {}; + + // Force the XPIProvider provider to reload to better + // simulate real-world usage. + let XPIscope = Components.utils.import("resource://gre/modules/addons/XPIProvider.jsm"); + // This would be cleaner if I could get it as the rejection reason from + // the AddonManagerInternal.shutdown() promise + gXPISaveError = XPIscope.XPIProvider._shutdownError; + do_print("gXPISaveError set to: " + gXPISaveError); + AddonManagerPrivate.unregisterProvider(XPIscope.XPIProvider); + Components.utils.unload("resource://gre/modules/addons/XPIProvider.jsm"); + if (hookErr) { + throw hookErr; + } + }); +} + +function loadAddonsList() { + function readDirectories(aSection) { + var dirs = []; + var keys = parser.getKeys(aSection); + while (keys.hasMore()) { + let descriptor = parser.getString(aSection, keys.getNext()); + try { + let file = AM_Cc["@mozilla.org/file/local;1"]. + createInstance(AM_Ci.nsIFile); + file.persistentDescriptor = descriptor; + dirs.push(file); + } + catch (e) { + // Throws if the directory doesn't exist, we can ignore this since the + // platform will too. + } + } + return dirs; + } + + gAddonsList = { + extensions: [], + themes: [], + mpIncompatible: new Set() + }; + + if (!gExtensionsINI.exists()) + return; + + var factory = AM_Cc["@mozilla.org/xpcom/ini-parser-factory;1"]. + getService(AM_Ci.nsIINIParserFactory); + var parser = factory.createINIParser(gExtensionsINI); + gAddonsList.extensions = readDirectories("ExtensionDirs"); + gAddonsList.themes = readDirectories("ThemeDirs"); + var keys = parser.getKeys("MultiprocessIncompatibleExtensions"); + while (keys.hasMore()) { + let id = parser.getString("MultiprocessIncompatibleExtensions", keys.getNext()); + gAddonsList.mpIncompatible.add(id); + } +} + +function isItemInAddonsList(aType, aDir, aId) { + var path = aDir.clone(); + path.append(aId); + var xpiPath = aDir.clone(); + xpiPath.append(aId + ".xpi"); + for (var i = 0; i < gAddonsList[aType].length; i++) { + let file = gAddonsList[aType][i]; + if (!file.exists()) + do_throw("Non-existant path found in extensions.ini: " + file.path) + if (file.isDirectory() && file.equals(path)) + return true; + if (file.isFile() && file.equals(xpiPath)) + return true; + } + return false; } function isItemMarkedMPIncompatible(aId) { - return AddonTestUtils.addonsList.isMultiprocessIncompatible(aId); + return gAddonsList.mpIncompatible.has(aId); } function isThemeInAddonsList(aDir, aId) { - return AddonTestUtils.addonsList.hasTheme(aDir, aId); + return isItemInAddonsList("themes", aDir, aId); } function isExtensionInAddonsList(aDir, aId) { - return AddonTestUtils.addonsList.hasExtension(aDir, aId); + return isItemInAddonsList("extensions", aDir, aId); } function check_startup_changes(aType, aIds) { var ids = aIds.slice(0); ids.sort(); var changes = AddonManager.getStartupChanges(aType); - changes = changes.filter(aEl => /@tests.mozilla.org$/.test(aEl)); + changes = changes.filter(function(aEl) /@tests.mozilla.org$/.test(aEl)); changes.sort(); do_check_eq(JSON.stringify(ids), JSON.stringify(changes)); } /** + * Escapes any occurances of &, ", < or > with XML entities. + * + * @param str + * The string to escape + * @return The escaped string + */ +function escapeXML(aStr) { + return aStr.toString() + .replace(/&/g, "&") + .replace(/"/g, """) + .replace(/</g, "<") + .replace(/>/g, ">"); +} + +function writeLocaleStrings(aData) { + let rdf = ""; + ["name", "description", "creator", "homepageURL"].forEach(function(aProp) { + if (aProp in aData) + rdf += "<em:" + aProp + ">" + escapeXML(aData[aProp]) + "</em:" + aProp + ">\n"; + }); + + ["developer", "translator", "contributor"].forEach(function(aProp) { + if (aProp in aData) { + aData[aProp].forEach(function(aValue) { + rdf += "<em:" + aProp + ">" + escapeXML(aValue) + "</em:" + aProp + ">\n"; + }); + } + }); + return rdf; +} + +/** + * Creates an update.rdf structure as a string using for the update data passed. + * + * @param aData + * The update data as a JS object. Each property name is an add-on ID, + * the property value is an array of each version of the add-on. Each + * array value is a JS object containing the data for the version, at + * minimum a "version" and "targetApplications" property should be + * included to create a functional update manifest. + * @return the update.rdf structure as a string. + */ +function createUpdateRDF(aData) { + var rdf = '<?xml version="1.0"?>\n'; + rdf += '<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"\n' + + ' xmlns:em="http://www.mozilla.org/2004/em-rdf#">\n'; + + for (let addon in aData) { + rdf += ' <Description about="urn:mozilla:extension:' + escapeXML(addon) + '"><em:updates><Seq>\n'; + + for (let versionData of aData[addon]) { + rdf += ' <li><Description>\n'; + + for (let prop of ["version", "multiprocessCompatible"]) { + if (prop in versionData) + rdf += " <em:" + prop + ">" + escapeXML(versionData[prop]) + "</em:" + prop + ">\n"; + } + + if ("targetApplications" in versionData) { + for (let app of versionData.targetApplications) { + rdf += " <em:targetApplication><Description>\n"; + for (let prop of ["id", "minVersion", "maxVersion", "updateLink", "updateHash"]) { + if (prop in app) + rdf += " <em:" + prop + ">" + escapeXML(app[prop]) + "</em:" + prop + ">\n"; + } + rdf += " </Description></em:targetApplication>\n"; + } + } + + rdf += ' </Description></li>\n'; + } + + rdf += ' </Seq></em:updates></Description>\n' + } + rdf += "</RDF>\n"; + + return rdf; +} + +function createInstallRDF(aData) { + var rdf = '<?xml version="1.0"?>\n'; + rdf += '<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"\n' + + ' xmlns:em="http://www.mozilla.org/2004/em-rdf#">\n'; + rdf += '<Description about="urn:mozilla:install-manifest">\n'; + + ["id", "version", "type", "internalName", "updateURL", "updateKey", + "optionsURL", "optionsType", "aboutURL", "iconURL", "icon64URL", + "skinnable", "bootstrap", "strictCompatibility", "multiprocessCompatible"].forEach(function(aProp) { + if (aProp in aData) + rdf += "<em:" + aProp + ">" + escapeXML(aData[aProp]) + "</em:" + aProp + ">\n"; + }); + + rdf += writeLocaleStrings(aData); + + if ("targetPlatforms" in aData) { + aData.targetPlatforms.forEach(function(aPlatform) { + rdf += "<em:targetPlatform>" + escapeXML(aPlatform) + "</em:targetPlatform>\n"; + }); + } + + if ("targetApplications" in aData) { + aData.targetApplications.forEach(function(aApp) { + rdf += "<em:targetApplication><Description>\n"; + ["id", "minVersion", "maxVersion"].forEach(function(aProp) { + if (aProp in aApp) + rdf += "<em:" + aProp + ">" + escapeXML(aApp[aProp]) + "</em:" + aProp + ">\n"; + }); + rdf += "</Description></em:targetApplication>\n"; + }); + } + + if ("localized" in aData) { + aData.localized.forEach(function(aLocalized) { + rdf += "<em:localized><Description>\n"; + if ("locale" in aLocalized) { + aLocalized.locale.forEach(function(aLocaleName) { + rdf += "<em:locale>" + escapeXML(aLocaleName) + "</em:locale>\n"; + }); + } + rdf += writeLocaleStrings(aLocalized); + rdf += "</Description></em:localized>\n"; + }); + } + + rdf += "</Description>\n</RDF>\n"; + return rdf; +} + +/** * Writes an install.rdf manifest into a directory using the properties passed * in a JS object. The objects should contain a property for each property to * appear in the RDF. The object may contain an array of objects with id, @@ -660,22 +715,38 @@ function check_startup_changes(aType, aIds) { * An optional dummy file to create in the directory * @return An nsIFile for the directory in which the add-on is installed. */ -function writeInstallRDFToDir(aData, aDir, aId = aData.id, aExtraFile = null) { - let files = { - "install.rdf": AddonTestUtils.createInstallRDF(aData), - }; - if (aExtraFile) - files[aExtraFile] = ""; - - let dir = aDir.clone(); - dir.append(aId); - - awaitPromise(AddonTestUtils.promiseWriteFilesToDir(dir.path, files)); +function writeInstallRDFToDir(aData, aDir, aId, aExtraFile) { + var id = aId ? aId : aData.id + + var dir = aDir.clone(); + dir.append(id); + + var rdf = createInstallRDF(aData); + if (!dir.exists()) + dir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY); + var file = dir.clone(); + file.append("install.rdf"); + if (file.exists()) + file.remove(true); + var fos = AM_Cc["@mozilla.org/network/file-output-stream;1"]. + createInstance(AM_Ci.nsIFileOutputStream); + fos.init(file, + FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE | FileUtils.MODE_TRUNCATE, + FileUtils.PERMS_FILE, 0); + fos.write(rdf, rdf.length); + fos.close(); + + if (!aExtraFile) + return dir; + + file = dir.clone(); + file.append(aExtraFile); + file.create(AM_Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); return dir; } /** - * Writes an install.rdf manifest into a packed extension using the properties passed + * Writes an install.rdf manifest into an extension using the properties passed * in a JS object. The objects should contain a property for each property to * appear in the RDF. The object may contain an array of objects with id, * minVersion and maxVersion in the targetApplications property to give target @@ -691,26 +762,15 @@ function writeInstallRDFToDir(aData, aDir, aId = aData.id, aExtraFile = null) { * An optional dummy file to create in the extension * @return A file pointing to where the extension was installed */ -function writeInstallRDFToXPI(aData, aDir, aId = aData.id, aExtraFile = null) { - let files = { - "install.rdf": AddonTestUtils.createInstallRDF(aData), - }; - if (aExtraFile) - files[aExtraFile] = ""; - - if (!aDir.exists()) - aDir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY); - - var file = aDir.clone(); - file.append(`${aId}.xpi`); - - AddonTestUtils.writeFilesToZip(file.path, files); - - return file; +function writeInstallRDFForExtension(aData, aDir, aId, aExtraFile) { + if (TEST_UNPACKED) { + return writeInstallRDFToDir(aData, aDir, aId, aExtraFile); + } + return writeInstallRDFToXPI(aData, aDir, aId, aExtraFile); } /** - * Writes an install.rdf manifest into an extension using the properties passed + * Writes an install.rdf manifest into a packed extension using the properties passed * in a JS object. The objects should contain a property for each property to * appear in the RDF. The object may contain an array of objects with id, * minVersion and maxVersion in the targetApplications property to give target @@ -726,32 +786,50 @@ function writeInstallRDFToXPI(aData, aDir, aId = aData.id, aExtraFile = null) { * An optional dummy file to create in the extension * @return A file pointing to where the extension was installed */ -function writeInstallRDFForExtension(aData, aDir, aId, aExtraFile) { - if (TEST_UNPACKED) { - return writeInstallRDFToDir(aData, aDir, aId, aExtraFile); - } - return writeInstallRDFToXPI(aData, aDir, aId, aExtraFile); +function writeInstallRDFToXPI(aData, aDir, aId, aExtraFile) { + var id = aId ? aId : aData.id + + if (!aDir.exists()) + aDir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY); + + var file = aDir.clone(); + file.append(id + ".xpi"); + writeInstallRDFToXPIFile(aData, file, aExtraFile); + + return file; } /** - * Writes a manifest.json manifest into an extension using the properties passed - * in a JS object. + * Writes an install.rdf manifest into an XPI file using the properties passed + * in a JS object. The objects should contain a property for each property to + * appear in the RDF. The object may contain an array of objects with id, + * minVersion and maxVersion in the targetApplications property to give target + * application compatibility. * - * @param aManifest - * The data to write - * @param aDir - * The install directory to add the extension to - * @param aId - * An optional string to override the default installation aId - * @return A file pointing to where the extension was installed + * @param aData + * The object holding data about the add-on + * @param aFile + * The XPI file to write to. Any existing file will be overwritten + * @param aExtraFile + * An optional dummy file to create in the extension */ -function promiseWriteWebManifestForExtension(aData, aDir, aId = aData.applications.gecko.id) { - let files = { - "manifest.json": JSON.stringify(aData), - } - return AddonTestUtils.promiseWriteFilesToExtension(aDir.path, aId, files); +function writeInstallRDFToXPIFile(aData, aFile, aExtraFile) { + var rdf = createInstallRDF(aData); + var stream = AM_Cc["@mozilla.org/io/string-input-stream;1"]. + createInstance(AM_Ci.nsIStringInputStream); + stream.setData(rdf, -1); + var zipW = AM_Cc["@mozilla.org/zipwriter;1"]. + createInstance(AM_Ci.nsIZipWriter); + zipW.open(aFile, FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE | FileUtils.MODE_TRUNCATE); + zipW.addEntryStream("install.rdf", 0, AM_Ci.nsIZipWriter.COMPRESSION_NONE, + stream, false); + if (aExtraFile) + zipW.addEntryStream(aExtraFile, 0, AM_Ci.nsIZipWriter.COMPRESSION_NONE, + stream, false); + zipW.close(); } +let temp_xpis = []; /** * Creates an XPI file for some manifest data in the temporary directory and * returns the nsIFile for it. The file will be deleted when the test completes. @@ -760,16 +838,148 @@ function promiseWriteWebManifestForExtension(aData, aDir, aId = aData.applicatio * The object holding data about the add-on * @return A file pointing to the created XPI file */ -function createTempXPIFile(aData, aExtraFile) { - let files = { - "install.rdf": aData, - }; - if (typeof aExtraFile == "object") - Object.assign(files, aExtraFile); - else if (aExtraFile) - files[aExtraFile] = ""; +function createTempXPIFile(aData) { + var file = gTmpD.clone(); + file.append("foo.xpi"); + do { + file.leafName = Math.floor(Math.random() * 1000000) + ".xpi"; + } while (file.exists()); + + temp_xpis.push(file); + writeInstallRDFToXPIFile(aData, file); + return file; +} + +/** + * Sets the last modified time of the extension, usually to trigger an update + * of its metadata. If the extension is unpacked, this function assumes that + * the extension contains only the install.rdf file. + * + * @param aExt a file pointing to either the packed extension or its unpacked directory. + * @param aTime the time to which we set the lastModifiedTime of the extension + * + * @deprecated Please use promiseSetExtensionModifiedTime instead + */ +function setExtensionModifiedTime(aExt, aTime) { + aExt.lastModifiedTime = aTime; + if (aExt.isDirectory()) { + let entries = aExt.directoryEntries + .QueryInterface(AM_Ci.nsIDirectoryEnumerator); + while (entries.hasMoreElements()) + setExtensionModifiedTime(entries.nextFile, aTime); + entries.close(); + } +} +function promiseSetExtensionModifiedTime(aPath, aTime) { + return Task.spawn(function* () { + yield OS.File.setDates(aPath, aTime, aTime); + let entries, iterator; + try { + let iterator = new OS.File.DirectoryIterator(aPath); + entries = yield iterator.nextBatch(); + } catch (ex if ex instanceof OS.File.Error) { + return; + } finally { + if (iterator) { + iterator.close(); + } + } + for (let entry of entries) { + yield promiseSetExtensionModifiedTime(entry.path, aTime); + } + }); +} + +/** + * Manually installs an XPI file into an install location by either copying the + * XPI there or extracting it depending on whether unpacking is being tested + * or not. + * + * @param aXPIFile + * The XPI file to install. + * @param aInstallLocation + * The install location (an nsIFile) to install into. + * @param aID + * The ID to install as. + */ +function manuallyInstall(aXPIFile, aInstallLocation, aID) { + if (TEST_UNPACKED) { + let dir = aInstallLocation.clone(); + dir.append(aID); + dir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY); + let zip = AM_Cc["@mozilla.org/libjar/zip-reader;1"]. + createInstance(AM_Ci.nsIZipReader); + zip.open(aXPIFile); + let entries = zip.findEntries(null); + while (entries.hasMore()) { + let entry = entries.getNext(); + let target = dir.clone(); + entry.split("/").forEach(function(aPart) { + target.append(aPart); + }); + zip.extract(entry, target); + } + zip.close(); + + return dir; + } + else { + let target = aInstallLocation.clone(); + target.append(aID + ".xpi"); + aXPIFile.copyTo(target.parent, target.leafName); + return target; + } +} + +/** + * Manually uninstalls an add-on by removing its files from the install + * location. + * + * @param aInstallLocation + * The nsIFile of the install location to remove from. + * @param aID + * The ID of the add-on to remove. + */ +function manuallyUninstall(aInstallLocation, aID) { + let file = getFileForAddon(aInstallLocation, aID); + + // In reality because the app is restarted a flush isn't necessary for XPIs + // removed outside the app, but for testing we must flush manually. + if (file.isFile()) + Services.obs.notifyObservers(file, "flush-cache-entry", null); + + file.remove(true); +} + +/** + * Gets the nsIFile for where an add-on is installed. It may point to a file or + * a directory depending on whether add-ons are being installed unpacked or not. + * + * @param aDir + * The nsIFile for the install location + * @param aId + * The ID of the add-on + * @return an nsIFile + */ +function getFileForAddon(aDir, aId) { + var dir = aDir.clone(); + dir.append(do_get_expected_addon_name(aId)); + return dir; +} - return AddonTestUtils.createTempXPIFile(files); +function registerDirectory(aKey, aDir) { + var dirProvider = { + getFile: function(aProp, aPersistent) { + aPersistent.value = true; + if (aProp == aKey) + return aDir.clone(); + return null; + }, + + QueryInterface: XPCOMUtils.generateQI([AM_Ci.nsIDirectoryServiceProvider, + AM_Ci.nsISupports]) + }; + Services.dirsvc.registerProvider(dirProvider); } var gExpectedEvents = {}; @@ -898,13 +1108,9 @@ const AddonListener = { const InstallListener = { onNewInstall: function(install) { if (install.state != AddonManager.STATE_DOWNLOADED && - install.state != AddonManager.STATE_DOWNLOAD_FAILED && install.state != AddonManager.STATE_AVAILABLE) do_throw("Bad install state " + install.state); - if (install.state != AddonManager.STATE_DOWNLOAD_FAILED) - do_check_eq(install.error, 0); - else - do_check_neq(install.error, 0); + do_check_eq(install.error, 0); do_check_eq("onNewInstall", getExpectedInstall()); return check_test_completed(arguments); }, @@ -996,9 +1202,7 @@ function check_test_completed(aArgs) { if (gExpectedInstalls instanceof Array && gExpectedInstalls.length > 0) return undefined; - - for (let id in gExpectedInstalls) { - let installList = gExpectedInstalls[id]; + else for each (let installList in gExpectedInstalls) { if (installList.length > 0) return undefined; } @@ -1032,7 +1236,38 @@ function ensure_test_completed() { * The callback to call when all installs have finished */ function completeAllInstalls(aInstalls, aCallback) { - promiseCompleteAllInstalls(aInstalls).then(aCallback); + let count = aInstalls.length; + + if (count == 0) { + aCallback(); + return; + } + + function installCompleted(aInstall) { + aInstall.removeListener(listener); + + if (--count == 0) + do_execute_soon(aCallback); + } + + let listener = { + onDownloadFailed: installCompleted, + onDownloadCancelled: installCompleted, + onInstallFailed: installCompleted, + onInstallCancelled: installCompleted, + onInstallEnded: installCompleted + }; + + aInstalls.forEach(function(aInstall) { + aInstall.addListener(listener); + aInstall.install(); + }); +} + +function promiseCompleteAllInstalls(aInstalls) { + return new Promise(resolve => { + completeAllInstalls(aInstalls, resolve); + }); } /** @@ -1048,13 +1283,179 @@ function completeAllInstalls(aInstalls, aCallback) { * aome way with the application */ function installAllFiles(aFiles, aCallback, aIgnoreIncompatible) { - promiseInstallAllFiles(aFiles, aIgnoreIncompatible).then(aCallback); + let count = aFiles.length; + let installs = []; + function callback() { + if (aCallback) { + aCallback(); + } + } + aFiles.forEach(function(aFile) { + AddonManager.getInstallForFile(aFile, function(aInstall) { + if (!aInstall) + do_throw("No AddonInstall created for " + aFile.path); + do_check_eq(aInstall.state, AddonManager.STATE_DOWNLOADED); + + if (!aIgnoreIncompatible || !aInstall.addon.appDisabled) + installs.push(aInstall); + + if (--count == 0) + completeAllInstalls(installs, callback); + }); + }); +} + +function promiseInstallAllFiles(aFiles, aIgnoreIncompatible) { + let deferred = Promise.defer(); + installAllFiles(aFiles, deferred.resolve, aIgnoreIncompatible); + return deferred.promise; + +} + +if ("nsIWindowsRegKey" in AM_Ci) { + var MockRegistry = { + LOCAL_MACHINE: {}, + CURRENT_USER: {}, + CLASSES_ROOT: {}, + + getRoot: function(aRoot) { + switch (aRoot) { + case AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE: + return MockRegistry.LOCAL_MACHINE; + case AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER: + return MockRegistry.CURRENT_USER; + case AM_Ci.nsIWindowsRegKey.ROOT_KEY_CLASSES_ROOT: + return MockRegistry.CLASSES_ROOT; + default: + do_throw("Unknown root " + aRootKey); + return null; + } + }, + + setValue: function(aRoot, aPath, aName, aValue) { + let rootKey = MockRegistry.getRoot(aRoot); + + if (!(aPath in rootKey)) { + rootKey[aPath] = []; + } + else { + for (let i = 0; i < rootKey[aPath].length; i++) { + if (rootKey[aPath][i].name == aName) { + if (aValue === null) + rootKey[aPath].splice(i, 1); + else + rootKey[aPath][i].value = aValue; + return; + } + } + } + + if (aValue === null) + return; + + rootKey[aPath].push({ + name: aName, + value: aValue + }); + } + }; + + /** + * This is a mock nsIWindowsRegistry implementation. It only implements the + * methods that the extension manager requires. + */ + function MockWindowsRegKey() { + } + + MockWindowsRegKey.prototype = { + values: null, + + // --- Overridden nsISupports interface functions --- + QueryInterface: XPCOMUtils.generateQI([AM_Ci.nsIWindowsRegKey]), + + // --- Overridden nsIWindowsRegKey interface functions --- + open: function(aRootKey, aRelPath, aMode) { + let rootKey = MockRegistry.getRoot(aRootKey); + + if (!(aRelPath in rootKey)) + rootKey[aRelPath] = []; + this.values = rootKey[aRelPath]; + }, + + close: function() { + this.values = null; + }, + + get valueCount() { + if (!this.values) + throw Components.results.NS_ERROR_FAILURE; + return this.values.length; + }, + + getValueName: function(aIndex) { + if (!this.values || aIndex >= this.values.length) + throw Components.results.NS_ERROR_FAILURE; + return this.values[aIndex].name; + }, + + readStringValue: function(aName) { + for (let value of this.values) { + if (value.name == aName) + return value.value; + } + return null; + } + }; + + var WinRegFactory = { + createInstance: function(aOuter, aIid) { + if (aOuter != null) + throw Components.results.NS_ERROR_NO_AGGREGATION; + + var key = new MockWindowsRegKey(); + return key.QueryInterface(aIid); + } + }; + + var registrar = Components.manager.QueryInterface(AM_Ci.nsIComponentRegistrar); + registrar.registerFactory(Components.ID("{0478de5b-0f38-4edb-851d-4c99f1ed8eba}"), + "Mock Windows Registry Implementation", + "@mozilla.org/windows-registry-key;1", WinRegFactory); } +// Get the profile directory for tests to use. +const gProfD = do_get_profile(); + const EXTENSIONS_DB = "extensions.json"; -var gExtensionsJSON = gProfD.clone(); +let gExtensionsJSON = gProfD.clone(); gExtensionsJSON.append(EXTENSIONS_DB); +const EXTENSIONS_INI = "extensions.ini"; +let gExtensionsINI = gProfD.clone(); +gExtensionsINI.append(EXTENSIONS_INI); + +// Enable more extensive EM logging +Services.prefs.setBoolPref("extensions.logging.enabled", true); + +// By default only load extensions from the profile install location +Services.prefs.setIntPref("extensions.enabledScopes", AddonManager.SCOPE_PROFILE); + +// By default don't disable add-ons from any scope +Services.prefs.setIntPref("extensions.autoDisableScopes", 0); + +// By default, don't cache add-ons in AddonRepository.jsm +Services.prefs.setBoolPref("extensions.getAddons.cache.enabled", false); + +// Disable the compatibility updates window by default +Services.prefs.setBoolPref("extensions.showMismatchUI", false); + +// Point update checks to the local machine for fast failures +Services.prefs.setCharPref("extensions.update.url", "http://127.0.0.1/updateURL"); +Services.prefs.setCharPref("extensions.update.background.url", "http://127.0.0.1/updateBackgroundURL"); +Services.prefs.setCharPref("extensions.blocklist.url", "http://127.0.0.1/blocklistURL"); + +// By default ignore bundled add-ons +Services.prefs.setBoolPref("extensions.installDistroAddons", false); // By default use strict compatibility Services.prefs.setBoolPref("extensions.strictCompatibility", true); @@ -1063,9 +1464,26 @@ Services.prefs.setBoolPref("extensions.strictCompatibility", true); Services.prefs.setCharPref(PREF_EM_MIN_COMPAT_APP_VERSION, "0"); Services.prefs.setCharPref(PREF_EM_MIN_COMPAT_PLATFORM_VERSION, "0"); -// Ensure signature checks are enabled by default -Services.prefs.setBoolPref(PREF_XPI_SIGNATURES_REQUIRED, true); - +// Register a temporary directory for the tests. +const gTmpD = gProfD.clone(); +gTmpD.append("temp"); +gTmpD.create(AM_Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY); +registerDirectory("TmpD", gTmpD); + +// Write out an empty blocklist.xml file to the profile to ensure nothing +// is blocklisted by default +var blockFile = gProfD.clone(); +blockFile.append("blocklist.xml"); +var stream = AM_Cc["@mozilla.org/network/file-output-stream;1"]. + createInstance(AM_Ci.nsIFileOutputStream); +stream.init(blockFile, FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE | FileUtils.MODE_TRUNCATE, + FileUtils.PERMS_FILE, 0); + +var data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + + "<blocklist xmlns=\"http://www.mozilla.org/2006/addons-blocklist\">\n" + + "</blocklist>\n"; +stream.write(data, data.length); +stream.close(); // Copies blocklistFile (an nsIFile) to gProfD/blocklist.xml. function copyBlocklistToProfile(blocklistFile) { @@ -1091,40 +1509,51 @@ var timer = AM_Cc["@mozilla.org/timer;1"].createInstance(AM_Ci.nsITimer); timer.init(timeout, TIMEOUT_MS, AM_Ci.nsITimer.TYPE_ONE_SHOT); // Make sure that a given path does not exist -function pathShouldntExist(file) { - if (file.exists()) { - do_throw(`Test cleanup: path ${file.path} exists when it should not`); +function pathShouldntExist(aPath) { + if (aPath.exists()) { + do_throw("Test cleanup: path " + aPath.path + " exists when it should not"); } } do_register_cleanup(function addon_cleanup() { if (timer) timer.cancel(); -}); -/** - * Creates a new HttpServer for testing, and begins listening on the - * specified port. Automatically shuts down the server when the test - * unit ends. - * - * @param port - * The port to listen on. If omitted, listen on a random - * port. The latter is the preferred behavior. - * - * @return HttpServer - */ -function createHttpServer(port = -1) { - let server = new HttpServer(); - server.start(port); + for (let file of temp_xpis) { + if (file.exists()) + file.remove(false); + } - do_register_cleanup(() => { - return new Promise(resolve => { - server.stop(resolve); - }); - }); + // Check that the temporary directory is empty + var dirEntries = gTmpD.directoryEntries + .QueryInterface(AM_Ci.nsIDirectoryEnumerator); + var entry; + while ((entry = dirEntries.nextFile)) { + do_throw("Found unexpected file in temporary directory: " + entry.leafName); + } + dirEntries.close(); - return server; -} + var testDir = gProfD.clone(); + testDir.append("extensions"); + testDir.append("trash"); + pathShouldntExist(testDir); + + testDir.leafName = "staged"; + pathShouldntExist(testDir); + + testDir.leafName = "staged-xpis"; + pathShouldntExist(testDir); + + shutdownManager(); + + // Clear commonly set prefs. + try { + Services.prefs.clearUserPref(PREF_EM_CHECK_UPDATE_SECURITY); + } catch (e) {} + try { + Services.prefs.clearUserPref(PREF_EM_STRICT_COMPATIBILITY); + } catch (e) {} +}); /** * Handler function that responds with the interpolated @@ -1154,7 +1583,7 @@ function interpolateAndServeFile(request, response) { response.write(data); } catch (e) { - do_throw(`Exception while serving interpolated file: ${e}\n${e.stack}`); + do_throw("Exception while serving interpolated file."); } finally { cstream.close(); // this closes fstream as well } @@ -1195,7 +1624,7 @@ function do_exception_wrap(func) { try { func.apply(null, arguments); } - catch (e) { + catch(e) { do_report_unexpected_exception(e); } }; @@ -1204,11 +1633,9 @@ function do_exception_wrap(func) { /** * Change the schema version of the JSON extensions database */ -function changeXPIDBVersion(aNewVersion, aMutator = undefined) { +function changeXPIDBVersion(aNewVersion) { let jData = loadJSON(gExtensionsJSON); jData.schemaVersion = aNewVersion; - if (aMutator) - aMutator(jData); saveJSON(jData, gExtensionsJSON); } @@ -1239,7 +1666,7 @@ function loadFile(aFile) { function loadJSON(aFile) { let data = loadFile(aFile); do_print("Loaded JSON file " + aFile.path); - return (JSON.parse(data)); + return(JSON.parse(data)); } /** @@ -1271,75 +1698,62 @@ function callback_soon(aFunction) { } } -function writeProxyFileToDir(aDir, aAddon, aId) { - awaitPromise(promiseWriteProxyFileToDir(aDir, aAddon, aId)); - - let file = aDir.clone(); - file.append(aId); - return file +/** + * A promise-based variant of AddonManager.getAddonsByIDs. + * + * @param {array} list As the first argument of AddonManager.getAddonsByIDs + * @return {promise} + * @resolve {array} The list of add-ons sent by AddonManaget.getAddonsByIDs to + * its callback. + */ +function promiseAddonsByIDs(list) { + return new Promise(resolve => AddonManager.getAddonsByIDs(list, resolve)); } -function* serveSystemUpdate(xml, perform_update, testserver) { - testserver.registerPathHandler("/data/update.xml", (request, response) => { - response.write(xml); - }); - - try { - yield perform_update(); - } - finally { - testserver.registerPathHandler("/data/update.xml", null); - } +/** + * A promise-based variant of AddonManager.getAddonByID. + * + * @param {string} aId The ID of the add-on. + * @return {promise} + * @resolve {AddonWrapper} The corresponding add-on, or null. + */ +function promiseAddonByID(aId) { + return new Promise(resolve => AddonManager.getAddonByID(aId, resolve)); } -// Runs an update check making it use the passed in xml string. Uses the direct -// call to the update function so we get rejections on failure. -function* installSystemAddons(xml, testserver) { - do_print("Triggering system add-on update check."); - - yield serveSystemUpdate(xml, function*() { - let { XPIProvider } = Components.utils.import("resource://gre/modules/addons/XPIProvider.jsm", {}); - yield XPIProvider.updateSystemAddons(); - }, testserver); +/** + * A promise-based variant of AddonManager.getAddonsWithOperationsByTypes + * + * @param {array} aTypes The first argument to + * AddonManager.getAddonsWithOperationsByTypes + * @return {promise} + * @resolve {array} The list of add-ons sent by + * AddonManaget.getAddonsWithOperationsByTypes to its callback. + */ +function promiseAddonsWithOperationsByTypes(aTypes) { + return new Promise(resolve => AddonManager.getAddonsWithOperationsByTypes(aTypes, resolve)); } -// Runs a full add-on update check which will in some cases do a system add-on -// update check. Always succeeds. -function* updateAllSystemAddons(xml, testserver) { - do_print("Triggering full add-on update check."); - - yield serveSystemUpdate(xml, function() { - return new Promise(resolve => { - Services.obs.addObserver(function() { - Services.obs.removeObserver(arguments.callee, "addons-background-update-complete"); - - resolve(); - }, "addons-background-update-complete", false); - - // Trigger the background update timer handler - gInternalManager.notify(null); - }); - }, testserver); -} - -// Builds an update.xml file for an update check based on the data passed. -function* buildSystemAddonUpdates(addons, root) { - let xml = `<?xml version="1.0" encoding="UTF-8"?>\n\n<updates>\n`; - if (addons) { - xml += ` <addons>\n`; - for (let addon of addons) { - xml += ` <addon id="${addon.id}" URL="${root + addon.path}" version="${addon.version}"`; - if (addon.size) - xml += ` size="${addon.size}"`; - if (addon.hashFunction) - xml += ` hashFunction="${addon.hashFunction}"`; - if (addon.hashValue) - xml += ` hashValue="${addon.hashValue}"`; - xml += `/>\n`; - } - xml += ` </addons>\n`; - } - xml += `</updates>\n`; - - return xml; +/** + * Returns a promise that will be resolved when an add-on update check is + * complete. The value resolved will be an AddonInstall if a new version was + * found. + */ +function promiseFindAddonUpdates(addon, reason = AddonManager.UPDATE_WHEN_PERIODIC_UPDATE) { + return new Promise((resolve, reject) => { + addon.findUpdates({ + install: null, + + onUpdateAvailable: function(addon, install) { + this.install = install; + }, + + onUpdateFinished: function(addon, error) { + if (error == AddonManager.UPDATE_STATUS_NO_ERROR) + resolve(this.install); + else + reject(error); + } + }, reason); + }); } diff --git a/toolkit/mozapps/extensions/test/xpcshell/head_unpack.js b/toolkit/mozapps/extensions/test/xpcshell/head_unpack.js index 6310bbc60..088898b41 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/head_unpack.js +++ b/toolkit/mozapps/extensions/test/xpcshell/head_unpack.js @@ -1,3 +1,2 @@ -/* globals Services, TEST_UNPACKED: true*/ Services.prefs.setBoolPref("extensions.alwaysUnpack", true); TEST_UNPACKED = true; diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository.js b/toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository.js index dd0dc1981..3f51d7226 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository.js @@ -208,7 +208,7 @@ var SEARCH_RESULTS = [{ repositoryStatus: 8, size: 5555, updateDate: new Date(1265033045000), - + }, { id: "purchase1@tests.mozilla.org", type: "extension", @@ -403,7 +403,7 @@ function run_test() { try { aInstall.install(); } - catch (e) { + catch(e) { do_print("Failed to install add-on " + aInstall.sourceURI.spec); do_report_unexpected_exception(e); } @@ -469,12 +469,12 @@ function run_test_1() { initiallyUndefined: true, preference: PREF_GETADDONS_BROWSEADDONS, urlTests: urlTests, - getURL: () => AddonRepository.homepageURL + getURL: function() AddonRepository.homepageURL }, { initiallyUndefined: true, preference: PREF_GETADDONS_BROWSERECOMMENDED, urlTests: urlTests, - getURL: () => AddonRepository.getRecommendedURL() + getURL: function() AddonRepository.getRecommendedURL() }, { initiallyUndefined: false, preference: PREF_GETADDONS_BROWSESEARCHRESULTS, diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository_cache.js b/toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository_cache.js index 203235940..0327ab6d0 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository_cache.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository_cache.js @@ -6,7 +6,8 @@ Components.utils.import("resource://gre/modules/addons/AddonRepository.jsm"); -var gServer; +Components.utils.import("resource://testing-common/httpd.js"); +let gServer; const PORT = 4444; const BASE_URL = "http://localhost:" + PORT; @@ -21,7 +22,7 @@ const FILE_DATABASE = "addons.json"; const ADDON_NAMES = ["test_AddonRepository_1", "test_AddonRepository_2", "test_AddonRepository_3"]; -const ADDON_IDS = ADDON_NAMES.map(aName => aName + "@tests.mozilla.org"); +const ADDON_IDS = ADDON_NAMES.map(function(aName) aName + "@tests.mozilla.org"); const ADDON_FILES = ADDON_NAMES.map(do_get_addon); const PREF_ADDON0_CACHE_ENABLED = "extensions." + ADDON_IDS[0] + ".getAddons.cache.enabled"; @@ -132,7 +133,7 @@ const REPOSITORY_ADDONS = [{ url: BASE_URL + "/repo/2/firstFull.png", thumbnailURL: BASE_URL + "/repo/2/firstThumbnail.png", caption: "Repo Add-on 2 - First Caption" - }, { + } , { url: BASE_URL + "/repo/2/secondFull.png", thumbnailURL: BASE_URL + "/repo/2/secondThumbnail.png", caption: "Repo Add-on 2 - Second Caption" @@ -160,7 +161,7 @@ const REPOSITORY_ADDONS = [{ url: BASE_URL + "/repo/3/firstFull.png", thumbnailURL: BASE_URL + "/repo/3/firstThumbnail.png", caption: "Repo Add-on 3 - First Caption" - }, { + } , { url: BASE_URL + "/repo/3/secondFull.png", thumbnailURL: BASE_URL + "/repo/3/secondThumbnail.png", caption: "Repo Add-on 3 - Second Caption" @@ -288,7 +289,7 @@ const WITH_CACHE = [{ url: BASE_URL + "/repo/2/firstFull.png", thumbnailURL: BASE_URL + "/repo/2/firstThumbnail.png", caption: "Repo Add-on 2 - First Caption" - }, { + } , { url: BASE_URL + "/repo/2/secondFull.png", thumbnailURL: BASE_URL + "/repo/2/secondThumbnail.png", caption: "Repo Add-on 2 - Second Caption" @@ -320,7 +321,7 @@ const WITH_CACHE = [{ url: BASE_URL + "/repo/3/firstFull.png", thumbnailURL: BASE_URL + "/repo/3/firstThumbnail.png", caption: "Repo Add-on 3 - First Caption" - }, { + } , { url: BASE_URL + "/repo/3/secondFull.png", thumbnailURL: BASE_URL + "/repo/3/secondThumbnail.png", caption: "Repo Add-on 3 - Second Caption" @@ -401,7 +402,7 @@ const WITH_EXTENSION_CACHE = [{ sourceURI: NetUtil.newURI(ADDON_FILES[2]).spec }]; -var gDBFile = gProfD.clone(); +let gDBFile = gProfD.clone(); gDBFile.append(FILE_DATABASE); /* @@ -504,8 +505,9 @@ add_task(function* setup() { yield promiseInstallAllFiles(ADDON_FILES); yield promiseRestartManager(); - gServer = createHttpServer(PORT); + gServer = new HttpServer(); gServer.registerDirectory("/data/", do_get_file("data")); + gServer.start(PORT); }); // Tests AddonRepository.cacheEnabled @@ -702,3 +704,7 @@ add_task(function* run_test_17() { let aAddons = yield promiseAddonsByIDs(ADDON_IDS); check_results(aAddons, WITH_EXTENSION_CACHE); }); + +add_task(function* end_test() { + yield new Promise((resolve, reject) => gServer.stop(resolve)); +}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_ChromeManifestParser.js b/toolkit/mozapps/extensions/test/xpcshell/test_ChromeManifestParser.js index 605c4224b..2e4adbe0f 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_ChromeManifestParser.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_ChromeManifestParser.js @@ -1,108 +1,108 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -// Tests ChromeManifestParser.js - -Components.utils.import("resource://gre/modules/ChromeManifestParser.jsm"); - - -function run_test() { - do_test_pending(); - createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "2"); - - startupManager(); - - installAllFiles([do_get_addon("test_chromemanifest_1"), - do_get_addon("test_chromemanifest_2"), - do_get_addon("test_chromemanifest_3"), - do_get_addon("test_chromemanifest_4")], - function() { - - restartManager(); - run_test_1(); - }); -} - -function run_test_1() { - AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", - "addon2@tests.mozilla.org", - "addon3@tests.mozilla.org", - "addon4@tests.mozilla.org"], - function([a1, a2, a3, a4]) { - // addon1 - let a1Uri = a1.getResourceURI("/").spec; - let expected = [ - {type: "content", baseURI: a1Uri, args: ["test-addon-1", "chrome/content"]}, - {type: "locale", baseURI: a1Uri, args: ["test-addon-1", "en-US", "locale/en-US"]}, - {type: "locale", baseURI: a1Uri, args: ["test-addon-1", "fr-FR", "locale/fr-FR"]}, - {type: "overlay", baseURI: a1Uri, args: ["chrome://browser/content/browser.xul", "chrome://test-addon-1/content/overlay.xul"]} - ]; - let manifestURI = a1.getResourceURI("chrome.manifest"); - let manifest = ChromeManifestParser.parseSync(manifestURI); - - do_check_true(Array.isArray(manifest)); - do_check_eq(manifest.length, expected.length); - for (let i = 0; i < manifest.length; i++) { - do_check_eq(JSON.stringify(manifest[i]), JSON.stringify(expected[i])); - } - - // addon2 - let a2Uri = a2.getResourceURI("/").spec; - expected = [ - {type: "content", baseURI: a2Uri, args: ["test-addon-1", "chrome/content"]}, - {type: "locale", baseURI: a2Uri, args: ["test-addon-1", "en-US", "locale/en-US"]}, - {type: "locale", baseURI: a2Uri, args: ["test-addon-1", "fr-FR", "locale/fr-FR"]}, - {type: "overlay", baseURI: a2Uri, args: ["chrome://browser/content/browser.xul", "chrome://test-addon-1/content/overlay.xul"]}, - {type: "binary-component", baseURI: a2Uri, args: ["components/something.so"]} - ]; - manifestURI = a2.getResourceURI("chrome.manifest"); - manifest = ChromeManifestParser.parseSync(manifestURI); - - do_check_true(Array.isArray(manifest)); - do_check_eq(manifest.length, expected.length); - for (let i = 0; i < manifest.length; i++) { - do_check_eq(JSON.stringify(manifest[i]), JSON.stringify(expected[i])); - } - - // addon3 - let a3Uri = a3.getResourceURI("/").spec; - expected = [ - {type: "content", baseURI: a3Uri, args: ["test-addon-1", "chrome/content"]}, - {type: "locale", baseURI: a3Uri, args: ["test-addon-1", "en-US", "locale/en-US"]}, - {type: "locale", baseURI: a3Uri, args: ["test-addon-1", "fr-FR", "locale/fr-FR"]}, - {type: "overlay", baseURI: a3Uri, args: ["chrome://browser/content/browser.xul", "chrome://test-addon-1/content/overlay.xul"]}, - {type: "binary-component", baseURI: a3Uri, args: ["components/something.so"]}, - {type: "locale", baseURI: "jar:" + a3.getResourceURI("/inner.jar").spec + "!/", args: ["test-addon-1", "en-NZ", "locale/en-NZ"]}, - ]; - manifestURI = a3.getResourceURI("chrome.manifest"); - manifest = ChromeManifestParser.parseSync(manifestURI); - - do_check_true(Array.isArray(manifest)); - do_check_eq(manifest.length, expected.length); - for (let i = 0; i < manifest.length; i++) { - do_check_eq(JSON.stringify(manifest[i]), JSON.stringify(expected[i])); - } - - // addon4 - let a4Uri = a4.getResourceURI("/").spec; - expected = [ - {type: "content", baseURI: a4Uri, args: ["test-addon-1", "chrome/content"]}, - {type: "locale", baseURI: a4Uri, args: ["test-addon-1", "en-US", "locale/en-US"]}, - {type: "locale", baseURI: a4Uri, args: ["test-addon-1", "fr-FR", "locale/fr-FR"]}, - {type: "overlay", baseURI: a4Uri, args: ["chrome://browser/content/browser.xul", "chrome://test-addon-1/content/overlay.xul"]}, - {type: "binary-component", baseURI: a4.getResourceURI("components/").spec, args: ["mycomponent.dll"]}, - {type: "binary-component", baseURI: a4.getResourceURI("components/other/").spec, args: ["thermalnuclearwar.dll"]} - ]; - manifestURI = a4.getResourceURI("chrome.manifest"); - manifest = ChromeManifestParser.parseSync(manifestURI); - - do_check_true(Array.isArray(manifest)); - do_check_eq(manifest.length, expected.length); - for (let i = 0; i < manifest.length; i++) { - do_check_eq(JSON.stringify(manifest[i]), JSON.stringify(expected[i])); - } - - do_execute_soon(do_test_finished); - }); -} +/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Tests ChromeManifestParser.js
+
+Components.utils.import("resource://gre/modules/ChromeManifestParser.jsm");
+
+
+function run_test() {
+ do_test_pending();
+ createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "2");
+
+ startupManager();
+
+ installAllFiles([do_get_addon("test_chromemanifest_1"),
+ do_get_addon("test_chromemanifest_2"),
+ do_get_addon("test_chromemanifest_3"),
+ do_get_addon("test_chromemanifest_4")],
+ function() {
+
+ restartManager();
+ run_test_1();
+ });
+}
+
+function run_test_1() {
+ AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
+ "addon2@tests.mozilla.org",
+ "addon3@tests.mozilla.org",
+ "addon4@tests.mozilla.org"],
+ function([a1, a2, a3, a4]) {
+ // addon1
+ let a1Uri = a1.getResourceURI("/").spec;
+ let expected = [
+ {type: "content", baseURI: a1Uri, args: ["test-addon-1", "chrome/content"]},
+ {type: "locale", baseURI: a1Uri, args: ["test-addon-1", "en-US", "locale/en-US"]},
+ {type: "locale", baseURI: a1Uri, args: ["test-addon-1", "fr-FR", "locale/fr-FR"]},
+ {type: "overlay", baseURI: a1Uri, args: ["chrome://browser/content/browser.xul", "chrome://test-addon-1/content/overlay.xul"]}
+ ];
+ let manifestURI = a1.getResourceURI("chrome.manifest");
+ let manifest = ChromeManifestParser.parseSync(manifestURI);
+
+ do_check_true(Array.isArray(manifest));
+ do_check_eq(manifest.length, expected.length);
+ for (let i = 0; i < manifest.length; i++) {
+ do_check_eq(JSON.stringify(manifest[i]), JSON.stringify(expected[i]));
+ }
+
+ // addon2
+ let a2Uri = a2.getResourceURI("/").spec;
+ expected = [
+ {type: "content", baseURI: a2Uri, args: ["test-addon-1", "chrome/content"]},
+ {type: "locale", baseURI: a2Uri, args: ["test-addon-1", "en-US", "locale/en-US"]},
+ {type: "locale", baseURI: a2Uri, args: ["test-addon-1", "fr-FR", "locale/fr-FR"]},
+ {type: "overlay", baseURI: a2Uri, args: ["chrome://browser/content/browser.xul", "chrome://test-addon-1/content/overlay.xul"]},
+ {type: "binary-component", baseURI: a2Uri, args: ["components/something.so"]}
+ ];
+ manifestURI = a2.getResourceURI("chrome.manifest");
+ manifest = ChromeManifestParser.parseSync(manifestURI);
+
+ do_check_true(Array.isArray(manifest));
+ do_check_eq(manifest.length, expected.length);
+ for (let i = 0; i < manifest.length; i++) {
+ do_check_eq(JSON.stringify(manifest[i]), JSON.stringify(expected[i]));
+ }
+
+ // addon3
+ let a3Uri = a3.getResourceURI("/").spec;
+ expected = [
+ {type: "content", baseURI: a3Uri, args: ["test-addon-1", "chrome/content"]},
+ {type: "locale", baseURI: a3Uri, args: ["test-addon-1", "en-US", "locale/en-US"]},
+ {type: "locale", baseURI: a3Uri, args: ["test-addon-1", "fr-FR", "locale/fr-FR"]},
+ {type: "overlay", baseURI: a3Uri, args: ["chrome://browser/content/browser.xul", "chrome://test-addon-1/content/overlay.xul"]},
+ {type: "binary-component", baseURI: a3Uri, args: ["components/something.so"]},
+ {type: "locale", baseURI: "jar:" + a3.getResourceURI("/inner.jar").spec + "!/", args: ["test-addon-1", "en-NZ", "locale/en-NZ"]},
+ ];
+ manifestURI = a3.getResourceURI("chrome.manifest");
+ manifest = ChromeManifestParser.parseSync(manifestURI);
+
+ do_check_true(Array.isArray(manifest));
+ do_check_eq(manifest.length, expected.length);
+ for (let i = 0; i < manifest.length; i++) {
+ do_check_eq(JSON.stringify(manifest[i]), JSON.stringify(expected[i]));
+ }
+
+ // addon4
+ let a4Uri = a4.getResourceURI("/").spec;
+ expected = [
+ {type: "content", baseURI: a4Uri, args: ["test-addon-1", "chrome/content"]},
+ {type: "locale", baseURI: a4Uri, args: ["test-addon-1", "en-US", "locale/en-US"]},
+ {type: "locale", baseURI: a4Uri, args: ["test-addon-1", "fr-FR", "locale/fr-FR"]},
+ {type: "overlay", baseURI: a4Uri, args: ["chrome://browser/content/browser.xul", "chrome://test-addon-1/content/overlay.xul"]},
+ {type: "binary-component", baseURI: a4.getResourceURI("components/").spec, args: ["mycomponent.dll"]},
+ {type: "binary-component", baseURI: a4.getResourceURI("components/other/").spec, args: ["thermalnuclearwar.dll"]}
+ ];
+ manifestURI = a4.getResourceURI("chrome.manifest");
+ manifest = ChromeManifestParser.parseSync(manifestURI);
+
+ do_check_true(Array.isArray(manifest));
+ do_check_eq(manifest.length, expected.length);
+ for (let i = 0; i < manifest.length; i++) {
+ do_check_eq(JSON.stringify(manifest[i]), JSON.stringify(expected[i]));
+ }
+
+ do_execute_soon(do_test_finished);
+ });
+}
diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_DeferredSave.js b/toolkit/mozapps/extensions/test/xpcshell/test_DeferredSave.js index 2a6ff291e..7599c8b80 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_DeferredSave.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_DeferredSave.js @@ -12,8 +12,8 @@ testFile.append("DeferredSaveTest"); Components.utils.import("resource://gre/modules/Promise.jsm"); -var DSContext = Components.utils.import("resource://gre/modules/DeferredSave.jsm", {}); -var DeferredSave = DSContext.DeferredSave; +let DSContext = Components.utils.import("resource://gre/modules/DeferredSave.jsm", {}); +let DeferredSave = DSContext.DeferredSave; // Test wrapper to let us do promise/task based testing of DeferredSave function DeferredSaveTester(aDataProvider) { @@ -67,7 +67,7 @@ function DeferredSaveTester(aDataProvider) { }; return tester; -} +}; /** * Install a mock nsITimer factory that triggers on the next spin of @@ -147,7 +147,7 @@ function run_test() { } // Modify set data once, ask for save, make sure it saves cleanly -add_task(function* test_basic_save_succeeds() { +add_task(function test_basic_save_succeeds() { setQuickMockTimer(); let tester = DeferredSaveTester(); let data = "Test 1 Data"; @@ -159,7 +159,7 @@ add_task(function* test_basic_save_succeeds() { // Two saves called during the same event loop, both with callbacks // Make sure we save only the second version of the data -add_task(function* test_two_saves() { +add_task(function test_two_saves() { setQuickMockTimer(); let tester = DeferredSaveTester(); let firstCallback_happened = false; @@ -182,7 +182,7 @@ add_task(function* test_two_saves() { // Two saves called with a delay in between, both with callbacks // Make sure we save the second version of the data -add_task(function* test_two_saves_delay() { +add_task(function test_two_saves_delay() { let timerPromise = setPromiseMockTimer(); let tester = DeferredSaveTester(); let firstCallback_happened = false; @@ -219,7 +219,7 @@ add_task(function* test_two_saves_delay() { // Test case where OS.File immediately reports an error when the write begins // Also check that the "error" getter correctly returns the error // Then do a write that succeeds, and make sure the error is cleared -add_task(function* test_error_immediate() { +add_task(function test_error_immediate() { let tester = DeferredSaveTester(); let testError = new Error("Forced failure"); function writeFail(aTester) { @@ -243,7 +243,7 @@ add_task(function* test_error_immediate() { // Save one set of changes, then while the write is in progress, modify the // data two more times. Test that we re-write the dirty data exactly once // after the first write succeeds -add_task(function* dirty_while_writing() { +add_task(function dirty_while_writing() { let tester = DeferredSaveTester(); let firstData = "First data"; let secondData = "Second data"; @@ -303,6 +303,7 @@ add_task(function* dirty_while_writing() { // A write callback for the OS.File.writeAtomic mock that rejects write attempts function disabled_write_callback(aTester) { do_throw("Should not have written during clean flush"); + deferred.reject(new Error("Write during supposedly clean flush")); } // special write callback that disables itself to make sure @@ -316,7 +317,7 @@ function write_then_disable(aTester) { // Flush tests. First, do an ordinary clean save and then call flush; // there should not be another save -add_task(function* flush_after_save() { +add_task(function flush_after_save() { setQuickMockTimer(); let tester = DeferredSaveTester(); let dataToSave = "Flush after save"; @@ -327,7 +328,7 @@ add_task(function* flush_after_save() { }); // Flush while a write is in progress, but the in-memory data is clean -add_task(function* flush_during_write() { +add_task(function flush_during_write() { let tester = DeferredSaveTester(); let dataToSave = "Flush during write"; let firstCallback_happened = false; @@ -360,7 +361,7 @@ add_task(function* flush_during_write() { // Flush while dirty but write not in progress // The data written should be the value at the time // flush() is called, even if it is changed later -add_task(function* flush_while_dirty() { +add_task(function flush_while_dirty() { let timerPromise = setPromiseMockTimer(); let tester = DeferredSaveTester(); let firstData = "Flush while dirty, valid data"; @@ -396,7 +397,7 @@ add_task(function* flush_while_dirty() { // then flush, then modify the data again // Data for the second write should be taken at the time // flush() is called, even if it is modified later -add_task(function* flush_writing_dirty() { +add_task(function flush_writing_dirty() { let timerPromise = setPromiseMockTimer(); let tester = DeferredSaveTester(); let firstData = "Flush first pass data"; @@ -453,7 +454,7 @@ add_task(function* flush_writing_dirty() { // with the error and (b) make sure the provider is only // called once in case of error const expectedDataError = "Failed to serialize data"; -var badDataError = null; +let badDataError = null; function badDataProvider() { let err = new Error(badDataError); badDataError = "badDataProvider called twice"; @@ -462,7 +463,7 @@ function badDataProvider() { // Handle cases where data provider throws // First, throws during a normal save -add_task(function* data_throw() { +add_task(function data_throw() { setQuickMockTimer(); badDataError = expectedDataError; let tester = DeferredSaveTester(badDataProvider); @@ -472,7 +473,7 @@ add_task(function* data_throw() { }); // Now, throws during flush -add_task(function* data_throw_during_flush() { +add_task(function data_throw_during_flush() { badDataError = expectedDataError; let tester = DeferredSaveTester(badDataProvider); let firstCallback_happened = false; @@ -507,7 +508,7 @@ add_task(function* data_throw_during_flush() { // actually restart timer for delayed write // write completes // delayed timer goes off, throws error because DeferredSave has been torn down -add_task(function* delay_flush_race() { +add_task(function delay_flush_race() { let timerPromise = setPromiseMockTimer(); let tester = DeferredSaveTester(); let firstData = "First save"; diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_LightweightThemeManager.js b/toolkit/mozapps/extensions/test/xpcshell/test_LightweightThemeManager.js index 61a46b251..c0cf78a89 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_LightweightThemeManager.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_LightweightThemeManager.js @@ -1,5 +1,5 @@ -var Cc = Components.classes; -var Ci = Components.interfaces; +const Cc = Components.classes; +const Ci = Components.interfaces; const MANDATORY = ["id", "name", "headerURL"]; const OPTIONAL = ["footerURL", "textcolor", "accentcolor", "iconURL", @@ -19,20 +19,18 @@ function dummy(id) { }; } -function hasPermission(aAddon, aPerm) { - var perm = AddonManager["PERM_CAN_" + aPerm.toUpperCase()]; - return !!(aAddon.permissions & perm); -} - function run_test() { createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9"); startupManager(); Services.prefs.setIntPref("lightweightThemes.maxUsedThemes", 8); - let {LightweightThemeManager: ltm} = Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm", {}); + var temp = {}; + Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm", temp); + do_check_eq(typeof temp.LightweightThemeManager, "object"); + + var ltm = temp.LightweightThemeManager; - do_check_eq(typeof ltm, "object"); do_check_eq(typeof ltm.usedThemes, "object"); do_check_eq(ltm.usedThemes.length, 0); do_check_eq(ltm.currentTheme, null); @@ -207,71 +205,71 @@ function run_test() { function roundtripSet(props, modify, test, secure) { props.forEach(function (prop) { - var theme = dummy(); - modify(theme, prop); - test(roundtrip(theme, secure), prop, theme); + var data = dummy(); + modify(data, prop); + test(roundtrip(data, secure), prop, data); }); } - roundtripSet(MANDATORY, function (theme, prop) { - delete theme[prop]; + roundtripSet(MANDATORY, function (data, prop) { + delete data[prop]; }, function (after) { do_check_eq(after, null); }); - roundtripSet(OPTIONAL, function (theme, prop) { - delete theme[prop]; + roundtripSet(OPTIONAL, function (data, prop) { + delete data[prop]; }, function (after) { do_check_neq(after, null); }); - roundtripSet(MANDATORY, function (theme, prop) { - theme[prop] = ""; + roundtripSet(MANDATORY, function (data, prop) { + data[prop] = ""; }, function (after) { do_check_eq(after, null); }); - roundtripSet(OPTIONAL, function (theme, prop) { - theme[prop] = ""; + roundtripSet(OPTIONAL, function (data, prop) { + data[prop] = ""; }, function (after, prop) { do_check_eq(typeof after[prop], "undefined"); }); - roundtripSet(MANDATORY, function (theme, prop) { - theme[prop] = " "; + roundtripSet(MANDATORY, function (data, prop) { + data[prop] = " "; }, function (after) { do_check_eq(after, null); }); - roundtripSet(OPTIONAL, function (theme, prop) { - theme[prop] = " "; + roundtripSet(OPTIONAL, function (data, prop) { + data[prop] = " "; }, function (after, prop) { do_check_neq(after, null); do_check_eq(typeof after[prop], "undefined"); }); function non_urls(props) { - return props.filter(prop => !/URL$/.test(prop)); + return props.filter(function (prop) !/URL$/.test(prop)); } function urls(props) { - return props.filter(prop => /URL$/.test(prop)); + return props.filter(function (prop) /URL$/.test(prop)); } - roundtripSet(non_urls(MANDATORY.concat(OPTIONAL)), function (theme, prop) { - theme[prop] = prop; + roundtripSet(non_urls(MANDATORY.concat(OPTIONAL)), function (data, prop) { + data[prop] = prop; }, function (after, prop, before) { do_check_eq(after[prop], before[prop]); }); - roundtripSet(non_urls(MANDATORY.concat(OPTIONAL)), function (theme, prop) { - theme[prop] = " " + prop + " "; + roundtripSet(non_urls(MANDATORY.concat(OPTIONAL)), function (data, prop) { + data[prop] = " " + prop + " "; }, function (after, prop, before) { do_check_eq(after[prop], before[prop].trim()); }); - roundtripSet(urls(MANDATORY.concat(OPTIONAL)), function (theme, prop) { - theme[prop] = Math.random().toString(); + roundtripSet(urls(MANDATORY.concat(OPTIONAL)), function (data, prop) { + data[prop] = Math.random().toString(); }, function (after, prop, before) { if (prop == "updateURL") do_check_eq(typeof after[prop], "undefined"); @@ -279,26 +277,26 @@ function run_test() { do_check_eq(after[prop], "http://lwttest.invalid/" + before[prop]); }); - roundtripSet(urls(MANDATORY.concat(OPTIONAL)), function (theme, prop) { - theme[prop] = Math.random().toString(); + roundtripSet(urls(MANDATORY.concat(OPTIONAL)), function (data, prop) { + data[prop] = Math.random().toString(); }, function (after, prop, before) { do_check_eq(after[prop], "https://lwttest.invalid/" + before[prop]); }, true); - roundtripSet(urls(MANDATORY.concat(OPTIONAL)), function (theme, prop) { - theme[prop] = "https://sub.lwttest.invalid/" + Math.random().toString(); + roundtripSet(urls(MANDATORY.concat(OPTIONAL)), function (data, prop) { + data[prop] = "https://sub.lwttest.invalid/" + Math.random().toString(); }, function (after, prop, before) { do_check_eq(after[prop], before[prop]); }); - roundtripSet(urls(MANDATORY), function (theme, prop) { - theme[prop] = "ftp://lwttest.invalid/" + Math.random().toString(); + roundtripSet(urls(MANDATORY), function (data, prop) { + data[prop] = "ftp://lwttest.invalid/" + Math.random().toString(); }, function (after) { do_check_eq(after, null); }); - roundtripSet(urls(OPTIONAL), function (theme, prop) { - theme[prop] = "ftp://lwttest.invalid/" + Math.random().toString(); + roundtripSet(urls(OPTIONAL), function (data, prop) { + data[prop] = "ftp://lwttest.invalid/" + Math.random().toString(); }, function (after, prop) { do_check_eq(typeof after[prop], "undefined"); }); @@ -513,86 +511,4 @@ function run_test() { Services.prefs.clearUserPref("lightweightThemes.maxUsedThemes"); do_check_eq(ltm.usedThemes.length, 30); - - let usedThemes = ltm.usedThemes; - for (let theme of usedThemes) { - ltm.forgetUsedTheme(theme.id); - } - - // Check builtInTheme functionality for Bug 1094821 - do_check_eq(ltm._builtInThemes.toString(), "[object Map]"); - do_check_eq([...ltm._builtInThemes.entries()].length, 0); - do_check_eq(ltm.usedThemes.length, 0); - - ltm.addBuiltInTheme(dummy("builtInTheme0")); - do_check_eq([...ltm._builtInThemes].length, 1); - do_check_eq(ltm.usedThemes.length, 1); - do_check_eq(ltm.usedThemes[0].id, "builtInTheme0"); - - ltm.addBuiltInTheme(dummy("builtInTheme1")); - do_check_eq([...ltm._builtInThemes].length, 2); - do_check_eq(ltm.usedThemes.length, 2); - do_check_eq(ltm.usedThemes[1].id, "builtInTheme1"); - - // Clear all and then re-add - ltm.clearBuiltInThemes(); - do_check_eq([...ltm._builtInThemes].length, 0); - do_check_eq(ltm.usedThemes.length, 0); - - ltm.addBuiltInTheme(dummy("builtInTheme0")); - ltm.addBuiltInTheme(dummy("builtInTheme1")); - do_check_eq([...ltm._builtInThemes].length, 2); - do_check_eq(ltm.usedThemes.length, 2); - - do_test_pending(); - - AddonManager.getAddonByID("builtInTheme0@personas.mozilla.org", builtInThemeAddon => { - // App specific theme can't be uninstalled or disabled, - // but can be enabled (since it isn't already applied). - do_check_eq(hasPermission(builtInThemeAddon, "uninstall"), false); - do_check_eq(hasPermission(builtInThemeAddon, "disable"), false); - do_check_eq(hasPermission(builtInThemeAddon, "enable"), true); - - ltm.currentTheme = dummy("x0"); - do_check_eq([...ltm._builtInThemes].length, 2); - do_check_eq(ltm.usedThemes.length, 3); - do_check_eq(ltm.usedThemes[0].id, "x0"); - do_check_eq(ltm.currentTheme.id, "x0"); - do_check_eq(ltm.usedThemes[1].id, "builtInTheme0"); - do_check_eq(ltm.usedThemes[2].id, "builtInTheme1"); - - Assert.throws(() => { ltm.addBuiltInTheme(dummy("builtInTheme0")) }, - "Exception is thrown adding a duplicate theme"); - Assert.throws(() => { ltm.addBuiltInTheme("not a theme object") }, - "Exception is thrown adding an invalid theme"); - - AddonManager.getAddonByID("x0@personas.mozilla.org", x0Addon => { - // Currently applied (non-app-specific) can be uninstalled or disabled, - // but can't be enabled (since it's already applied). - do_check_eq(hasPermission(x0Addon, "uninstall"), true); - do_check_eq(hasPermission(x0Addon, "disable"), true); - do_check_eq(hasPermission(x0Addon, "enable"), false); - - ltm.forgetUsedTheme("x0"); - do_check_eq(ltm.currentTheme, null); - - // Removing the currently applied app specific theme should unapply it - ltm.currentTheme = ltm.getUsedTheme("builtInTheme0"); - do_check_eq(ltm.currentTheme.id, "builtInTheme0"); - do_check_true(ltm.forgetBuiltInTheme("builtInTheme0")); - do_check_eq(ltm.currentTheme, null); - - do_check_eq([...ltm._builtInThemes].length, 1); - do_check_eq(ltm.usedThemes.length, 1); - - do_check_true(ltm.forgetBuiltInTheme("builtInTheme1")); - do_check_false(ltm.forgetBuiltInTheme("not-an-existing-theme-id")); - - do_check_eq([...ltm._builtInThemes].length, 0); - do_check_eq(ltm.usedThemes.length, 0); - do_check_eq(ltm.currentTheme, null); - - do_test_finished(); - }); - }); } diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_ProductAddonChecker.js b/toolkit/mozapps/extensions/test/xpcshell/test_ProductAddonChecker.js deleted file mode 100644 index 6c562db65..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_ProductAddonChecker.js +++ /dev/null @@ -1,244 +0,0 @@ -"use strict"; - -Components.utils.import("resource://gre/modules/addons/ProductAddonChecker.jsm"); -Components.utils.import("resource://testing-common/httpd.js"); -Components.utils.import("resource://gre/modules/osfile.jsm"); - -const LocalFile = new Components.Constructor("@mozilla.org/file/local;1", AM_Ci.nsIFile, "initWithPath"); - -var testserver = new HttpServer(); -testserver.registerDirectory("/data/", do_get_file("data/productaddons")); -testserver.start(); -var root = testserver.identity.primaryScheme + "://" + - testserver.identity.primaryHost + ":" + - testserver.identity.primaryPort + "/data/" - -/** - * Compares binary data of 2 arrays and returns true if they are the same - * - * @param arr1 The first array to compare - * @param arr2 The second array to compare -*/ -function compareBinaryData(arr1, arr2) { - do_check_eq(arr1.length, arr2.length); - for (let i = 0; i < arr1.length; i++) { - if (arr1[i] != arr2[i]) { - do_print("Data differs at index " + i + - ", arr1: " + arr1[i] + ", arr2: " + arr2[i]); - return false; - } - } - return true; -} - -/** - * Reads a file's data and returns it - * - * @param file The file to read the data from - * @return array of bytes for the data in the file. -*/ -function getBinaryFileData(file) { - let fileStream = AM_Cc["@mozilla.org/network/file-input-stream;1"]. - createInstance(AM_Ci.nsIFileInputStream); - // Open as RD_ONLY with default permissions. - fileStream.init(file, FileUtils.MODE_RDONLY, FileUtils.PERMS_FILE, 0); - - let stream = AM_Cc["@mozilla.org/binaryinputstream;1"]. - createInstance(AM_Ci.nsIBinaryInputStream); - stream.setInputStream(fileStream); - let bytes = stream.readByteArray(stream.available()); - fileStream.close(); - return bytes; -} - -/** - * Compares binary data of 2 files and returns true if they are the same - * - * @param file1 The first file to compare - * @param file2 The second file to compare -*/ -function compareFiles(file1, file2) { - return compareBinaryData(getBinaryFileData(file1), getBinaryFileData(file2)); -} - -add_task(function* test_404() { - let res = yield ProductAddonChecker.getProductAddonList(root + "404.xml"); - do_check_true(res.usedFallback); -}); - -add_task(function* test_not_xml() { - let res = yield ProductAddonChecker.getProductAddonList(root + "bad.txt"); - do_check_true(res.usedFallback); -}); - -add_task(function* test_invalid_xml() { - let res = yield ProductAddonChecker.getProductAddonList(root + "bad.xml"); - do_check_true(res.usedFallback); -}); - -add_task(function* test_wrong_xml() { - let res = yield ProductAddonChecker.getProductAddonList(root + "bad2.xml"); - do_check_true(res.usedFallback); -}); - -add_task(function* test_missing() { - let addons = yield ProductAddonChecker.getProductAddonList(root + "missing.xml"); - do_check_eq(addons, null); -}); - -add_task(function* test_empty() { - let res = yield ProductAddonChecker.getProductAddonList(root + "empty.xml"); - do_check_true(Array.isArray(res.gmpAddons)); - do_check_eq(res.gmpAddons.length, 0); -}); - -add_task(function* test_good_xml() { - let res = yield ProductAddonChecker.getProductAddonList(root + "good.xml"); - do_check_true(Array.isArray(res.gmpAddons)); - - // There are three valid entries in the XML - do_check_eq(res.gmpAddons.length, 5); - - let addon = res.gmpAddons[0]; - do_check_eq(addon.id, "test1"); - do_check_eq(addon.URL, "http://example.com/test1.xpi"); - do_check_eq(addon.hashFunction, undefined); - do_check_eq(addon.hashValue, undefined); - do_check_eq(addon.version, undefined); - do_check_eq(addon.size, undefined); - - addon = res.gmpAddons[1]; - do_check_eq(addon.id, "test2"); - do_check_eq(addon.URL, "http://example.com/test2.xpi"); - do_check_eq(addon.hashFunction, "md5"); - do_check_eq(addon.hashValue, "djhfgsjdhf"); - do_check_eq(addon.version, undefined); - do_check_eq(addon.size, undefined); - - addon = res.gmpAddons[2]; - do_check_eq(addon.id, "test3"); - do_check_eq(addon.URL, "http://example.com/test3.xpi"); - do_check_eq(addon.hashFunction, undefined); - do_check_eq(addon.hashValue, undefined); - do_check_eq(addon.version, "1.0"); - do_check_eq(addon.size, 45); - - addon = res.gmpAddons[3]; - do_check_eq(addon.id, "test4"); - do_check_eq(addon.URL, undefined); - do_check_eq(addon.hashFunction, undefined); - do_check_eq(addon.hashValue, undefined); - do_check_eq(addon.version, undefined); - do_check_eq(addon.size, undefined); - - addon = res.gmpAddons[4]; - do_check_eq(addon.id, undefined); - do_check_eq(addon.URL, "http://example.com/test5.xpi"); - do_check_eq(addon.hashFunction, undefined); - do_check_eq(addon.hashValue, undefined); - do_check_eq(addon.version, undefined); - do_check_eq(addon.size, undefined); -}); - -add_task(function* test_download_nourl() { - try { - let path = yield ProductAddonChecker.downloadAddon({}); - - yield OS.File.remove(path); - do_throw("Should not have downloaded a file with a missing url"); - } - catch (e) { - do_check_true(true, "Should have thrown when downloading a file with a missing url."); - } -}); - -add_task(function* test_download_missing() { - try { - let path = yield ProductAddonChecker.downloadAddon({ - URL: root + "nofile.xpi", - }); - - yield OS.File.remove(path); - do_throw("Should not have downloaded a missing file"); - } - catch (e) { - do_check_true(true, "Should have thrown when downloading a missing file."); - } -}); - -add_task(function* test_download_noverify() { - let path = yield ProductAddonChecker.downloadAddon({ - URL: root + "unsigned.xpi", - }); - - let stat = yield OS.File.stat(path); - do_check_false(stat.isDir); - do_check_eq(stat.size, 452) - - do_check_true(compareFiles(do_get_file("data/productaddons/unsigned.xpi"), new LocalFile(path))); - - yield OS.File.remove(path); -}); - -add_task(function* test_download_badsize() { - try { - let path = yield ProductAddonChecker.downloadAddon({ - URL: root + "unsigned.xpi", - size: 400, - }); - - yield OS.File.remove(path); - do_throw("Should not have downloaded a file with a bad size"); - } - catch (e) { - do_check_true(true, "Should have thrown when downloading a file with a bad size."); - } -}); - -add_task(function* test_download_badhashfn() { - try { - let path = yield ProductAddonChecker.downloadAddon({ - URL: root + "unsigned.xpi", - hashFunction: "sha2567", - hashValue: "9b9abf7ddfc1a6d7ffc7e0247481dcc202363e4445ad3494fb22036f1698c7f3", - }); - - yield OS.File.remove(path); - do_throw("Should not have downloaded a file with a bad hash function"); - } - catch (e) { - do_check_true(true, "Should have thrown when downloading a file with a bad hash function."); - } -}); - -add_task(function* test_download_badhash() { - try { - let path = yield ProductAddonChecker.downloadAddon({ - URL: root + "unsigned.xpi", - hashFunction: "sha256", - hashValue: "8b9abf7ddfc1a6d7ffc7e0247481dcc202363e4445ad3494fb22036f1698c7f3", - }); - - yield OS.File.remove(path); - do_throw("Should not have downloaded a file with a bad hash"); - } - catch (e) { - do_check_true(true, "Should have thrown when downloading a file with a bad hash."); - } -}); - -add_task(function* test_download_works() { - let path = yield ProductAddonChecker.downloadAddon({ - URL: root + "unsigned.xpi", - size: 452, - hashFunction: "sha256", - hashValue: "9b9abf7ddfc1a6d7ffc7e0247481dcc202363e4445ad3494fb22036f1698c7f3", - }); - - let stat = yield OS.File.stat(path); - do_check_false(stat.isDir); - - do_check_true(compareFiles(do_get_file("data/productaddons/unsigned.xpi"), new LocalFile(path))); - - yield OS.File.remove(path); -}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_XPIStates.js b/toolkit/mozapps/extensions/test/xpcshell/test_XPIStates.js index 99ab8ab13..37ac161ca 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_XPIStates.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_XPIStates.js @@ -60,7 +60,7 @@ writeInstallRDFToDir({ maxVersion: "1" }], name: "Unpacked, Enabled", -}, profileDir, undefined, "extraFile.js"); +}, profileDir, null, "extraFile.js"); // Unpacked, disabled @@ -75,12 +75,12 @@ writeInstallRDFToDir({ maxVersion: "1" }], name: "Unpacked, disabled", -}, profileDir, undefined, "extraFile.js"); +}, profileDir, null, "extraFile.js"); // Keep track of the last time stamp we've used, so that we can keep moving // it forward (if we touch two different files in the same add-on with the same // timestamp we may not consider the change significant) -var lastTimestamp = Date.now(); +let lastTimestamp = Date.now(); /* * Helper function to touch a file and then test whether we detect the change. diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_XPIcancel.js b/toolkit/mozapps/extensions/test/xpcshell/test_XPIcancel.js index d733778a5..7d8778301 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_XPIcancel.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_XPIcancel.js @@ -4,8 +4,8 @@ // Test the cancellable doing/done/cancelAll API in XPIProvider -var scope = Components.utils.import("resource://gre/modules/addons/XPIProvider.jsm"); -var XPIProvider = scope.XPIProvider; +let scope = Components.utils.import("resource://gre/modules/addons/XPIProvider.jsm"); +let XPIProvider = scope.XPIProvider; function run_test() { // Check that cancelling with nothing in progress doesn't blow up diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_addon_path_service.js b/toolkit/mozapps/extensions/test/xpcshell/test_addon_path_service.js index 56ce3c614..30bb577a1 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_addon_path_service.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_addon_path_service.js @@ -2,7 +2,7 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -var service = Components.classes["@mozilla.org/addon-path-service;1"].getService(Components.interfaces.amIAddonPathService); +let service = Components.classes["@mozilla.org/addon-path-service;1"].getService(Components.interfaces.amIAddonPathService); function insert(path, value) { diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_asyncBlocklistLoad.js b/toolkit/mozapps/extensions/test/xpcshell/test_asyncBlocklistLoad.js index 38e563979..11d9f2943 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_asyncBlocklistLoad.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_asyncBlocklistLoad.js @@ -6,7 +6,7 @@ function run_test() { run_next_test(); } -add_task(function* () { +add_task(function () { let blocklist = AM_Cc["@mozilla.org/extensions/blocklist;1"]. getService().wrappedJSObject; let scope = Components.utils.import("resource://gre/modules/osfile.jsm"); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_backgroundupdate.js b/toolkit/mozapps/extensions/test/xpcshell/test_backgroundupdate.js index 3890b76e1..d69c33e33 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_backgroundupdate.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_backgroundupdate.js @@ -92,10 +92,6 @@ function run_test_2() { "http://localhost:" + gPort +"/data/test_backgroundupdate.rdf"); restartManager(); - // Do hotfix checks - Services.prefs.setCharPref("extensions.hotfix.id", "hotfix@tests.mozilla.org"); - Services.prefs.setCharPref("extensions.hotfix.url", "http://localhost:" + gPort + "/missing.rdf"); - let installCount = 0; let completeCount = 0; let sawCompleteNotification = false; diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_gfx.js b/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_gfx.js deleted file mode 100644 index cbcd5cb7e..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_gfx.js +++ /dev/null @@ -1,157 +0,0 @@ -const { classes: Cc, interfaces: Ci, utils: Cu } = Components; - -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); - -const TEST_APP_ID = "xpcshell@tests.mozilla.org"; - - -const EVENT_NAME = "blocklist-data-gfxItems"; - -const SAMPLE_GFX_RECORD = { - "driverVersionComparator": "LESS_THAN_OR_EQUAL", - "driverVersion": "8.17.12.5896", - "vendor": "0x10de", - "blockID": "g36", - "feature": "DIRECT3D_9_LAYERS", - "devices": ["0x0a6c", "geforce"], - "featureStatus": "BLOCKED_DRIVER_VERSION", - "last_modified": 1458035931837, - "os": "WINNT 6.1", - "id": "3f947f16-37c2-4e96-d356-78b26363729b", - "versionRange": {"minVersion": 0, "maxVersion": "*"} -}; - - -function Blocklist() { - let blocklist = Cc["@mozilla.org/extensions/blocklist;1"]. - getService().wrappedJSObject; - blocklist._clear(); - return blocklist; -} - - -function run_test() { - run_next_test(); -} - - -add_task(function* test_sends_serialized_data() { - const blocklist = Blocklist(); - blocklist._gfxEntries = [SAMPLE_GFX_RECORD]; - - const expected = "blockID:g36\tdevices:0x0a6c,geforce\tdriverVersion:8.17.12.5896\t" + - "driverVersionComparator:LESS_THAN_OR_EQUAL\tfeature:DIRECT3D_9_LAYERS\t" + - "featureStatus:BLOCKED_DRIVER_VERSION\tos:WINNT 6.1\tvendor:0x10de\t" + - "versionRange:0,*"; - let received; - const observe = (subject, topic, data) => { received = data }; - Services.obs.addObserver(observe, EVENT_NAME, false); - blocklist._notifyObserversBlocklistGFX(); - equal(received, expected); - Services.obs.removeObserver(observe, EVENT_NAME); -}); - - -add_task(function* test_parsing_fails_if_devices_contains_comma() { - const input = "<blocklist xmlns=\"http://www.mozilla.org/2006/addons-blocklist\">" + - "<gfxItems>" + - " <gfxBlacklistEntry>" + - " <devices>" + - " <device>0x2,582</device>" + - " <device>0x2782</device>" + - " </devices>" + - " </gfxBlacklistEntry>" + - "</gfxItems>" + - "</blocklist>"; - const blocklist = Blocklist(); - blocklist._loadBlocklistFromString(input); - equal(blocklist._gfxEntries[0].devices.length, 1); - equal(blocklist._gfxEntries[0].devices[0], "0x2782"); -}); - - -add_task(function* test_empty_values_are_ignored() { - const input = "<blocklist xmlns=\"http://www.mozilla.org/2006/addons-blocklist\">" + - "<gfxItems>" + - " <gfxBlacklistEntry>" + - " <os></os>" + - " </gfxBlacklistEntry>" + - "</gfxItems>" + - "</blocklist>"; - const blocklist = Blocklist(); - let received; - const observe = (subject, topic, data) => { received = data }; - Services.obs.addObserver(observe, EVENT_NAME, false); - blocklist._loadBlocklistFromString(input); - ok(received.indexOf("os" < 0)); - Services.obs.removeObserver(observe, EVENT_NAME); -}); - -add_task(function* test_empty_devices_are_ignored() { - const input = "<blocklist xmlns=\"http://www.mozilla.org/2006/addons-blocklist\">" + - "<gfxItems>" + - " <gfxBlacklistEntry>" + - " <devices></devices>" + - " </gfxBlacklistEntry>" + - "</gfxItems>" + - "</blocklist>"; - const blocklist = Blocklist(); - let received; - const observe = (subject, topic, data) => { received = data }; - Services.obs.addObserver(observe, EVENT_NAME, false); - blocklist._loadBlocklistFromString(input); - ok(received.indexOf("devices" < 0)); - Services.obs.removeObserver(observe, EVENT_NAME); -}); - -add_task(function* test_version_range_default_values() { - const input = "<blocklist xmlns=\"http://www.mozilla.org/2006/addons-blocklist\">" + - "<gfxItems>" + - " <gfxBlacklistEntry>" + - " <versionRange minVersion=\"13.0b2\" maxVersion=\"42.0\"/>" + - " </gfxBlacklistEntry>" + - " <gfxBlacklistEntry>" + - " <versionRange maxVersion=\"2.0\"/>" + - " </gfxBlacklistEntry>" + - " <gfxBlacklistEntry>" + - " <versionRange minVersion=\"1.0\"/>" + - " </gfxBlacklistEntry>" + - " <gfxBlacklistEntry>" + - " <versionRange minVersion=\" \"/>" + - " </gfxBlacklistEntry>" + - " <gfxBlacklistEntry>" + - " <versionRange/>" + - " </gfxBlacklistEntry>" + - "</gfxItems>" + - "</blocklist>"; - const blocklist = Blocklist(); - blocklist._loadBlocklistFromString(input); - equal(blocklist._gfxEntries[0].versionRange.minVersion, "13.0b2"); - equal(blocklist._gfxEntries[0].versionRange.maxVersion, "42.0"); - equal(blocklist._gfxEntries[1].versionRange.minVersion, "0"); - equal(blocklist._gfxEntries[1].versionRange.maxVersion, "2.0"); - equal(blocklist._gfxEntries[2].versionRange.minVersion, "1.0"); - equal(blocklist._gfxEntries[2].versionRange.maxVersion, "*"); - equal(blocklist._gfxEntries[3].versionRange.minVersion, "0"); - equal(blocklist._gfxEntries[3].versionRange.maxVersion, "*"); - equal(blocklist._gfxEntries[4].versionRange.minVersion, "0"); - equal(blocklist._gfxEntries[4].versionRange.maxVersion, "*"); -}); - -add_task(function* test_blockid_attribute() { - const input = "<blocklist xmlns=\"http://www.mozilla.org/2006/addons-blocklist\">" + - "<gfxItems>" + - " <gfxBlacklistEntry blockID=\"g60\">" + - " <vendor> 0x10de </vendor>" + - " </gfxBlacklistEntry>" + - " <gfxBlacklistEntry>" + - " <feature> DIRECT3D_9_LAYERS </feature>" + - " </gfxBlacklistEntry>" + - "</gfxItems>" + - "</blocklist>"; - const blocklist = Blocklist(); - blocklist._loadBlocklistFromString(input); - equal(blocklist._gfxEntries[0].blockID, "g60"); - ok(!blocklist._gfxEntries[1].hasOwnProperty("blockID")); -}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_metadata_filters.js b/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_metadata_filters.js index 5befa6fa0..15e951bce 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_metadata_filters.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_metadata_filters.js @@ -5,12 +5,11 @@ // Tests blocking of extensions by ID, name, creator, homepageURL, updateURL // and RegExps for each. See bug 897735. -var {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; +const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; const URI_EXTENSION_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul"; Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://testing-common/MockRegistrar.jsm"); var testserver = new HttpServer(); testserver.start(-1); gPort = testserver.identity.primaryPort; @@ -24,18 +23,18 @@ profileDir.append("extensions"); // Don't need the full interface, attempts to call other methods will just // throw which is just fine var WindowWatcher = { - openWindow: function(parent, url, name, features, args) { + openWindow: function(parent, url, name, features, arguments) { // Should be called to list the newly blocklisted items do_check_eq(url, URI_EXTENSION_BLOCKLIST_DIALOG); // Simulate auto-disabling any softblocks - var list = args.wrappedJSObject.list; + var list = arguments.wrappedJSObject.list; list.forEach(function(aItem) { if (!aItem.blocked) aItem.disable = true; }); - // run the code after the blocklist is closed + //run the code after the blocklist is closed Services.obs.notifyObservers(null, "addon-blocklist-closed", null); }, @@ -49,7 +48,20 @@ var WindowWatcher = { } }; -MockRegistrar.register("@mozilla.org/embedcomp/window-watcher;1", WindowWatcher); +var WindowWatcherFactory = { + createInstance: function createInstance(outer, iid) { + if (outer != null) + throw Cr.NS_ERROR_NO_AGGREGATION; + return WindowWatcher.QueryInterface(iid); + } +}; + +var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); +registrar.registerFactory(Components.ID("{1dfeb90a-2193-45d5-9cb8-864928b2af55}"), + "Fake Window Watcher", + "@mozilla.org/embedcomp/window-watcher;1", + WindowWatcherFactory); + function load_blocklist(aFile, aCallback) { Services.obs.addObserver(function() { diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_prefs.js b/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_prefs.js index 41ef62f98..71112387b 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_prefs.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_prefs.js @@ -5,7 +5,7 @@ // Tests resetting of preferences in blocklist entry when an add-on is blocked. // See bug 802434. -var {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; +const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; const URI_EXTENSION_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul"; @@ -15,7 +15,6 @@ XPCOMUtils.defineLazyGetter(this, "gPref", function bls_gPref() { }); Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://testing-common/MockRegistrar.jsm"); var testserver = new HttpServer(); testserver.start(-1); gPort = testserver.identity.primaryPort; @@ -30,18 +29,18 @@ profileDir.append("extensions"); // Don't need the full interface, attempts to call other methods will just // throw which is just fine var WindowWatcher = { - openWindow: function(parent, url, name, features, args) { + openWindow: function(parent, url, name, features, arguments) { // Should be called to list the newly blocklisted items do_check_eq(url, URI_EXTENSION_BLOCKLIST_DIALOG); // Simulate auto-disabling any softblocks - var list = args.wrappedJSObject.list; + var list = arguments.wrappedJSObject.list; list.forEach(function(aItem) { if (!aItem.blocked) aItem.disable = true; }); - // run the code after the blocklist is closed + //run the code after the blocklist is closed Services.obs.notifyObservers(null, "addon-blocklist-closed", null); }, @@ -55,7 +54,19 @@ var WindowWatcher = { } }; -MockRegistrar.register("@mozilla.org/embedcomp/window-watcher;1", WindowWatcher); +var WindowWatcherFactory = { + createInstance: function createInstance(outer, iid) { + if (outer != null) + throw Cr.NS_ERROR_NO_AGGREGATION; + return WindowWatcher.QueryInterface(iid); + } +}; + +var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); +registrar.registerFactory(Components.ID("{1dfeb90a-2193-45d5-9cb8-864928b2af55}"), + "Fake Window Watcher", + "@mozilla.org/embedcomp/window-watcher;1", + WindowWatcherFactory); function load_blocklist(aFile, aCallback) { Services.obs.addObserver(function() { diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_regexp.js b/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_regexp.js index c89ccdef8..d9acf7170 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_regexp.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_regexp.js @@ -1,114 +1,125 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -// Checks that blocklist entries using RegExp work as expected. This only covers -// behavior specific to RegExp entries - general behavior is already tested -// in test_blocklistchange.js. - -var {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; - -const URI_EXTENSION_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul"; - -Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://testing-common/MockRegistrar.jsm"); -var testserver = new HttpServer(); -testserver.start(-1); -gPort = testserver.identity.primaryPort; - -// register static files with server and interpolate port numbers in them -mapFile("/data/test_blocklist_regexp_1.xml", testserver); - -const profileDir = gProfD.clone(); -profileDir.append("extensions"); - -// Don't need the full interface, attempts to call other methods will just -// throw which is just fine -var WindowWatcher = { - openWindow: function(parent, url, name, features, args) { - // Should be called to list the newly blocklisted items - do_check_eq(url, URI_EXTENSION_BLOCKLIST_DIALOG); - - // Simulate auto-disabling any softblocks - var list = args.wrappedJSObject.list; - list.forEach(function(aItem) { - if (!aItem.blocked) - aItem.disable = true; - }); - - // run the code after the blocklist is closed - Services.obs.notifyObservers(null, "addon-blocklist-closed", null); - - }, - - QueryInterface: function(iid) { - if (iid.equals(Ci.nsIWindowWatcher) - || iid.equals(Ci.nsISupports)) - return this; - - throw Cr.NS_ERROR_NO_INTERFACE; - } -}; - -MockRegistrar.register("@mozilla.org/embedcomp/window-watcher;1", WindowWatcher); - - -function load_blocklist(aFile, aCallback) { - Services.obs.addObserver(function() { - Services.obs.removeObserver(arguments.callee, "blocklist-updated"); - - do_execute_soon(aCallback); - }, "blocklist-updated", false); - - Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" + - gPort + "/data/" + aFile); - var blocklist = Cc["@mozilla.org/extensions/blocklist;1"]. - getService(Ci.nsITimerCallback); - blocklist.notify(null); -} - - -function end_test() { - testserver.stop(do_test_finished); -} - - -function run_test() { - do_test_pending(); - - createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1"); - - writeInstallRDFForExtension({ - id: "block1@tests.mozilla.org", - version: "1.0", - name: "RegExp blocked add-on", - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "1", - maxVersion: "3" - }] - }, profileDir); - - startupManager(); - - AddonManager.getAddonsByIDs(["block1@tests.mozilla.org"], function([a1]) { - do_check_eq(a1.blocklistState, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); - - run_test_1(); - }); -} - -function run_test_1() { - load_blocklist("test_blocklist_regexp_1.xml", function() { - restartManager(); - - AddonManager.getAddonsByIDs(["block1@tests.mozilla.org"], function([a1]) { - // Blocklist contains two entries that will match this addon - ensure - // that the first one is applied. - do_check_neq(a1, null); - do_check_eq(a1.blocklistState, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); - - end_test(); - }); - }); -} +/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Checks that blocklist entries using RegExp work as expected. This only covers
+// behavior specific to RegExp entries - general behavior is already tested
+// in test_blocklistchange.js.
+
+const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
+
+const URI_EXTENSION_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul";
+
+Cu.import("resource://testing-common/httpd.js");
+var testserver = new HttpServer();
+testserver.start(-1);
+gPort = testserver.identity.primaryPort;
+
+// register static files with server and interpolate port numbers in them
+mapFile("/data/test_blocklist_regexp_1.xml", testserver);
+
+const profileDir = gProfD.clone();
+profileDir.append("extensions");
+
+// Don't need the full interface, attempts to call other methods will just
+// throw which is just fine
+var WindowWatcher = {
+ openWindow: function(parent, url, name, features, arguments) {
+ // Should be called to list the newly blocklisted items
+ do_check_eq(url, URI_EXTENSION_BLOCKLIST_DIALOG);
+
+ // Simulate auto-disabling any softblocks
+ var list = arguments.wrappedJSObject.list;
+ list.forEach(function(aItem) {
+ if (!aItem.blocked)
+ aItem.disable = true;
+ });
+
+ //run the code after the blocklist is closed
+ Services.obs.notifyObservers(null, "addon-blocklist-closed", null);
+
+ },
+
+ QueryInterface: function(iid) {
+ if (iid.equals(Ci.nsIWindowWatcher)
+ || iid.equals(Ci.nsISupports))
+ return this;
+
+ throw Cr.NS_ERROR_NO_INTERFACE;
+ }
+};
+
+var WindowWatcherFactory = {
+ createInstance: function createInstance(outer, iid) {
+ if (outer != null)
+ throw Cr.NS_ERROR_NO_AGGREGATION;
+ return WindowWatcher.QueryInterface(iid);
+ }
+};
+
+var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
+registrar.registerFactory(Components.ID("{1dfeb90a-2193-45d5-9cb8-864928b2af55}"),
+ "Fake Window Watcher",
+ "@mozilla.org/embedcomp/window-watcher;1",
+ WindowWatcherFactory);
+
+
+function load_blocklist(aFile, aCallback) {
+ Services.obs.addObserver(function() {
+ Services.obs.removeObserver(arguments.callee, "blocklist-updated");
+
+ do_execute_soon(aCallback);
+ }, "blocklist-updated", false);
+
+ Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" +
+ gPort + "/data/" + aFile);
+ var blocklist = Cc["@mozilla.org/extensions/blocklist;1"].
+ getService(Ci.nsITimerCallback);
+ blocklist.notify(null);
+}
+
+
+function end_test() {
+ testserver.stop(do_test_finished);
+}
+
+
+function run_test() {
+ do_test_pending();
+
+ createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1");
+
+ writeInstallRDFForExtension({
+ id: "block1@tests.mozilla.org",
+ version: "1.0",
+ name: "RegExp blocked add-on",
+ targetApplications: [{
+ id: "xpcshell@tests.mozilla.org",
+ minVersion: "1",
+ maxVersion: "3"
+ }]
+ }, profileDir);
+
+ startupManager();
+
+ AddonManager.getAddonsByIDs(["block1@tests.mozilla.org"], function([a1]) {
+ do_check_eq(a1.blocklistState, Ci.nsIBlocklistService.STATE_NOT_BLOCKED);
+
+ run_test_1();
+ });
+}
+
+function run_test_1() {
+ load_blocklist("test_blocklist_regexp_1.xml", function() {
+ restartManager();
+
+ AddonManager.getAddonsByIDs(["block1@tests.mozilla.org"], function([a1]) {
+ // Blocklist contains two entries that will match this addon - ensure
+ // that the first one is applied.
+ do_check_neq(a1, null);
+ do_check_eq(a1.blocklistState, Ci.nsIBlocklistService.STATE_SOFTBLOCKED);
+
+ end_test();
+ });
+ });
+}
diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_blocklistchange.js b/toolkit/mozapps/extensions/test/xpcshell/test_blocklistchange.js index d065f700d..46f939943 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_blocklistchange.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_blocklistchange.js @@ -27,20 +27,21 @@ // softblocked and have to be manually re-enabled if they become completely // unblocked (bug 657520) -var Cc = Components.classes; -var Ci = Components.interfaces; -var Cu = Components.utils; -var Cr = Components.results; +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cu = Components.utils; +const Cr = Components.results; const URI_EXTENSION_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul"; Cu.import("resource://gre/modules/NetUtil.jsm"); -Cu.import("resource://testing-common/MockRegistrar.jsm"); // Allow insecure updates Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false) -var testserver = createHttpServer(); +Cu.import("resource://testing-common/httpd.js"); +var testserver = new HttpServer(); +testserver.start(-1); gPort = testserver.identity.primaryPort; // register static files with server and interpolate port numbers in them @@ -345,7 +346,7 @@ var WindowWatcher = { aItem.disable = true; }); - // run the code after the blocklist is closed + //run the code after the blocklist is closed Services.obs.notifyObservers(null, "addon-blocklist-closed", null); }, @@ -359,7 +360,13 @@ var WindowWatcher = { } }; -MockRegistrar.register("@mozilla.org/embedcomp/window-watcher;1", WindowWatcher); +var WindowWatcherFactory = { + createInstance: function createInstance(outer, iid) { + if (outer != null) + throw Components.results.NS_ERROR_NO_AGGREGATION; + return WindowWatcher.QueryInterface(iid); + } +}; var InstallConfirm = { confirm: function(aWindow, aUrl, aInstalls, aInstallCount) { @@ -386,6 +393,9 @@ var InstallConfirmFactory = { }; var registrar = Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar); +registrar.registerFactory(Components.ID("{1dfeb90a-2193-45d5-9cb8-864928b2af55}"), + "Fake Window Watcher", + "@mozilla.org/embedcomp/window-watcher;1", WindowWatcherFactory); registrar.registerFactory(Components.ID("{f0863905-4dde-42e2-991c-2dc8209bc9ca}"), "Fake Install Prompt", "@mozilla.org/addons/web-install-prompt;1", InstallConfirmFactory); @@ -481,7 +491,7 @@ function Pmanual_update(aVersion) { // the add-on is valid or not. let webInstaller = Cc["@mozilla.org/addons/web-install-listener;1"] .getService(Ci.amIWebInstallListener); - webInstaller.onWebInstallRequested(null, null, installs); + webInstaller.onWebInstallRequested(null, null, installs, installs.length); return Promise.all(completePromises); }); @@ -1303,3 +1313,9 @@ add_task(function* run_local_install_test() { check_addon(h, "1.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED); check_addon(r, "1.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED); }); + +add_task(function* shutdown_httpserver() { + yield new Promise((resolve, reject) => { + testserver.stop(resolve); + }); +}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bootstrap.js b/toolkit/mozapps/extensions/test/xpcshell/test_bootstrap.js index ff58599bc..e8d12c1fa 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bootstrap.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bootstrap.js @@ -11,9 +11,6 @@ const ADDON_UNINSTALL = 6; const ADDON_UPGRADE = 7; const ADDON_DOWNGRADE = 8; -const ID1 = "bootstrap1@tests.mozilla.org"; -const ID2 = "bootstrap2@tests.mozilla.org"; - // This verifies that bootstrappable add-ons can be used without restarts. Components.utils.import("resource://gre/modules/Services.jsm"); Components.utils.import("resource://gre/modules/Promise.jsm"); @@ -22,8 +19,6 @@ Components.utils.import("resource://gre/modules/Promise.jsm"); Services.prefs.setIntPref("extensions.enabledScopes", AddonManager.SCOPE_PROFILE + AddonManager.SCOPE_USER); -BootstrapMonitor.init(); - createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); const profileDir = gProfD.clone(); @@ -35,49 +30,99 @@ registerDirectory("XREUSysExt", userExtDir.parent); Components.utils.import("resource://testing-common/httpd.js"); var testserver = new HttpServer(); -testserver.start(undefined); +testserver.start(-1); gPort = testserver.identity.primaryPort; testserver.registerDirectory("/addons/", do_get_file("addons")); +function resetPrefs() { + Services.prefs.setIntPref("bootstraptest.active_version", -1); + Services.prefs.setIntPref("bootstraptest.installed_version", -1); + Services.prefs.setIntPref("bootstraptest2.active_version", -1); + Services.prefs.setIntPref("bootstraptest2.installed_version", -1); + Services.prefs.setIntPref("bootstraptest.startup_reason", -1); + Services.prefs.setIntPref("bootstraptest.shutdown_reason", -1); + Services.prefs.setIntPref("bootstraptest.install_reason", -1); + Services.prefs.setIntPref("bootstraptest.uninstall_reason", -1); + Services.prefs.setIntPref("bootstraptest.startup_oldversion", -1); + Services.prefs.setIntPref("bootstraptest.shutdown_newversion", -1); + Services.prefs.setIntPref("bootstraptest.install_oldversion", -1); + Services.prefs.setIntPref("bootstraptest.uninstall_newversion", -1); +} + +function waitForPref(aPref, aCallback) { + function prefChanged() { + Services.prefs.removeObserver(aPref, prefChanged); + // Always let whoever set the preference keep running + do_execute_soon(aCallback); + } + Services.prefs.addObserver(aPref, prefChanged, false); +} + +function promisePref(aPref) { + let deferred = Promise.defer(); + + waitForPref(aPref, deferred.resolve.bind(deferred)); + + return deferred.promise; +} + +function promiseInstall(aFiles) { + let deferred = Promise.defer(); + + installAllFiles(aFiles, function() { + deferred.resolve(); + }); + + return deferred.promise; +} + +function getActiveVersion() { + return Services.prefs.getIntPref("bootstraptest.active_version"); +} + +function getInstalledVersion() { + return Services.prefs.getIntPref("bootstraptest.installed_version"); +} + +function getActiveVersion2() { + return Services.prefs.getIntPref("bootstraptest2.active_version"); +} + +function getInstalledVersion2() { + return Services.prefs.getIntPref("bootstraptest2.installed_version"); +} + function getStartupReason() { - let info = BootstrapMonitor.started.get(ID1); - return info ? info.reason : undefined; + return Services.prefs.getIntPref("bootstraptest.startup_reason"); } function getShutdownReason() { - let info = BootstrapMonitor.stopped.get(ID1); - return info ? info.reason : undefined; + return Services.prefs.getIntPref("bootstraptest.shutdown_reason"); } function getInstallReason() { - let info = BootstrapMonitor.installed.get(ID1); - return info ? info.reason : undefined; + return Services.prefs.getIntPref("bootstraptest.install_reason"); } function getUninstallReason() { - let info = BootstrapMonitor.uninstalled.get(ID1); - return info ? info.reason : undefined; + return Services.prefs.getIntPref("bootstraptest.uninstall_reason"); } function getStartupOldVersion() { - let info = BootstrapMonitor.started.get(ID1); - return info ? info.data.oldVersion : undefined; + return Services.prefs.getIntPref("bootstraptest.startup_oldversion"); } function getShutdownNewVersion() { - let info = BootstrapMonitor.stopped.get(ID1); - return info ? info.data.newVersion : undefined; + return Services.prefs.getIntPref("bootstraptest.shutdown_newversion"); } function getInstallOldVersion() { - let info = BootstrapMonitor.installed.get(ID1); - return info ? info.data.oldVersion : undefined; + return Services.prefs.getIntPref("bootstraptest.install_oldversion"); } function getUninstallNewVersion() { - let info = BootstrapMonitor.uninstalled.get(ID1); - return info ? info.data.newVersion : undefined; + return Services.prefs.getIntPref("bootstraptest.uninstall_newversion"); } function do_check_bootstrappedPref(aCallback) { @@ -112,6 +157,8 @@ function do_check_bootstrappedPref(aCallback) { function run_test() { do_test_pending(); + resetPrefs(); + startupManager(); do_check_false(gExtensionsJSON.exists()); @@ -141,18 +188,18 @@ function run_test_1() { do_check_false(install.addon.hasResource("foo.bar")); do_check_eq(install.addon.operationsRequiringRestart & AddonManager.OP_NEEDS_RESTART_INSTALL, 0); - do_check_not_in_crash_annotation(ID1, "1.0"); + do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0"); let addon = install.addon; - BootstrapMonitor.promiseAddonStartup(ID1).then(function() { + waitForPref("bootstraptest.startup_reason", function() { do_check_bootstrappedPref(function() { check_test_1(addon.syncGUID); }); }); prepare_test({ - [ID1]: [ + "bootstrap1@tests.mozilla.org": [ ["onInstalling", false], "onInstalled" ] @@ -163,7 +210,7 @@ function run_test_1() { do_check_true(addon.hasResource("install.rdf")); // startup should not have been called yet. - BootstrapMonitor.checkAddonNotStarted(ID1); + do_check_eq(getActiveVersion(), -1); }); install.install(); }); @@ -177,7 +224,7 @@ function check_test_1(installSyncGUID) { // doesn't require a restart. do_check_eq(installs.length, 0); - AddonManager.getAddonByID(ID1, function(b1) { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { do_check_neq(b1, null); do_check_eq(b1.version, "1.0"); do_check_neq(b1.syncGUID, null); @@ -185,17 +232,16 @@ function check_test_1(installSyncGUID) { do_check_false(b1.appDisabled); do_check_false(b1.userDisabled); do_check_true(b1.isActive); - do_check_false(b1.isSystem); - BootstrapMonitor.checkAddonInstalled(ID1, "1.0"); - BootstrapMonitor.checkAddonStarted(ID1, "1.0"); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 1); do_check_eq(getStartupReason(), ADDON_INSTALL); - do_check_eq(getStartupOldVersion(), undefined); + do_check_eq(getStartupOldVersion(), 0); do_check_true(b1.hasResource("install.rdf")); do_check_true(b1.hasResource("bootstrap.js")); do_check_false(b1.hasResource("foo.bar")); - do_check_in_crash_annotation(ID1, "1.0"); + do_check_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0"); - let dir = do_get_addon_root_uri(profileDir, ID1); + let dir = do_get_addon_root_uri(profileDir, "bootstrap1@tests.mozilla.org"); do_check_eq(b1.getResourceURI("bootstrap.js").spec, dir + "bootstrap.js"); AddonManager.getAddonsWithOperationsByTypes(null, function(list) { @@ -209,9 +255,9 @@ function check_test_1(installSyncGUID) { // Tests that disabling doesn't require a restart function run_test_2() { - AddonManager.getAddonByID(ID1, function(b1) { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { prepare_test({ - [ID1]: [ + "bootstrap1@tests.mozilla.org": [ ["onDisabling", false], "onDisabled" ] @@ -227,13 +273,13 @@ function run_test_2() { do_check_false(b1.appDisabled); do_check_true(b1.userDisabled); do_check_false(b1.isActive); - BootstrapMonitor.checkAddonInstalled(ID1, "1.0"); - BootstrapMonitor.checkAddonNotStarted(ID1); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 0); do_check_eq(getShutdownReason(), ADDON_DISABLE); - do_check_eq(getShutdownNewVersion(), undefined); - do_check_not_in_crash_annotation(ID1, "1.0"); + do_check_eq(getShutdownNewVersion(), 0); + do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0"); - AddonManager.getAddonByID(ID1, function(newb1) { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(newb1) { do_check_neq(newb1, null); do_check_eq(newb1.version, "1.0"); do_check_false(newb1.appDisabled); @@ -248,20 +294,20 @@ function run_test_2() { // Test that restarting doesn't accidentally re-enable function run_test_3() { shutdownManager(); - BootstrapMonitor.checkAddonInstalled(ID1, "1.0"); - BootstrapMonitor.checkAddonNotStarted(ID1); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 0); do_check_eq(getShutdownReason(), ADDON_DISABLE); - do_check_eq(getShutdownNewVersion(), undefined); + do_check_eq(getShutdownNewVersion(), 0); startupManager(false); - BootstrapMonitor.checkAddonInstalled(ID1, "1.0"); - BootstrapMonitor.checkAddonNotStarted(ID1); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 0); do_check_eq(getShutdownReason(), ADDON_DISABLE); - do_check_eq(getShutdownNewVersion(), undefined); - do_check_not_in_crash_annotation(ID1, "1.0"); + do_check_eq(getShutdownNewVersion(), 0); + do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0"); do_check_false(gExtensionsINI.exists()); - AddonManager.getAddonByID(ID1, function(b1) { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { do_check_neq(b1, null); do_check_eq(b1.version, "1.0"); do_check_false(b1.appDisabled); @@ -274,9 +320,9 @@ function run_test_3() { // Tests that enabling doesn't require a restart function run_test_4() { - AddonManager.getAddonByID(ID1, function(b1) { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { prepare_test({ - [ID1]: [ + "bootstrap1@tests.mozilla.org": [ ["onEnabling", false], "onEnabled" ] @@ -292,14 +338,13 @@ function run_test_4() { do_check_false(b1.appDisabled); do_check_false(b1.userDisabled); do_check_true(b1.isActive); - do_check_false(b1.isSystem); - BootstrapMonitor.checkAddonInstalled(ID1, "1.0"); - BootstrapMonitor.checkAddonStarted(ID1, "1.0"); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 1); do_check_eq(getStartupReason(), ADDON_ENABLE); - do_check_eq(getStartupOldVersion(), undefined); - do_check_in_crash_annotation(ID1, "1.0"); + do_check_eq(getStartupOldVersion(), 0); + do_check_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0"); - AddonManager.getAddonByID(ID1, function(newb1) { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(newb1) { do_check_neq(newb1, null); do_check_eq(newb1.version, "1.0"); do_check_false(newb1.appDisabled); @@ -317,25 +362,24 @@ function run_test_5() { // By the time we've shut down, the database must have been written do_check_true(gExtensionsJSON.exists()); - BootstrapMonitor.checkAddonInstalled(ID1, "1.0"); - BootstrapMonitor.checkAddonNotStarted(ID1); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 0); do_check_eq(getShutdownReason(), APP_SHUTDOWN); - do_check_eq(getShutdownNewVersion(), undefined); - do_check_not_in_crash_annotation(ID1, "1.0"); + do_check_eq(getShutdownNewVersion(), 0); + do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0"); startupManager(false); - BootstrapMonitor.checkAddonInstalled(ID1, "1.0"); - BootstrapMonitor.checkAddonStarted(ID1, "1.0"); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 1); do_check_eq(getStartupReason(), APP_STARTUP); - do_check_eq(getStartupOldVersion(), undefined); - do_check_in_crash_annotation(ID1, "1.0"); + do_check_eq(getStartupOldVersion(), 0); + do_check_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0"); - AddonManager.getAddonByID(ID1, function(b1) { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { do_check_neq(b1, null); do_check_eq(b1.version, "1.0"); do_check_false(b1.appDisabled); do_check_false(b1.userDisabled); do_check_true(b1.isActive); - do_check_false(b1.isSystem); do_check_false(isExtensionInAddonsList(profileDir, b1.id)); do_check_bootstrappedPref(run_test_6); @@ -357,9 +401,9 @@ function run_test_6() { do_check_eq(install.name, "Test Bootstrap 1"); do_check_eq(install.state, AddonManager.STATE_DOWNLOADED); - BootstrapMonitor.promiseAddonStartup(ID1).then(check_test_6); + waitForPref("bootstraptest.startup_reason", check_test_6); prepare_test({ - [ID1]: [ + "bootstrap1@tests.mozilla.org": [ ["onInstalling", false], "onInstalled" ] @@ -373,23 +417,22 @@ function run_test_6() { } function check_test_6() { - AddonManager.getAddonByID(ID1, function(b1) { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { do_check_neq(b1, null); do_check_eq(b1.version, "2.0"); do_check_false(b1.appDisabled); do_check_false(b1.userDisabled); do_check_true(b1.isActive); - do_check_false(b1.isSystem); - BootstrapMonitor.checkAddonInstalled(ID1, "2.0"); - BootstrapMonitor.checkAddonStarted(ID1, "2.0"); + do_check_eq(getInstalledVersion(), 2); + do_check_eq(getActiveVersion(), 2); do_check_eq(getStartupReason(), ADDON_UPGRADE); do_check_eq(getInstallOldVersion(), 1); do_check_eq(getStartupOldVersion(), 1); do_check_eq(getShutdownReason(), ADDON_UPGRADE); do_check_eq(getShutdownNewVersion(), 2); do_check_eq(getUninstallNewVersion(), 2); - do_check_not_in_crash_annotation(ID1, "1.0"); - do_check_in_crash_annotation(ID1, "2.0"); + do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0"); + do_check_in_crash_annotation("bootstrap1@tests.mozilla.org", "2.0"); do_check_bootstrappedPref(run_test_7); }); @@ -397,9 +440,9 @@ function check_test_6() { // Tests that uninstalling doesn't require a restart function run_test_7() { - AddonManager.getAddonByID(ID1, function(b1) { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { prepare_test({ - [ID1]: [ + "bootstrap1@tests.mozilla.org": [ ["onUninstalling", false], "onUninstalled" ] @@ -415,18 +458,18 @@ function run_test_7() { function check_test_7() { ensure_test_completed(); - BootstrapMonitor.checkAddonNotInstalled(ID1); - BootstrapMonitor.checkAddonNotStarted(ID1); + do_check_eq(getInstalledVersion(), 0); + do_check_eq(getActiveVersion(), 0); do_check_eq(getShutdownReason(), ADDON_UNINSTALL); - do_check_eq(getShutdownNewVersion(), undefined); - do_check_not_in_crash_annotation(ID1, "2.0"); + do_check_eq(getShutdownNewVersion(), 0); + do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "2.0"); - AddonManager.getAddonByID(ID1, callback_soon(function(b1) { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) { do_check_eq(b1, null); restartManager(); - AddonManager.getAddonByID(ID1, function(newb1) { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(newb1) { do_check_eq(newb1, null); do_check_bootstrappedPref(run_test_8); @@ -440,22 +483,21 @@ function run_test_8() { shutdownManager(); manuallyInstall(do_get_addon("test_bootstrap1_1"), profileDir, - ID1); + "bootstrap1@tests.mozilla.org"); startupManager(false); - AddonManager.getAddonByID(ID1, function(b1) { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { do_check_neq(b1, null); do_check_eq(b1.version, "1.0"); do_check_false(b1.appDisabled); do_check_false(b1.userDisabled); do_check_true(b1.isActive); - do_check_false(b1.isSystem); - BootstrapMonitor.checkAddonInstalled(ID1, "1.0"); - BootstrapMonitor.checkAddonStarted(ID1, "1.0"); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 1); do_check_eq(getStartupReason(), ADDON_INSTALL); - do_check_eq(getStartupOldVersion(), undefined); - do_check_in_crash_annotation(ID1, "1.0"); + do_check_eq(getStartupOldVersion(), 0); + do_check_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0"); do_check_bootstrappedPref(run_test_9); }); @@ -465,14 +507,13 @@ function run_test_8() { function run_test_9() { shutdownManager(); - manuallyUninstall(profileDir, ID1); - BootstrapMonitor.clear(ID1); + manuallyUninstall(profileDir, "bootstrap1@tests.mozilla.org"); startupManager(false); - AddonManager.getAddonByID(ID1, function(b1) { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { do_check_eq(b1, null); - do_check_not_in_crash_annotation(ID1, "1.0"); + do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0"); do_check_bootstrappedPref(run_test_10); }); @@ -481,6 +522,7 @@ function run_test_9() { // Tests that installing a downgrade sends the right reason function run_test_10() { + resetPrefs(); prepare_test({ }, [ "onNewInstall" ]); @@ -496,11 +538,11 @@ function run_test_10() { do_check_true(install.addon.hasResource("install.rdf")); do_check_true(install.addon.hasResource("bootstrap.js")); do_check_false(install.addon.hasResource("foo.bar")); - do_check_not_in_crash_annotation(ID1, "2.0"); + do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "2.0"); - BootstrapMonitor.promiseAddonStartup(ID1).then(check_test_10_pt1); + waitForPref("bootstraptest.startup_reason", check_test_10_pt1); prepare_test({ - [ID1]: [ + "bootstrap1@tests.mozilla.org": [ ["onInstalling", false], "onInstalled" ] @@ -515,21 +557,20 @@ function run_test_10() { } function check_test_10_pt1() { - AddonManager.getAddonByID(ID1, function(b1) { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { do_check_neq(b1, null); do_check_eq(b1.version, "2.0"); do_check_false(b1.appDisabled); do_check_false(b1.userDisabled); do_check_true(b1.isActive); - do_check_false(b1.isSystem); - BootstrapMonitor.checkAddonInstalled(ID1, "2.0"); - BootstrapMonitor.checkAddonStarted(ID1, "2.0"); + do_check_eq(getInstalledVersion(), 2); + do_check_eq(getActiveVersion(), 2); do_check_eq(getStartupReason(), ADDON_INSTALL); - do_check_eq(getStartupOldVersion(), undefined); + do_check_eq(getStartupOldVersion(), 0); do_check_true(b1.hasResource("install.rdf")); do_check_true(b1.hasResource("bootstrap.js")); do_check_false(b1.hasResource("foo.bar")); - do_check_in_crash_annotation(ID1, "2.0"); + do_check_in_crash_annotation("bootstrap1@tests.mozilla.org", "2.0"); prepare_test({ }, [ "onNewInstall" @@ -544,9 +585,9 @@ function check_test_10_pt1() { do_check_eq(install.name, "Test Bootstrap 1"); do_check_eq(install.state, AddonManager.STATE_DOWNLOADED); - BootstrapMonitor.promiseAddonStartup(ID1).then(check_test_10_pt2); + waitForPref("bootstraptest.startup_reason", check_test_10_pt2); prepare_test({ - [ID1]: [ + "bootstrap1@tests.mozilla.org": [ ["onInstalling", false], "onInstalled" ] @@ -560,23 +601,22 @@ function check_test_10_pt1() { } function check_test_10_pt2() { - AddonManager.getAddonByID(ID1, function(b1) { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { do_check_neq(b1, null); do_check_eq(b1.version, "1.0"); do_check_false(b1.appDisabled); do_check_false(b1.userDisabled); do_check_true(b1.isActive); - do_check_false(b1.isSystem); - BootstrapMonitor.checkAddonInstalled(ID1, "1.0"); - BootstrapMonitor.checkAddonStarted(ID1, "1.0"); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 1); do_check_eq(getStartupReason(), ADDON_DOWNGRADE); do_check_eq(getInstallOldVersion(), 2); do_check_eq(getStartupOldVersion(), 2); do_check_eq(getShutdownReason(), ADDON_DOWNGRADE); do_check_eq(getShutdownNewVersion(), 1); do_check_eq(getUninstallNewVersion(), 1); - do_check_in_crash_annotation(ID1, "1.0"); - do_check_not_in_crash_annotation(ID1, "2.0"); + do_check_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0"); + do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "2.0"); do_check_bootstrappedPref(run_test_11); }); @@ -584,9 +624,9 @@ function check_test_10_pt2() { // Tests that uninstalling a disabled add-on still calls the uninstall method function run_test_11() { - AddonManager.getAddonByID(ID1, function(b1) { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { prepare_test({ - [ID1]: [ + "bootstrap1@tests.mozilla.org": [ ["onDisabling", false], "onDisabled", ["onUninstalling", false], @@ -596,11 +636,11 @@ function run_test_11() { b1.userDisabled = true; - BootstrapMonitor.checkAddonInstalled(ID1, "1.0"); - BootstrapMonitor.checkAddonNotStarted(ID1); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 0); do_check_eq(getShutdownReason(), ADDON_DISABLE); - do_check_eq(getShutdownNewVersion(), undefined); - do_check_not_in_crash_annotation(ID1, "1.0"); + do_check_eq(getShutdownNewVersion(), 0); + do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0"); b1.uninstall(); @@ -610,9 +650,9 @@ function run_test_11() { function check_test_11() { ensure_test_completed(); - BootstrapMonitor.checkAddonNotInstalled(ID1); - BootstrapMonitor.checkAddonNotStarted(ID1); - do_check_not_in_crash_annotation(ID1, "1.0"); + do_check_eq(getInstalledVersion(), 0); + do_check_eq(getActiveVersion(), 0); + do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0"); do_check_bootstrappedPref(run_test_12); } @@ -623,22 +663,21 @@ function run_test_12() { shutdownManager(); manuallyInstall(do_get_addon("test_bootstrap1_1"), profileDir, - ID1); + "bootstrap1@tests.mozilla.org"); startupManager(true); - AddonManager.getAddonByID(ID1, function(b1) { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { do_check_neq(b1, null); do_check_eq(b1.version, "1.0"); do_check_false(b1.appDisabled); do_check_false(b1.userDisabled); do_check_true(b1.isActive); - do_check_false(b1.isSystem); - BootstrapMonitor.checkAddonInstalled(ID1, "1.0"); - BootstrapMonitor.checkAddonStarted(ID1, "1.0"); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 1); do_check_eq(getStartupReason(), ADDON_INSTALL); - do_check_eq(getStartupOldVersion(), undefined); - do_check_in_crash_annotation(ID1, "1.0"); + do_check_eq(getStartupOldVersion(), 0); + do_check_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0"); b1.uninstall(); do_execute_soon(test_12_restart); @@ -666,10 +705,10 @@ function run_test_13() { do_check_eq(install.version, "3.0"); do_check_eq(install.name, "Test Bootstrap 1"); do_check_eq(install.state, AddonManager.STATE_DOWNLOADED); - do_check_not_in_crash_annotation(ID1, "3.0"); + do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "3.0"); prepare_test({ - [ID1]: [ + "bootstrap1@tests.mozilla.org": [ ["onInstalling", false], "onInstalled" ] @@ -687,15 +726,15 @@ function check_test_13() { // doesn't require a restart. do_check_eq(installs.length, 0); - AddonManager.getAddonByID(ID1, function(b1) { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { do_check_neq(b1, null); do_check_eq(b1.version, "3.0"); do_check_true(b1.appDisabled); do_check_false(b1.userDisabled); do_check_false(b1.isActive); - BootstrapMonitor.checkAddonInstalled(ID1, "3.0"); // We call install even for disabled add-ons - BootstrapMonitor.checkAddonNotStarted(ID1); // Should not have called startup though - do_check_not_in_crash_annotation(ID1, "3.0"); + do_check_eq(getInstalledVersion(), 3); // We call install even for disabled add-ons + do_check_eq(getActiveVersion(), 0); // Should not have called startup though + do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "3.0"); do_execute_soon(test_13_restart); }); @@ -705,15 +744,15 @@ function check_test_13() { function test_13_restart() { restartManager(); - AddonManager.getAddonByID(ID1, function(b1) { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { do_check_neq(b1, null); do_check_eq(b1.version, "3.0"); do_check_true(b1.appDisabled); do_check_false(b1.userDisabled); do_check_false(b1.isActive); - BootstrapMonitor.checkAddonInstalled(ID1, "3.0"); // We call install even for disabled add-ons - BootstrapMonitor.checkAddonNotStarted(ID1); // Should not have called startup though - do_check_not_in_crash_annotation(ID1, "3.0"); + do_check_eq(getInstalledVersion(), 3); // We call install even for disabled add-ons + do_check_eq(getActiveVersion(), 0); // Should not have called startup though + do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "3.0"); do_check_bootstrappedPref(function() { b1.uninstall(); @@ -730,19 +769,19 @@ function run_test_14() { shutdownManager(); manuallyInstall(do_get_addon("test_bootstrap1_3"), profileDir, - ID1); + "bootstrap1@tests.mozilla.org"); startupManager(false); - AddonManager.getAddonByID(ID1, function(b1) { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { do_check_neq(b1, null); do_check_eq(b1.version, "3.0"); do_check_true(b1.appDisabled); do_check_false(b1.userDisabled); do_check_false(b1.isActive); - BootstrapMonitor.checkAddonInstalled(ID1, "3.0"); // We call install even for disabled add-ons - BootstrapMonitor.checkAddonNotStarted(ID1); // Should not have called startup though - do_check_not_in_crash_annotation(ID1, "3.0"); + do_check_eq(getInstalledVersion(), 3); // We call install even for disabled add-ons + do_check_eq(getActiveVersion(), 0); // Should not have called startup though + do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "3.0"); do_check_bootstrappedPref(function() { b1.uninstall(); @@ -755,21 +794,21 @@ function run_test_14() { // Tests that upgrading a disabled bootstrapped extension still calls uninstall // and install but doesn't startup the new version function run_test_15() { - BootstrapMonitor.promiseAddonStartup(ID1).then(function test_15_after_startup() { - AddonManager.getAddonByID(ID1, function(b1) { + resetPrefs(); + waitForPref("bootstraptest.startup_reason", function test_15_after_startup() { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { do_check_neq(b1, null); do_check_eq(b1.version, "1.0"); do_check_false(b1.appDisabled); do_check_false(b1.userDisabled); do_check_true(b1.isActive); - do_check_false(b1.isSystem); - BootstrapMonitor.checkAddonInstalled(ID1, "1.0"); - BootstrapMonitor.checkAddonStarted(ID1, "1.0"); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 1); b1.userDisabled = true; do_check_false(b1.isActive); - BootstrapMonitor.checkAddonInstalled(ID1, "1.0"); - BootstrapMonitor.checkAddonNotStarted(ID1); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 0); prepare_test({ }, [ "onNewInstall" @@ -782,7 +821,7 @@ function run_test_15() { do_check_true(install.addon.userDisabled); prepare_test({ - [ID1]: [ + "bootstrap1@tests.mozilla.org": [ ["onInstalling", false], "onInstalled" ] @@ -798,28 +837,28 @@ function run_test_15() { } function check_test_15() { - AddonManager.getAddonByID(ID1, function(b1) { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { do_check_neq(b1, null); do_check_eq(b1.version, "2.0"); do_check_false(b1.appDisabled); do_check_true(b1.userDisabled); do_check_false(b1.isActive); - BootstrapMonitor.checkAddonInstalled(ID1, "2.0"); - BootstrapMonitor.checkAddonNotStarted(ID1); + do_check_eq(getInstalledVersion(), 2); + do_check_eq(getActiveVersion(), 0); do_check_bootstrappedPref(function() { restartManager(); - AddonManager.getAddonByID(ID1, callback_soon(function(b1_2) { - do_check_neq(b1_2, null); - do_check_eq(b1_2.version, "2.0"); - do_check_false(b1_2.appDisabled); - do_check_true(b1_2.userDisabled); - do_check_false(b1_2.isActive); - BootstrapMonitor.checkAddonInstalled(ID1, "2.0"); - BootstrapMonitor.checkAddonNotStarted(ID1); + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "2.0"); + do_check_false(b1.appDisabled); + do_check_true(b1.userDisabled); + do_check_false(b1.isActive); + do_check_eq(getInstalledVersion(), 2); + do_check_eq(getActiveVersion(), 0); - b1_2.uninstall(); + b1.uninstall(); run_test_16(); })); @@ -829,13 +868,13 @@ function check_test_15() { // Tests that bootstrapped extensions don't get loaded when in safe mode function run_test_16() { - BootstrapMonitor.promiseAddonStartup(ID1).then(function test_16_after_startup() { - AddonManager.getAddonByID(ID1, callback_soon(function(b1) { + resetPrefs(); + waitForPref("bootstraptest.startup_reason", function test_16_after_startup() { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) { // Should have installed and started - BootstrapMonitor.checkAddonInstalled(ID1, "1.0"); - BootstrapMonitor.checkAddonStarted(ID1, "1.0"); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 1); do_check_true(b1.isActive); - do_check_false(b1.isSystem); do_check_eq(b1.iconURL, "chrome://foo/skin/icon.png"); do_check_eq(b1.aboutURL, "chrome://foo/content/about.xul"); do_check_eq(b1.optionsURL, "chrome://foo/content/options.xul"); @@ -843,31 +882,31 @@ function run_test_16() { shutdownManager(); // Should have stopped - BootstrapMonitor.checkAddonInstalled(ID1, "1.0"); - BootstrapMonitor.checkAddonNotStarted(ID1); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 0); gAppInfo.inSafeMode = true; startupManager(false); - AddonManager.getAddonByID(ID1, callback_soon(function(b1_2) { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) { // Should still be stopped - BootstrapMonitor.checkAddonInstalled(ID1, "1.0"); - BootstrapMonitor.checkAddonNotStarted(ID1); - do_check_false(b1_2.isActive); - do_check_eq(b1_2.iconURL, null); - do_check_eq(b1_2.aboutURL, null); - do_check_eq(b1_2.optionsURL, null); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 0); + do_check_false(b1.isActive); + do_check_eq(b1.iconURL, null); + do_check_eq(b1.aboutURL, null); + do_check_eq(b1.optionsURL, null); shutdownManager(); gAppInfo.inSafeMode = false; startupManager(false); // Should have started - BootstrapMonitor.checkAddonInstalled(ID1, "1.0"); - BootstrapMonitor.checkAddonStarted(ID1, "1.0"); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 1); - AddonManager.getAddonByID(ID1, function(b1_3) { - b1_3.uninstall(); + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + b1.uninstall(); do_execute_soon(run_test_17); }); @@ -882,18 +921,18 @@ function run_test_17() { shutdownManager(); manuallyInstall(do_get_addon("test_bootstrap1_1"), userExtDir, - ID1); + "bootstrap1@tests.mozilla.org"); + resetPrefs(); startupManager(); - AddonManager.getAddonByID(ID1, function(b1) { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { // Should have installed and started - BootstrapMonitor.checkAddonInstalled(ID1, "1.0"); - BootstrapMonitor.checkAddonStarted(ID1, "1.0"); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 1); do_check_neq(b1, null); do_check_eq(b1.version, "1.0"); do_check_true(b1.isActive); - do_check_false(b1.isSystem); do_check_bootstrappedPref(run_test_18); }); @@ -902,15 +941,15 @@ function run_test_17() { // Check that installing a new bootstrapped extension in the profile replaces // the existing one function run_test_18() { - BootstrapMonitor.promiseAddonStartup(ID1).then(function test_18_after_startup() { - AddonManager.getAddonByID(ID1, function(b1) { + resetPrefs(); + waitForPref("bootstraptest.startup_reason", function test_18_after_startup() { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { // Should have installed and started - BootstrapMonitor.checkAddonInstalled(ID1, "2.0"); - BootstrapMonitor.checkAddonStarted(ID1, "2.0"); + do_check_eq(getInstalledVersion(), 2); + do_check_eq(getActiveVersion(), 2); do_check_neq(b1, null); do_check_eq(b1.version, "2.0"); do_check_true(b1.isActive); - do_check_false(b1.isSystem); do_check_eq(getShutdownReason(), ADDON_UPGRADE); do_check_eq(getUninstallReason(), ADDON_UPGRADE); @@ -930,10 +969,11 @@ function run_test_18() { // Check that uninstalling the profile version reveals the non-profile one function run_test_19() { - AddonManager.getAddonByID(ID1, function(b1) { + resetPrefs(); + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { // The revealed add-on gets activated asynchronously prepare_test({ - [ID1]: [ + "bootstrap1@tests.mozilla.org": [ ["onUninstalling", false], "onUninstalled", ["onInstalling", false], @@ -946,14 +986,13 @@ function run_test_19() { } function check_test_19() { - AddonManager.getAddonByID(ID1, function(b1) { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { // Should have reverted to the older version - BootstrapMonitor.checkAddonInstalled(ID1, "1.0"); - BootstrapMonitor.checkAddonStarted(ID1, "1.0"); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 1); do_check_neq(b1, null); do_check_eq(b1.version, "1.0"); do_check_true(b1.isActive); - do_check_false(b1.isSystem); // TODO these reasons really should be ADDON_DOWNGRADE (bug 607818) do_check_eq(getShutdownReason(), ADDON_UNINSTALL); @@ -961,10 +1000,10 @@ function check_test_19() { do_check_eq(getInstallReason(), ADDON_INSTALL); do_check_eq(getStartupReason(), ADDON_INSTALL); - do_check_eq(getShutdownNewVersion(), undefined); - do_check_eq(getUninstallNewVersion(), undefined); - do_check_eq(getInstallOldVersion(), undefined); - do_check_eq(getStartupOldVersion(), undefined); + do_check_eq(getShutdownNewVersion(), 0); + do_check_eq(getUninstallNewVersion(), 0); + do_check_eq(getInstallOldVersion(), 0); + do_check_eq(getStartupOldVersion(), 0); do_check_bootstrappedPref(run_test_20); }); @@ -973,31 +1012,31 @@ function check_test_19() { // Check that a new profile extension detected at startup replaces the non-profile // one function run_test_20() { + resetPrefs(); shutdownManager(); manuallyInstall(do_get_addon("test_bootstrap1_2"), profileDir, - ID1); + "bootstrap1@tests.mozilla.org"); startupManager(); - AddonManager.getAddonByID(ID1, function(b1) { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { // Should have installed and started - BootstrapMonitor.checkAddonInstalled(ID1, "2.0"); - BootstrapMonitor.checkAddonStarted(ID1, "2.0"); + do_check_eq(getInstalledVersion(), 2); + do_check_eq(getActiveVersion(), 2); do_check_neq(b1, null); do_check_eq(b1.version, "2.0"); do_check_true(b1.isActive); - do_check_false(b1.isSystem); do_check_eq(getShutdownReason(), APP_SHUTDOWN); do_check_eq(getUninstallReason(), ADDON_UPGRADE); do_check_eq(getInstallReason(), ADDON_UPGRADE); do_check_eq(getStartupReason(), APP_STARTUP); - do_check_eq(getShutdownNewVersion(), undefined); + do_check_eq(getShutdownNewVersion(), 0); do_check_eq(getUninstallNewVersion(), 2); do_check_eq(getInstallOldVersion(), 1); - do_check_eq(getStartupOldVersion(), undefined); + do_check_eq(getStartupOldVersion(), 0); do_execute_soon(run_test_21); }); @@ -1005,43 +1044,40 @@ function run_test_20() { // Check that a detected removal reveals the non-profile one function run_test_21() { + resetPrefs(); shutdownManager(); - do_check_eq(getShutdownReason(), APP_SHUTDOWN); - do_check_eq(getShutdownNewVersion(), undefined); - - manuallyUninstall(profileDir, ID1); - BootstrapMonitor.clear(ID1); + manuallyUninstall(profileDir, "bootstrap1@tests.mozilla.org"); startupManager(); - AddonManager.getAddonByID(ID1, function(b1) { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { // Should have installed and started - BootstrapMonitor.checkAddonInstalled(ID1, "1.0"); - BootstrapMonitor.checkAddonStarted(ID1, "1.0"); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 1); do_check_neq(b1, null); do_check_eq(b1.version, "1.0"); do_check_true(b1.isActive); - do_check_false(b1.isSystem); + + do_check_eq(getShutdownReason(), APP_SHUTDOWN); + do_check_eq(getShutdownNewVersion(), 0); // This won't be set as the bootstrap script was gone so we couldn't // uninstall it properly - do_check_eq(getUninstallReason(), undefined); - do_check_eq(getUninstallNewVersion(), undefined); + do_check_eq(getUninstallReason(), -1); + do_check_eq(getUninstallNewVersion(), -1); - do_check_eq(getInstallReason(), ADDON_DOWNGRADE); - do_check_eq(getInstallOldVersion(), 2); + // TODO this reason should probably be ADDON_DOWNGRADE (bug 607818) + do_check_eq(getInstallReason(), ADDON_INSTALL); + do_check_eq(getInstallOldVersion(), 0); do_check_eq(getStartupReason(), APP_STARTUP); - do_check_eq(getStartupOldVersion(), undefined); + do_check_eq(getStartupOldVersion(), 0); do_check_bootstrappedPref(function() { - shutdownManager(); + manuallyUninstall(userExtDir, "bootstrap1@tests.mozilla.org"); - manuallyUninstall(userExtDir, ID1); - BootstrapMonitor.clear(ID1); - - startupManager(false); + restartManager(); run_test_22(); }); }); @@ -1052,55 +1088,53 @@ function run_test_22() { shutdownManager(); let file = manuallyInstall(do_get_addon("test_bootstrap1_1"), profileDir, - ID1); + "bootstrap1@tests.mozilla.org"); // Make it look old so changes are detected setExtensionModifiedTime(file, file.lastModifiedTime - 5000); startupManager(); - AddonManager.getAddonByID(ID1, callback_soon(function(b1) { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) { // Should have installed and started - BootstrapMonitor.checkAddonInstalled(ID1, "1.0"); - BootstrapMonitor.checkAddonStarted(ID1, "1.0"); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 1); do_check_neq(b1, null); do_check_eq(b1.version, "1.0"); do_check_true(b1.isActive); - do_check_false(b1.isSystem); + resetPrefs(); shutdownManager(); - do_check_eq(getShutdownReason(), APP_SHUTDOWN); - do_check_eq(getShutdownNewVersion(), undefined); - - manuallyUninstall(profileDir, ID1); - BootstrapMonitor.clear(ID1); + manuallyUninstall(profileDir, "bootstrap1@tests.mozilla.org"); manuallyInstall(do_get_addon("test_bootstrap1_2"), profileDir, - ID1); + "bootstrap1@tests.mozilla.org"); startupManager(); - AddonManager.getAddonByID(ID1, function(b1_2) { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { // Should have installed and started - BootstrapMonitor.checkAddonInstalled(ID1, "2.0"); - BootstrapMonitor.checkAddonStarted(ID1, "2.0"); - do_check_neq(b1_2, null); - do_check_eq(b1_2.version, "2.0"); - do_check_true(b1_2.isActive); - do_check_false(b1_2.isSystem); + do_check_eq(getInstalledVersion(), 2); + do_check_eq(getActiveVersion(), 2); + do_check_neq(b1, null); + do_check_eq(b1.version, "2.0"); + do_check_true(b1.isActive); + + do_check_eq(getShutdownReason(), APP_SHUTDOWN); + do_check_eq(getShutdownNewVersion(), 0); // This won't be set as the bootstrap script was gone so we couldn't // uninstall it properly - do_check_eq(getUninstallReason(), undefined); - do_check_eq(getUninstallNewVersion(), undefined); + do_check_eq(getUninstallReason(), -1); + do_check_eq(getUninstallNewVersion(), -1); do_check_eq(getInstallReason(), ADDON_UPGRADE); do_check_eq(getInstallOldVersion(), 1); do_check_eq(getStartupReason(), APP_STARTUP); - do_check_eq(getStartupOldVersion(), undefined); + do_check_eq(getStartupOldVersion(), 0); do_check_bootstrappedPref(function() { - b1_2.uninstall(); + b1.uninstall(); run_test_23(); }); @@ -1134,11 +1168,11 @@ function run_test_23() { do_check_false(install.addon.hasResource("foo.bar")); do_check_eq(install.addon.operationsRequiringRestart & AddonManager.OP_NEEDS_RESTART_INSTALL, 0); - do_check_not_in_crash_annotation(ID1, "1.0"); + do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0"); let addon = install.addon; prepare_test({ - [ID1]: [ + "bootstrap1@tests.mozilla.org": [ ["onInstalling", false], "onInstalled" ] @@ -1160,32 +1194,31 @@ function check_test_23() { // doesn't require a restart. do_check_eq(installs.length, 0); - AddonManager.getAddonByID(ID1, function(b1) { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { do_execute_soon(function test_23_after_startup() { do_check_neq(b1, null); do_check_eq(b1.version, "1.0"); do_check_false(b1.appDisabled); do_check_false(b1.userDisabled); do_check_true(b1.isActive); - do_check_false(b1.isSystem); - BootstrapMonitor.checkAddonInstalled(ID1, "1.0"); - BootstrapMonitor.checkAddonStarted(ID1, "1.0"); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 1); do_check_eq(getStartupReason(), ADDON_INSTALL); - do_check_eq(getStartupOldVersion(), undefined); + do_check_eq(getStartupOldVersion(), 0); do_check_true(b1.hasResource("install.rdf")); do_check_true(b1.hasResource("bootstrap.js")); do_check_false(b1.hasResource("foo.bar")); - do_check_in_crash_annotation(ID1, "1.0"); + do_check_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0"); - let dir = do_get_addon_root_uri(profileDir, ID1); + let dir = do_get_addon_root_uri(profileDir, "bootstrap1@tests.mozilla.org"); do_check_eq(b1.getResourceURI("bootstrap.js").spec, dir + "bootstrap.js"); AddonManager.getAddonsWithOperationsByTypes(null, callback_soon(function(list) { do_check_eq(list.length, 0); restartManager(); - AddonManager.getAddonByID(ID1, callback_soon(function(b1_2) { - b1_2.uninstall(); + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) { + b1.uninstall(); restartManager(); testserver.stop(run_test_24); @@ -1198,42 +1231,45 @@ function check_test_23() { // Tests that we recover from a broken preference function run_test_24() { + resetPrefs(); do_print("starting 24"); - Promise.all([BootstrapMonitor.promiseAddonStartup(ID2), - promiseInstallAllFiles([do_get_addon("test_bootstrap1_1"), do_get_addon("test_bootstrap2_1")])]) + Promise.all([promisePref("bootstraptest2.active_version"), + promiseInstall([do_get_addon("test_bootstrap1_1"), do_get_addon("test_bootstrap2_1")])]) .then(function test_24_pref() { do_print("test 24 got prefs"); - BootstrapMonitor.checkAddonInstalled(ID1, "1.0"); - BootstrapMonitor.checkAddonStarted(ID1, "1.0"); - BootstrapMonitor.checkAddonInstalled(ID2, "1.0"); - BootstrapMonitor.checkAddonStarted(ID2, "1.0"); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 1); + do_check_eq(getInstalledVersion2(), 1); + do_check_eq(getActiveVersion2(), 1); + + resetPrefs(); restartManager(); - BootstrapMonitor.checkAddonInstalled(ID1, "1.0"); - BootstrapMonitor.checkAddonStarted(ID1, "1.0"); - BootstrapMonitor.checkAddonInstalled(ID2, "1.0"); - BootstrapMonitor.checkAddonStarted(ID2, "1.0"); + do_check_eq(getInstalledVersion(), -1); + do_check_eq(getActiveVersion(), 1); + do_check_eq(getInstalledVersion2(), -1); + do_check_eq(getActiveVersion2(), 1); shutdownManager(); - BootstrapMonitor.checkAddonInstalled(ID1, "1.0"); - BootstrapMonitor.checkAddonNotStarted(ID1); - BootstrapMonitor.checkAddonInstalled(ID2, "1.0"); - BootstrapMonitor.checkAddonNotStarted(ID2); + do_check_eq(getInstalledVersion(), -1); + do_check_eq(getActiveVersion(), 0); + do_check_eq(getInstalledVersion2(), -1); + do_check_eq(getActiveVersion2(), 0); - // Break the preference + // Break the preferece let bootstrappedAddons = JSON.parse(Services.prefs.getCharPref("extensions.bootstrappedAddons")); - bootstrappedAddons[ID1].descriptor += "foo"; + bootstrappedAddons["bootstrap1@tests.mozilla.org"].descriptor += "foo"; Services.prefs.setCharPref("extensions.bootstrappedAddons", JSON.stringify(bootstrappedAddons)); startupManager(false); - BootstrapMonitor.checkAddonInstalled(ID1, "1.0"); - BootstrapMonitor.checkAddonStarted(ID1, "1.0"); - BootstrapMonitor.checkAddonInstalled(ID2, "1.0"); - BootstrapMonitor.checkAddonStarted(ID2, "1.0"); + do_check_eq(getInstalledVersion(), -1); + do_check_eq(getActiveVersion(), 1); + do_check_eq(getInstalledVersion2(), -1); + do_check_eq(getActiveVersion2(), 1); run_test_25(); }); @@ -1242,36 +1278,34 @@ function run_test_24() { // Tests that updating from a bootstrappable add-on to a normal add-on calls // the uninstall method function run_test_25() { - BootstrapMonitor.promiseAddonStartup(ID1).then(function test_25_after_pref() { + waitForPref("bootstraptest.startup_reason", function test_25_after_pref() { do_print("test 25 pref change detected"); - BootstrapMonitor.checkAddonInstalled(ID1, "1.0"); - BootstrapMonitor.checkAddonStarted(ID1, "1.0"); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 1); installAllFiles([do_get_addon("test_bootstrap1_4")], function() { // Needs a restart to complete this so the old version stays running - BootstrapMonitor.checkAddonInstalled(ID1, "1.0"); - BootstrapMonitor.checkAddonStarted(ID1, "1.0"); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 1); - AddonManager.getAddonByID(ID1, callback_soon(function(b1) { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) { do_check_neq(b1, null); do_check_eq(b1.version, "1.0"); do_check_true(b1.isActive); - do_check_false(b1.isSystem); do_check_true(hasFlag(b1.pendingOperations, AddonManager.PENDING_UPGRADE)); restartManager(); - BootstrapMonitor.checkAddonNotInstalled(ID1); + do_check_eq(getInstalledVersion(), 0); do_check_eq(getUninstallReason(), ADDON_UPGRADE); do_check_eq(getUninstallNewVersion(), 4); - BootstrapMonitor.checkAddonNotStarted(ID1); + do_check_eq(getActiveVersion(), 0); - AddonManager.getAddonByID(ID1, function(b1_2) { - do_check_neq(b1_2, null); - do_check_eq(b1_2.version, "4.0"); - do_check_true(b1_2.isActive); - do_check_false(b1_2.isSystem); - do_check_eq(b1_2.pendingOperations, AddonManager.PENDING_NONE); + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "4.0"); + do_check_true(b1.isActive); + do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE); do_check_bootstrappedPref(run_test_26); }); @@ -1288,29 +1322,27 @@ function run_test_25() { function run_test_26() { installAllFiles([do_get_addon("test_bootstrap1_1")], function() { // Needs a restart to complete this - BootstrapMonitor.checkAddonNotInstalled(ID1); - BootstrapMonitor.checkAddonNotStarted(ID1); + do_check_eq(getInstalledVersion(), 0); + do_check_eq(getActiveVersion(), 0); - AddonManager.getAddonByID(ID1, callback_soon(function(b1) { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) { do_check_neq(b1, null); do_check_eq(b1.version, "4.0"); do_check_true(b1.isActive); - do_check_false(b1.isSystem); do_check_true(hasFlag(b1.pendingOperations, AddonManager.PENDING_UPGRADE)); restartManager(); - BootstrapMonitor.checkAddonInstalled(ID1, "1.0"); + do_check_eq(getInstalledVersion(), 1); do_check_eq(getInstallReason(), ADDON_DOWNGRADE); do_check_eq(getInstallOldVersion(), 4); - BootstrapMonitor.checkAddonStarted(ID1, "1.0"); + do_check_eq(getActiveVersion(), 1); - AddonManager.getAddonByID(ID1, function(b1_2) { - do_check_neq(b1_2, null); - do_check_eq(b1_2.version, "1.0"); - do_check_true(b1_2.isActive); - do_check_false(b1_2.isSystem); - do_check_eq(b1_2.pendingOperations, AddonManager.PENDING_NONE); + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "1.0"); + do_check_true(b1.isActive); + do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE); do_check_bootstrappedPref(run_test_27); }); @@ -1321,38 +1353,38 @@ function run_test_26() { // Tests that updating from a bootstrappable add-on to a normal add-on while // disabled calls the uninstall method function run_test_27() { - AddonManager.getAddonByID(ID1, function(b1) { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { do_check_neq(b1, null); b1.userDisabled = true; do_check_eq(b1.version, "1.0"); do_check_false(b1.isActive); do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE); - BootstrapMonitor.checkAddonInstalled(ID1, "1.0"); - BootstrapMonitor.checkAddonNotStarted(ID1); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 0); installAllFiles([do_get_addon("test_bootstrap1_4")], function() { // Updating disabled things happens immediately - BootstrapMonitor.checkAddonNotInstalled(ID1); + do_check_eq(getInstalledVersion(), 0); do_check_eq(getUninstallReason(), ADDON_UPGRADE); do_check_eq(getUninstallNewVersion(), 4); - BootstrapMonitor.checkAddonNotStarted(ID1); + do_check_eq(getActiveVersion(), 0); - AddonManager.getAddonByID(ID1, callback_soon(function(b1_2) { - do_check_neq(b1_2, null); - do_check_eq(b1_2.version, "4.0"); - do_check_false(b1_2.isActive); - do_check_eq(b1_2.pendingOperations, AddonManager.PENDING_NONE); + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "4.0"); + do_check_false(b1.isActive); + do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE); restartManager(); - BootstrapMonitor.checkAddonNotInstalled(ID1); - BootstrapMonitor.checkAddonNotStarted(ID1); + do_check_eq(getInstalledVersion(), 0); + do_check_eq(getActiveVersion(), 0); - AddonManager.getAddonByID(ID1, function(b1_3) { - do_check_neq(b1_3, null); - do_check_eq(b1_3.version, "4.0"); - do_check_false(b1_3.isActive); - do_check_eq(b1_3.pendingOperations, AddonManager.PENDING_NONE); + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "4.0"); + do_check_false(b1.isActive); + do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE); do_check_bootstrappedPref(run_test_28); }); @@ -1367,12 +1399,12 @@ function run_test_28() { installAllFiles([do_get_addon("test_bootstrap1_1")], function() { do_execute_soon(function bootstrap_disabled_downgrade_check() { // Doesn't need a restart to complete this - BootstrapMonitor.checkAddonInstalled(ID1, "1.0"); + do_check_eq(getInstalledVersion(), 1); do_check_eq(getInstallReason(), ADDON_DOWNGRADE); do_check_eq(getInstallOldVersion(), 4); - BootstrapMonitor.checkAddonNotStarted(ID1); + do_check_eq(getActiveVersion(), 0); - AddonManager.getAddonByID(ID1, callback_soon(function(b1) { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) { do_check_neq(b1, null); do_check_eq(b1.version, "1.0"); do_check_false(b1.isActive); @@ -1381,19 +1413,18 @@ function run_test_28() { restartManager(); - BootstrapMonitor.checkAddonInstalled(ID1, "1.0"); - BootstrapMonitor.checkAddonNotStarted(ID1); - - AddonManager.getAddonByID(ID1, function(b1_2) { - do_check_neq(b1_2, null); - do_check_true(b1_2.userDisabled); - b1_2.userDisabled = false; - do_check_eq(b1_2.version, "1.0"); - do_check_true(b1_2.isActive); - do_check_false(b1_2.isSystem); - do_check_eq(b1_2.pendingOperations, AddonManager.PENDING_NONE); - BootstrapMonitor.checkAddonInstalled(ID1, "1.0"); - BootstrapMonitor.checkAddonStarted(ID1, "1.0"); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 0); + + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + do_check_neq(b1, null); + do_check_true(b1.userDisabled); + b1.userDisabled = false; + do_check_eq(b1.version, "1.0"); + do_check_true(b1.isActive); + do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 1); do_check_bootstrappedPref(do_test_finished); }); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bootstrap_const.js b/toolkit/mozapps/extensions/test/xpcshell/test_bootstrap_const.js index 101d49510..fb02b59be 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bootstrap_const.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bootstrap_const.js @@ -1,17 +1,17 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1"); -startupManager(); - -add_task(function*() { - let sawInstall = false; - Services.obs.addObserver(function() { - sawInstall = true; - }, "addon-install", false); - - yield promiseInstallAllFiles([do_get_addon("test_bootstrap_const")]); - - ok(sawInstall); -}); +/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1");
+startupManager();
+
+add_task(function*() {
+ let sawInstall = false;
+ Services.obs.addObserver(function() {
+ sawInstall = true;
+ }, "addon-install", false);
+
+ yield promiseInstallAllFiles([do_get_addon("test_bootstrap_const")]);
+
+ ok(sawInstall);
+});
\ No newline at end of file diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bootstrap_globals.js b/toolkit/mozapps/extensions/test/xpcshell/test_bootstrap_globals.js index 29b538d21..2243a21a2 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bootstrap_globals.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bootstrap_globals.js @@ -23,7 +23,7 @@ function run_test() { }, "bootstrap-request-globals", false); Services.obs.addObserver(function({ wrappedJSObject: seenGlobals }) { - for (let [name, ] of EXPECTED_GLOBALS) + for (let [name,] of EXPECTED_GLOBALS) do_check_true(seenGlobals.has(name)); sawGlobals = true; diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug1180901.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug1180901.js deleted file mode 100644 index c13531dff..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug1180901.js +++ /dev/null @@ -1,35 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -function run_test() { - createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); - startupManager(); - run_next_test(); -} - -add_task(function* () { - let profileDir = OS.Constants.Path.profileDir; - let trashDir = OS.Path.join(profileDir, "extensions", "trash"); - let testFile = OS.Path.join(trashDir, "test.txt"); - - yield OS.File.makeDir(trashDir, { - from: profileDir, - ignoreExisting: true - }); - - let trashDirExists = yield OS.File.exists(trashDir); - ok(trashDirExists, "trash directory should have been created"); - - let file = yield OS.File.open(testFile, {create: true}, {winShare: 0}); - let fileExists = yield OS.File.exists(testFile); - ok(fileExists, "test.txt should have been created in " + trashDir); - - yield promiseInstallAllFiles([do_get_addon("test_install1")]); - yield promiseRestartManager(); - fileExists = yield OS.File.exists(testFile); - ok(fileExists, "test.txt still exists"); - yield file.close(); - yield OS.File.removeDir(OS.Path.join(OS.Constants.Path.profileDir, "extensions")); - yield promiseShutdownManager(); -}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug1180901_2.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug1180901_2.js deleted file mode 100644 index 8e9f30ef2..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug1180901_2.js +++ /dev/null @@ -1,60 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -function run_test() { - createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); - startupManager(); - run_next_test(); -} - -add_task(function* () { - let profileDir = OS.Constants.Path.profileDir; - let trashDir = OS.Path.join(profileDir, "extensions", "trash"); - let testFile = OS.Path.join(trashDir, "test.txt"); - - yield OS.File.makeDir(trashDir, { - from: profileDir, - ignoreExisting: true - }); - - let trashDirExists = yield OS.File.exists(trashDir); - ok(trashDirExists, "trash directory should have been created"); - - let file = yield OS.File.open(testFile, {create: true}, {winShare: 0}); - let fileExists = yield OS.File.exists(testFile); - ok(fileExists, "test.txt should have been created in " + trashDir); - - let promiseInstallStatus = new Promise((resolve, reject) => { - let listener = { - onInstallFailed: function() { - AddonManager.removeInstallListener(listener); - reject("extension installation should not have failed"); - }, - onInstallEnded: function() { - AddonManager.removeInstallListener(listener); - ok(true, "extension installation should not have failed"); - resolve(); - } - }; - - AddonManager.addInstallListener(listener); - }); - - yield promiseInstallAllFiles([do_get_addon("test_bootstrap1_1")]); - - // The testFile should still exist at this point because we have not - // yet closed the file handle and as a result, Windows cannot remove it. - fileExists = yield OS.File.exists(testFile); - ok(fileExists, "test.txt should still exist"); - - // Wait for the AddonManager to tell us if the installation of the extension - // succeeded or not. - yield promiseInstallStatus; - - // Cleanup - yield promiseShutdownManager(); - yield file.close(); - yield OS.File.remove(testFile); - yield OS.File.removeDir(trashDir); -}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug299716.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug299716.js index 66656abe6..5de941f32 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug299716.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug299716.js @@ -105,8 +105,9 @@ function do_check_item(aItem, aVersion, aAddonsEntry) { do_throw("Addon " + aAddonsEntry.id + " wasn't detected"); if (aItem.version != aVersion) do_throw("Addon " + aAddonsEntry.id + " was version " + aItem.version + " instead of " + aVersion); - } else if (aItem != null) { - do_throw("Addon " + aAddonsEntry.id + " was detected"); + } else { + if (aItem != null) + do_throw("Addon " + aAddonsEntry.id + " was detected"); } } @@ -148,7 +149,7 @@ function run_test() { startupManager(); dump("\n\n*** INSTALLING NEW ITEMS\n\n"); - installAllFiles(ADDONS.map(a => do_get_addon(a.addon)), run_test_pt2, + installAllFiles([do_get_addon(a.addon) for each (a in ADDONS)], run_test_pt2, true); } @@ -160,7 +161,7 @@ function run_test_pt2() { dump("\n\n*** RESTARTING EXTENSION MANAGER\n\n"); restartManager(); - AddonManager.getAddonsByIDs(ADDONS.map(a => a.id), function(items) { + AddonManager.getAddonsByIDs([a.id for each (a in ADDONS)], function(items) { dump("\n\n*** REQUESTING UPDATE\n\n"); // checkListener will call run_test_pt3(). next_test = run_test_pt3; @@ -185,7 +186,7 @@ function run_test_pt2() { function run_test_pt3() { // Install the new items. dump("\n\n*** UPDATING ITEMS\n\n"); - completeAllInstalls(ADDONS.filter(a => a.newInstall).map(a => a.newInstall), + completeAllInstalls([a.newInstall for each(a in ADDONS) if (a.newInstall)], run_test_pt4); } @@ -197,7 +198,7 @@ function run_test_pt4() { restartManager(); dump("\n\n*** FINAL CHECKS\n\n"); - AddonManager.getAddonsByIDs(ADDONS.map(a => a.id), function(items) { + AddonManager.getAddonsByIDs([a.id for each (a in ADDONS)], function(items) { for (var i = 0; i < ADDONS.length; i++) { var item = items[i]; do_check_item(item, "0.2", ADDONS[i]); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug324121.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug324121.js index 84b6c6189..b88c07b23 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug324121.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug324121.js @@ -136,11 +136,11 @@ function run_test() { startupManager(); - installAllFiles(ADDONS.map(a => do_get_addon(a.addon)), function() { + installAllFiles([do_get_addon(a.addon) for each (a in ADDONS)], function() { restartManager(); - AddonManager.getAddonByID(ADDONS[0].id, callback_soon(function(firstAddon) { - do_check_true(firstAddon); - firstAddon.userDisabled = true; + AddonManager.getAddonByID(ADDONS[0].id, callback_soon(function(addon) { + do_check_true(!(!addon)); + addon.userDisabled = true; restartManager(); AddonManager.getAddonsByTypes(["extension"], function(installedItems) { diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug335238.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug335238.js index 251bdca70..e691bb570 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug335238.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug335238.js @@ -9,11 +9,10 @@ const PREF_SELECTED_LOCALE = "general.useragent.locale"; // Disables security checking our updates which haven't been signed Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); -var Ci = Components.interfaces; -var Cu = Components.utils; +const Ci = Components.interfaces; +const Cu = Components.utils; Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://testing-common/MockRegistrar.jsm"); // This is the data we expect to see sent as part of the update url. var EXPECTED = [ @@ -106,7 +105,16 @@ var BlocklistService = { } }; -MockRegistrar.register("@mozilla.org/extensions/blocklist;1", BlocklistService); +var BlocklistServiceFactory = { + createInstance: function (outer, iid) { + if (outer != null) + throw Components.results.NS_ERROR_NO_AGGREGATION; + return BlocklistService.QueryInterface(iid); + } +}; +var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); +registrar.registerFactory(Components.ID("{61189e7a-6b1b-44b8-ac81-f180a6105085}"), "BlocklistService", + "@mozilla.org/extensions/blocklist;1", BlocklistServiceFactory); var server; @@ -154,7 +162,7 @@ function run_test() { Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "en-US"); startupManager(); - installAllFiles(ADDONS.map(a => do_get_addon(a.addon)), function() { + installAllFiles([do_get_addon(a.addon) for each (a in ADDONS)], function() { restartManager(); AddonManager.getAddonByID(ADDONS[1].id, callback_soon(function(addon) { @@ -162,7 +170,7 @@ function run_test() { addon.userDisabled = true; restartManager(); - AddonManager.getAddonsByIDs(ADDONS.map(a => a.id), function(installedItems) { + AddonManager.getAddonsByIDs([a.id for each (a in ADDONS)], function(installedItems) { installedItems.forEach(function(item) { updateListener.pendingCount++; item.findUpdates(updateListener, AddonManager.UPDATE_WHEN_USER_REQUESTED); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug371495.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug371495.js index 43656f126..3a80c1945 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug371495.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug371495.js @@ -23,10 +23,10 @@ function run_test() do_check_eq(addon.name, "Test theme"); restartManager(); - AddonManager.getAddonByID(ID, callback_soon(function(addon2) { - do_check_neq(addon2, null); - do_check_eq(addon2.optionsURL, null); - do_check_eq(addon2.aboutURL, null); + AddonManager.getAddonByID(ID, callback_soon(function(addon) { + do_check_neq(addon, null); + do_check_eq(addon.optionsURL, null); + do_check_eq(addon.aboutURL, null); do_execute_soon(do_test_finished); })); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug393285.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug393285.js index ebc330cdd..90cf29753 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug393285.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug393285.js @@ -3,12 +3,11 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -var {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; +const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; const URI_EXTENSION_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul"; Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://testing-common/MockRegistrar.jsm"); var testserver = new HttpServer(); testserver.start(-1); gPort = testserver.identity.primaryPort; @@ -19,7 +18,7 @@ mapFile("/data/test_bug393285.xml", testserver); const profileDir = gProfD.clone(); profileDir.append("extensions"); -var addonIDs = ["test_bug393285_1@tests.mozilla.org", +let addonIDs = ["test_bug393285_1@tests.mozilla.org", "test_bug393285_2@tests.mozilla.org", "test_bug393285_3a@tests.mozilla.org", "test_bug393285_3b@tests.mozilla.org", @@ -37,18 +36,18 @@ var addonIDs = ["test_bug393285_1@tests.mozilla.org", // A window watcher to deal with the blocklist UI dialog. var WindowWatcher = { - openWindow: function(parent, url, name, features, args) { + openWindow: function(parent, url, name, features, arguments) { // Should be called to list the newly blocklisted items do_check_eq(url, URI_EXTENSION_BLOCKLIST_DIALOG); // Simulate auto-disabling any softblocks - var list = args.wrappedJSObject.list; + var list = arguments.wrappedJSObject.list; list.forEach(function(aItem) { if (!aItem.blocked) aItem.disable = true; }); - // run the code after the blocklist is closed + //run the code after the blocklist is closed Services.obs.notifyObservers(null, "addon-blocklist-closed", null); }, @@ -62,7 +61,19 @@ var WindowWatcher = { } }; -MockRegistrar.register("@mozilla.org/embedcomp/window-watcher;1", WindowWatcher); +var WindowWatcherFactory = { + createInstance: function createInstance(outer, iid) { + if (outer != null) + throw Cr.NS_ERROR_NO_AGGREGATION; + return WindowWatcher.QueryInterface(iid); + } +}; + +var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); +registrar.registerFactory(Components.ID("{1dfeb90a-2193-45d5-9cb8-864928b2af55}"), + "Fake Window Watcher", + "@mozilla.org/embedcomp/window-watcher;1", + WindowWatcherFactory); function load_blocklist(aFile, aCallback) { @@ -258,7 +269,7 @@ function run_test() { startupManager(); AddonManager.getAddonsByIDs(addonIDs, function(addons) { - for (let addon of addons) { + for (addon of addons) { do_check_eq(addon.blocklistState, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); } run_test_1(); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug406118.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug406118.js index e22ab87c9..724b48dd5 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug406118.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug406118.js @@ -3,17 +3,16 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -var addonIDs = ["test_bug393285_1@tests.mozilla.org", +let addonIDs = ["test_bug393285_1@tests.mozilla.org", "test_bug393285_2@tests.mozilla.org", "test_bug393285_3a@tests.mozilla.org", "test_bug393285_4@tests.mozilla.org"]; -var {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; +const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; const URI_EXTENSION_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul"; Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://testing-common/MockRegistrar.jsm"); var testserver = new HttpServer(); testserver.start(-1); gPort = testserver.identity.primaryPort; @@ -26,18 +25,18 @@ profileDir.append("extensions"); // A window watcher to deal with the blocklist UI dialog. var WindowWatcher = { - openWindow: function(parent, url, name, features, args) { + openWindow: function(parent, url, name, features, arguments) { // Should be called to list the newly blocklisted items do_check_eq(url, URI_EXTENSION_BLOCKLIST_DIALOG); // Simulate auto-disabling any softblocks - var list = args.wrappedJSObject.list; + var list = arguments.wrappedJSObject.list; list.forEach(function(aItem) { if (!aItem.blocked) aItem.disable = true; }); - // run the code after the blocklist is closed + //run the code after the blocklist is closed Services.obs.notifyObservers(null, "addon-blocklist-closed", null); }, @@ -51,7 +50,20 @@ var WindowWatcher = { } }; -MockRegistrar.register("@mozilla.org/embedcomp/window-watcher;1", WindowWatcher); +var WindowWatcherFactory = { + createInstance: function createInstance(outer, iid) { + if (outer != null) + throw Cr.NS_ERROR_NO_AGGREGATION; + return WindowWatcher.QueryInterface(iid); + } +}; + +var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); +registrar.registerFactory(Components.ID("{1dfeb90a-2193-45d5-9cb8-864928b2af55}"), + "Fake Window Watcher", + "@mozilla.org/embedcomp/window-watcher;1", + WindowWatcherFactory); + function load_blocklist(aFile, aCallback) { Services.obs.addObserver(function() { @@ -125,7 +137,7 @@ function run_test() { startupManager(); AddonManager.getAddonsByIDs(addonIDs, function(addons) { - for (let addon of addons) { + for (addon of addons) { do_check_eq(addon.blocklistState, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); } run_test_1(); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug430120.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug430120.js index e13f36a7c..74080dba9 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug430120.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug430120.js @@ -14,7 +14,6 @@ const CATEGORY_UPDATE_TIMER = "update-timer"; // Get the HTTP server. Components.utils.import("resource://testing-common/httpd.js"); -Components.utils.import("resource://testing-common/MockRegistrar.jsm"); var testserver; var gOSVersion; var gBlocklist; @@ -50,7 +49,16 @@ var timerService = { } }; -MockRegistrar.register("@mozilla.org/updates/timer-manager;1", timerService); +var TimerServiceFactory = { + createInstance: function (outer, iid) { + if (outer != null) + throw Components.results.NS_ERROR_NO_AGGREGATION; + return timerService.QueryInterface(iid); + } +}; +var registrar = Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar); +registrar.registerFactory(Components.ID("{61189e7a-6b1b-44b8-ac81-f180a6105085}"), "TimerService", + "@mozilla.org/updates/timer-manager;1", TimerServiceFactory); function failHandler(metadata, response) { do_throw("Should not have attempted to retrieve the blocklist when it is disabled"); @@ -67,8 +75,7 @@ function pathHandler(metadata, response) { ABI += "-u-" + macutils.architecturesInBinary; } do_check_eq(metadata.queryString, - "xpcshell@tests.mozilla.org&1&XPCShell&1&" + - gAppInfo.appBuildID + "&" + + "xpcshell@tests.mozilla.org&1&XPCShell&1&2007010101&" + "XPCShell_" + ABI + "&locale&updatechannel&" + gOSVersion + "&1.9&distribution&distribution-version"); gBlocklist.observe(null, "quit-application", ""); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug449027.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug449027.js index 1512a7f92..623a6a14a 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug449027.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug449027.js @@ -4,11 +4,10 @@ */ const URI_EXTENSION_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul"; -var Ci = Components.interfaces; -var Cu = Components.utils; +const Ci = Components.interfaces; +const Cu = Components.utils; Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://testing-common/MockRegistrar.jsm"); var ADDONS = [{ id: "test_bug449027_1@tests.mozilla.org", @@ -250,15 +249,23 @@ var PluginHost = { } } +var PluginHostFactory = { + createInstance: function (outer, iid) { + if (outer != null) + throw Components.results.NS_ERROR_NO_AGGREGATION; + return PluginHost.QueryInterface(iid); + } +}; + // Don't need the full interface, attempts to call other methods will just // throw which is just fine var WindowWatcher = { - openWindow: function(parent, url, name, features, args) { + openWindow: function(parent, url, name, features, arguments) { // Should be called to list the newly blocklisted items do_check_eq(url, URI_EXTENSION_BLOCKLIST_DIALOG); do_check_neq(gCallback, null); - args = args.wrappedJSObject; + var args = arguments.wrappedJSObject; gNewBlocks = []; var list = args.list; @@ -278,8 +285,20 @@ var WindowWatcher = { } } -MockRegistrar.register("@mozilla.org/plugin/host;1", PluginHost); -MockRegistrar.register("@mozilla.org/embedcomp/window-watcher;1", WindowWatcher); +var WindowWatcherFactory = { + createInstance: function createInstance(outer, iid) { + if (outer != null) + throw Components.results.NS_ERROR_NO_AGGREGATION; + return WindowWatcher.QueryInterface(iid); + } +}; +var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); +registrar.registerFactory(Components.ID("{721c3e73-969e-474b-a6dc-059fd288c428}"), + "Fake Plugin Host", + "@mozilla.org/plugin/host;1", PluginHostFactory); +registrar.registerFactory(Components.ID("{1dfeb90a-2193-45d5-9cb8-864928b2af55}"), + "Fake Window Watcher", + "@mozilla.org/embedcomp/window-watcher;1", WindowWatcherFactory); function create_addon(addon) { var installrdf = "<?xml version=\"1.0\"?>\n" + @@ -303,10 +322,10 @@ function create_addon(addon) { target.append("extensions"); target.append(addon.id); target.append("install.rdf"); - target.create(target.NORMAL_FILE_TYPE, 0o644); + target.create(target.NORMAL_FILE_TYPE, 0644); var stream = Components.classes["@mozilla.org/network/file-output-stream;1"] .createInstance(Ci.nsIFileOutputStream); - stream.init(target, 0x04 | 0x08 | 0x20, 0o664, 0); // write, create, truncate + stream.init(target, 0x04 | 0x08 | 0x20, 0664, 0); // write, create, truncate stream.write(installrdf, installrdf.length); stream.close(); } @@ -317,7 +336,7 @@ function create_addon(addon) { * the newly blocked items compared to the previous test. */ function check_state(test, lastTest, callback) { - AddonManager.getAddonsByIDs(ADDONS.map(a => a.id), function(addons) { + AddonManager.getAddonsByIDs([a.id for each (a in ADDONS)], function(addons) { for (var i = 0; i < ADDONS.length; i++) { var blocked = addons[i].blocklistState == Ci.nsIBlocklistService.STATE_BLOCKED; if (blocked != ADDONS[i][test]) @@ -386,13 +405,13 @@ function run_test() { function check_test_pt1() { dump("Checking pt 1\n"); - AddonManager.getAddonsByIDs(ADDONS.map(a => a.id), function(addons) { + AddonManager.getAddonsByIDs([a.id for each (a in ADDONS)], function(addons) { for (var i = 0; i < ADDONS.length; i++) { if (!addons[i]) do_throw("Addon " + (i + 1) + " did not get installed correctly"); } - do_execute_soon(function checkstate1() { check_state("start", null, run_test_pt2); }); + do_execute_soon(function checkstate1() {check_state("start", null, run_test_pt2);}); }); } diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug455906.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug455906.js index 06e29b376..9a41e827c 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug455906.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug455906.js @@ -3,15 +3,14 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -var Cc = Components.classes; -var Ci = Components.interfaces; -var Cu = Components.utils; -var Cr = Components.results; +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cu = Components.utils; +const Cr = Components.results; const URI_EXTENSION_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul"; Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://testing-common/MockRegistrar.jsm"); var gTestserver = new HttpServer(); gTestserver.start(-1); gPort = gTestserver.identity.primaryPort; @@ -128,11 +127,19 @@ var PluginHost = { if (iid.equals(Ci.nsIPluginHost) || iid.equals(Ci.nsISupports)) return this; - + throw Components.results.NS_ERROR_NO_INTERFACE; } } +var PluginHostFactory = { + createInstance: function (outer, iid) { + if (outer != null) + throw Components.results.NS_ERROR_NO_AGGREGATION; + return PluginHost.QueryInterface(iid); + } +}; + // Don't need the full interface, attempts to call other methods will just // throw which is just fine var WindowWatcher = { @@ -145,7 +152,7 @@ var WindowWatcher = { gNotificationCheck(args); } - // run the code after the blocklist is closed + //run the code after the blocklist is closed Services.obs.notifyObservers(null, "addon-blocklist-closed", null); // Call the next test after the blocklist has finished up @@ -161,8 +168,20 @@ var WindowWatcher = { } } -MockRegistrar.register("@mozilla.org/plugin/host;1", PluginHost); -MockRegistrar.register("@mozilla.org/embedcomp/window-watcher;1", WindowWatcher); +var WindowWatcherFactory = { + createInstance: function createInstance(outer, iid) { + if (outer != null) + throw Components.results.NS_ERROR_NO_AGGREGATION; + return WindowWatcher.QueryInterface(iid); + } +}; +var registrar = Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar); +registrar.registerFactory(Components.ID("{721c3e73-969e-474b-a6dc-059fd288c428}"), + "Fake Plugin Host", + "@mozilla.org/plugin/host;1", PluginHostFactory); +registrar.registerFactory(Components.ID("{1dfeb90a-2193-45d5-9cb8-864928b2af55}"), + "Fake Window Watcher", + "@mozilla.org/embedcomp/window-watcher;1", WindowWatcherFactory); function create_addon(addon) { var installrdf = "<?xml version=\"1.0\"?>\n" + @@ -211,7 +230,7 @@ function check_plugin_state(plugin) { return plugin.disabled + "," + plugin.blocklisted; } -function create_blocklistURL(blockID) { +function create_blocklistURL(blockID){ let url = Services.urlFormatter.formatURLPref(PREF_BLOCKLIST_ITEM_URL); url = url.replace(/%blockID%/g, blockID); return url; @@ -239,7 +258,7 @@ function run_test() { // Before every main test this is the state the add-ons are meant to be in function check_initial_state(callback) { - AddonManager.getAddonsByIDs(ADDONS.map(a => a.id), function(addons) { + AddonManager.getAddonsByIDs([a.id for each (a in ADDONS)], function(addons) { do_check_eq(check_addon_state(addons[0]), "true,false,false"); do_check_eq(check_addon_state(addons[1]), "false,false,false"); do_check_eq(check_addon_state(addons[2]), "false,false,false"); @@ -247,7 +266,7 @@ function check_initial_state(callback) { do_check_eq(check_addon_state(addons[4]), "false,false,false"); do_check_eq(check_addon_state(addons[5]), "false,false,true"); do_check_eq(check_addon_state(addons[6]), "false,false,true"); - + do_check_eq(check_plugin_state(PLUGINS[0]), "true,false"); do_check_eq(check_plugin_state(PLUGINS[1]), "false,false"); do_check_eq(check_plugin_state(PLUGINS[2]), "false,false"); @@ -263,27 +282,27 @@ function check_initial_state(callback) { function check_test_pt1() { dump("Checking pt 1\n"); - AddonManager.getAddonsByIDs(ADDONS.map(a => a.id), callback_soon(function(addons) { + AddonManager.getAddonsByIDs([a.id for each (a in ADDONS)], callback_soon(function(addons) { for (var i = 0; i < ADDONS.length; i++) { if (!addons[i]) do_throw("Addon " + (i + 1) + " did not get installed correctly"); } - + do_check_eq(check_addon_state(addons[0]), "false,false,false"); do_check_eq(check_addon_state(addons[1]), "false,false,false"); do_check_eq(check_addon_state(addons[2]), "false,false,false"); - + // Warn add-ons should be soft disabled automatically do_check_eq(check_addon_state(addons[3]), "true,true,false"); do_check_eq(check_addon_state(addons[4]), "true,true,false"); - + // Blocked and incompatible should be app disabled only do_check_eq(check_addon_state(addons[5]), "false,false,true"); do_check_eq(check_addon_state(addons[6]), "false,false,true"); - + // We've overridden the plugin host so we cannot tell what that would have // initialised the plugins as - + // Put the add-ons into the base state addons[0].userDisabled = true; addons[4].userDisabled = false; @@ -335,14 +354,13 @@ function check_test_pt2() { restartManager(); dump("Checking results pt 2\n"); - AddonManager.getAddonsByIDs(ADDONS.map(a => a.id), callback_soon(function(addons) { + AddonManager.getAddonsByIDs([a.id for each (a in ADDONS)], callback_soon(function(addons) { // Should have disabled this add-on as requested do_check_eq(check_addon_state(addons[2]), "true,true,false"); do_check_eq(check_plugin_state(PLUGINS[2]), "true,false"); // The blocked add-on should have changed to soft disabled do_check_eq(check_addon_state(addons[5]), "true,true,false"); - do_check_eq(check_addon_state(addons[6]), "true,true,true"); do_check_eq(check_plugin_state(PLUGINS[5]), "true,false"); // These should have been unchanged @@ -350,6 +368,7 @@ function check_test_pt2() { do_check_eq(check_addon_state(addons[1]), "false,false,false"); do_check_eq(check_addon_state(addons[3]), "true,true,false"); do_check_eq(check_addon_state(addons[4]), "false,false,false"); + do_check_eq(check_addon_state(addons[6]), "false,false,true"); do_check_eq(check_plugin_state(PLUGINS[0]), "true,false"); do_check_eq(check_plugin_state(PLUGINS[1]), "false,false"); do_check_eq(check_plugin_state(PLUGINS[3]), "true,false"); @@ -421,7 +440,7 @@ function check_test_pt3() { let blocklist = Cc["@mozilla.org/extensions/blocklist;1"]. getService(Ci.nsIBlocklistService); - AddonManager.getAddonsByIDs(ADDONS.map(a => a.id), function(addons) { + AddonManager.getAddonsByIDs([a.id for each (a in ADDONS)], function(addons) { // All should have gained the blocklist state, user disabled as previously do_check_eq(check_addon_state(addons[0]), "true,false,true"); do_check_eq(check_addon_state(addons[1]), "false,false,true"); @@ -437,11 +456,11 @@ function check_test_pt3() { do_check_eq(check_addon_state(addons[3]), "false,false,true"); // Check blockIDs are correct - do_check_eq(blocklist.getAddonBlocklistURL(addons[0]), create_blocklistURL(addons[0].id)); - do_check_eq(blocklist.getAddonBlocklistURL(addons[1]), create_blocklistURL(addons[1].id)); - do_check_eq(blocklist.getAddonBlocklistURL(addons[2]), create_blocklistURL(addons[2].id)); - do_check_eq(blocklist.getAddonBlocklistURL(addons[3]), create_blocklistURL(addons[3].id)); - do_check_eq(blocklist.getAddonBlocklistURL(addons[4]), create_blocklistURL(addons[4].id)); + do_check_eq(blocklist.getAddonBlocklistURL(addons[0]),create_blocklistURL(addons[0].id)); + do_check_eq(blocklist.getAddonBlocklistURL(addons[1]),create_blocklistURL(addons[1].id)); + do_check_eq(blocklist.getAddonBlocklistURL(addons[2]),create_blocklistURL(addons[2].id)); + do_check_eq(blocklist.getAddonBlocklistURL(addons[3]),create_blocklistURL(addons[3].id)); + do_check_eq(blocklist.getAddonBlocklistURL(addons[4]),create_blocklistURL(addons[4].id)); // All plugins have the same blockID on the test do_check_eq(blocklist.getPluginBlocklistURL(PLUGINS[0]), create_blocklistURL('test_bug455906_plugin')); @@ -488,7 +507,7 @@ function check_test_pt4() { restartManager(); dump("Checking results pt 4\n"); - AddonManager.getAddonsByIDs(ADDONS.map(a => a.id), function(addons) { + AddonManager.getAddonsByIDs([a.id for each (a in ADDONS)], function(addons) { // This should have become unblocked do_check_eq(check_addon_state(addons[5]), "false,false,false"); do_check_eq(check_plugin_state(PLUGINS[5]), "false,false"); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug465190.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug465190.js index e8e2353e2..fc8c772c9 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug465190.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug465190.js @@ -5,7 +5,7 @@ var installLocation = gProfD.clone(); installLocation.append("baddir"); -installLocation.create(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0o664); +installLocation.create(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0664); var dirProvider2 = { getFile: function(prop, persistent) { diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug468528.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug468528.js index 01c976a17..5e8702eb7 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug468528.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug468528.js @@ -48,7 +48,7 @@ function run_test() { // not blocked - won't match due to invalid regexp do_check_true(blocklist.getPluginBlocklistState(PLUGINS[1], "1", "1.9") == nsIBLS.STATE_NOT_BLOCKED); - + // blocked - the invalid regexp for the previous item shouldn't affect this one do_check_true(blocklist.getPluginBlocklistState(PLUGINS[2], "1", "1.9") == nsIBLS.STATE_BLOCKED); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_1.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_1.js index 920c3731a..c456506ce 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_1.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_1.js @@ -28,7 +28,7 @@ function run_test() { startupManager(); - installAllFiles(ADDONS.map(a => do_get_addon(a)), function() { + installAllFiles([do_get_addon(a) for each (a in ADDONS)], function() { restartManager(); AddonManager.getAddonsByIDs(["bug470377_1@tests.mozilla.org", diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_1_strictcompat.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_1_strictcompat.js index 6fa11eb39..1e542dff8 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_1_strictcompat.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_1_strictcompat.js @@ -28,7 +28,7 @@ function run_test() { startupManager(); - installAllFiles(ADDONS.map(a => do_get_addon(a)), function() { + installAllFiles([do_get_addon(a) for each (a in ADDONS)], function() { restartManager(); AddonManager.getAddonsByIDs(["bug470377_1@tests.mozilla.org", diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_2.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_2.js index 0c912ceff..15e8d54c4 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_2.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_2.js @@ -28,7 +28,7 @@ function run_test() { startupManager(); AddonManager.checkCompatibility = false; - installAllFiles(ADDONS.map(a => do_get_addon(a)), function() { + installAllFiles([do_get_addon(a) for each (a in ADDONS)], function() { restartManager(); AddonManager.getAddonsByIDs(["bug470377_1@tests.mozilla.org", diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_3.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_3.js index 0d1d30f3b..fcac471ee 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_3.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_3.js @@ -13,31 +13,31 @@ function run_test() { var dest = gProfD.clone(); dest.append("extensions"); dest.append("bug470377_1@tests.mozilla.org"); - dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0o755); + dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0755); var source = do_get_file("data/test_bug470377/install_1.rdf"); source.copyTo(dest, "install.rdf"); dest = gProfD.clone(); dest.append("extensions"); dest.append("bug470377_2@tests.mozilla.org"); - dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0o755); + dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0755); source = do_get_file("data/test_bug470377/install_2.rdf"); source.copyTo(dest, "install.rdf"); dest = gProfD.clone(); dest.append("extensions"); dest.append("bug470377_3@tests.mozilla.org"); - dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0o755); + dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0755); source = do_get_file("data/test_bug470377/install_3.rdf"); source.copyTo(dest, "install.rdf"); dest = gProfD.clone(); dest.append("extensions"); dest.append("bug470377_4@tests.mozilla.org"); - dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0o755); + dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0755); source = do_get_file("data/test_bug470377/install_4.rdf"); source.copyTo(dest, "install.rdf"); dest = gProfD.clone(); dest.append("extensions"); dest.append("bug470377_5@tests.mozilla.org"); - dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0o755); + dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0755); source = do_get_file("data/test_bug470377/install_5.rdf"); source.copyTo(dest, "install.rdf"); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_3_strictcompat.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_3_strictcompat.js index 100ea99d7..7a3347320 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_3_strictcompat.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_3_strictcompat.js @@ -12,31 +12,31 @@ function run_test() { var dest = gProfD.clone(); dest.append("extensions"); dest.append("bug470377_1@tests.mozilla.org"); - dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0o755); + dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0755); var source = do_get_file("data/test_bug470377/install_1.rdf"); source.copyTo(dest, "install.rdf"); dest = gProfD.clone(); dest.append("extensions"); dest.append("bug470377_2@tests.mozilla.org"); - dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0o755); + dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0755); source = do_get_file("data/test_bug470377/install_2.rdf"); source.copyTo(dest, "install.rdf"); dest = gProfD.clone(); dest.append("extensions"); dest.append("bug470377_3@tests.mozilla.org"); - dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0o755); + dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0755); source = do_get_file("data/test_bug470377/install_3.rdf"); source.copyTo(dest, "install.rdf"); dest = gProfD.clone(); dest.append("extensions"); dest.append("bug470377_4@tests.mozilla.org"); - dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0o755); + dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0755); source = do_get_file("data/test_bug470377/install_4.rdf"); source.copyTo(dest, "install.rdf"); dest = gProfD.clone(); dest.append("extensions"); dest.append("bug470377_5@tests.mozilla.org"); - dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0o755); + dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0755); source = do_get_file("data/test_bug470377/install_5.rdf"); source.copyTo(dest, "install.rdf"); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_4.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_4.js index c51c38b0c..701cbe448 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_4.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_4.js @@ -12,27 +12,27 @@ function run_test() { profileDir.append("extensions"); var dest = profileDir.clone(); dest.append("bug470377_1@tests.mozilla.org"); - dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0o755); + dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0755); var source = do_get_file("data/test_bug470377/install_1.rdf"); source.copyTo(dest, "install.rdf"); dest = profileDir.clone(); dest.append("bug470377_2@tests.mozilla.org"); - dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0o755); + dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0755); source = do_get_file("data/test_bug470377/install_2.rdf"); source.copyTo(dest, "install.rdf"); dest = profileDir.clone(); dest.append("bug470377_3@tests.mozilla.org"); - dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0o755); + dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0755); source = do_get_file("data/test_bug470377/install_3.rdf"); source.copyTo(dest, "install.rdf"); dest = profileDir.clone(); dest.append("bug470377_4@tests.mozilla.org"); - dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0o755); + dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0755); source = do_get_file("data/test_bug470377/install_4.rdf"); source.copyTo(dest, "install.rdf"); dest = profileDir.clone(); dest.append("bug470377_5@tests.mozilla.org"); - dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0o755); + dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0755); source = do_get_file("data/test_bug470377/install_5.rdf"); source.copyTo(dest, "install.rdf"); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug514327_1.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug514327_1.js index 46b65ffff..c684e0ca2 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug514327_1.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug514327_1.js @@ -2,8 +2,8 @@ * 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/. */ -var Cc = Components.classes; -var Ci = Components.interfaces; +const Cc = Components.classes; +const Ci = Components.interfaces; const nsIBLS = Ci.nsIBlocklistService; diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug514327_2.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug514327_2.js index 261739da4..a8c369f1b 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug514327_2.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug514327_2.js @@ -2,8 +2,8 @@ * 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/. */ -var Cc = Components.classes; -var Ci = Components.interfaces; +const Cc = Components.classes; +const Ci = Components.interfaces; const nsIBLS = Ci.nsIBlocklistService; @@ -26,16 +26,17 @@ function run_test() { var blocklist = Cc["@mozilla.org/extensions/blocklist;1"].getService(nsIBLS); var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch); - prefs.setBoolPref("plugin.load_flash_only", false); - var plugin = get_test_plugintag(); if (!plugin) do_throw("Plugin tag not found"); - // run the code after the blocklist is closed + //run the code after the blocklist is closed Services.obs.notifyObservers(null, "addon-blocklist-closed", null); do_execute_soon(function() { // should be marked as outdated by the blocklist do_check_true(blocklist.getPluginBlocklistState(plugin, "1", "1.9") == nsIBLS.STATE_OUTDATED); + + // should indicate that a warning should be shown + do_check_true(prefs.getBoolPref("plugins.update.notifyUser")); }); } diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug514327_3.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug514327_3.js index 634361991..1267a8772 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug514327_3.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug514327_3.js @@ -2,13 +2,12 @@ * 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/. */ -var Cc = Components.classes; -var Ci = Components.interfaces; -var Cu = Components.utils; -var Cr = Components.results; +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cu = Components.utils; +const Cr = Components.results; Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://testing-common/MockRegistrar.jsm"); const nsIBLS = Ci.nsIBlocklistService; const URI_EXTENSION_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul"; @@ -52,21 +51,29 @@ var PluginHost = { if (iid.equals(Ci.nsIPluginHost) || iid.equals(Ci.nsISupports)) return this; - + throw Components.results.NS_ERROR_NO_INTERFACE; } } +var PluginHostFactory = { + createInstance: function (outer, iid) { + if (outer != null) + throw Components.results.NS_ERROR_NO_AGGREGATION; + return PluginHost.QueryInterface(iid); + } +}; + // Don't need the full interface, attempts to call other methods will just // throw which is just fine var WindowWatcher = { - openWindow: function(parent, url, name, features, args) { + openWindow: function(parent, url, name, features, arguments) { // Should be called to list the newly blocklisted items do_check_eq(url, URI_EXTENSION_BLOCKLIST_DIALOG); // Should only include one item - do_check_eq(args.wrappedJSObject.list.length, 1); + do_check_eq(arguments.wrappedJSObject.list.length, 1); // And that item should be the blocked plugin, not the outdated one - var item = args.wrappedJSObject.list[0]; + var item = arguments.wrappedJSObject.list[0]; do_check_true(item.item instanceof Ci.nsIPluginTag); do_check_neq(item.name, "test_bug514327_outdated"); @@ -83,8 +90,21 @@ var WindowWatcher = { } } -MockRegistrar.register("@mozilla.org/plugin/host;1", PluginHost); -MockRegistrar.register("@mozilla.org/embedcomp/window-watcher;1", WindowWatcher); +var WindowWatcherFactory = { + createInstance: function createInstance(outer, iid) { + if (outer != null) + throw Components.results.NS_ERROR_NO_AGGREGATION; + return WindowWatcher.QueryInterface(iid); + } +}; + +var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); +registrar.registerFactory(Components.ID("{721c3e73-969e-474b-a6dc-059fd288c428}"), + "Fake Plugin Host", + "@mozilla.org/plugin/host;1", PluginHostFactory); +registrar.registerFactory(Components.ID("{1dfeb90a-2193-45d5-9cb8-864928b2af55}"), + "Fake Window Watcher", + "@mozilla.org/embedcomp/window-watcher;1", WindowWatcherFactory); function do_update_blocklist(aDatafile, aNextPart) { @@ -106,13 +126,13 @@ function run_test() { // initialize the blocklist with no entries copyBlocklistToProfile(do_get_file("data/test_bug514327_3_empty.xml")); - + gPrefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch); gBlocklist = Cc["@mozilla.org/extensions/blocklist;1"].getService(nsIBLS); - + // should NOT be marked as outdated by the blocklist do_check_true(gBlocklist.getPluginBlocklistState(PLUGINS[0], "1", "1.9") == nsIBLS.STATE_NOT_BLOCKED); - + do_test_pending(); // update blocklist with data that marks the plugin as outdated @@ -122,7 +142,12 @@ function run_test() { function test_part_1() { // plugin should now be marked as outdated do_check_true(gBlocklist.getPluginBlocklistState(PLUGINS[0], "1", "1.9") == nsIBLS.STATE_OUTDATED); - + // and the notifyUser pref should be set to true + do_check_true(gPrefs.getBoolPref("plugins.update.notifyUser")); + + // preternd the user has been notified, reset the pref + gPrefs.setBoolPref("plugins.update.notifyUser", false); + // update blocklist with data that marks the plugin as outdated do_update_blocklist("test_bug514327_3_outdated_2.xml", test_part_2); } @@ -130,6 +155,8 @@ function test_part_1() { function test_part_2() { // plugin should still be marked as outdated do_check_true(gBlocklist.getPluginBlocklistState(PLUGINS[0], "1", "1.9") == nsIBLS.STATE_OUTDATED); + // and the notifyUser pref should NOT be set to true, as the plugin was already outdated + do_check_false(gPrefs.getBoolPref("plugins.update.notifyUser")); finish(); } diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug541420.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug541420.js index b7af5453f..1f70b42d5 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug541420.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug541420.js @@ -29,7 +29,7 @@ function run_test() { // only tests if the file is an application so it is better to just check the // raw permission bits if (!("nsIWindowsRegKey" in Components.interfaces)) - do_check_true((file.permissions & 0o100) == 0o100); + do_check_true((file.permissions & 0100) == 0100); do_execute_soon(do_test_finished); }); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug542391.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug542391.js index aa1bbd53f..ceb472f98 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug542391.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug542391.js @@ -9,12 +9,12 @@ const PREF_EM_SHOW_MISMATCH_UI = "extensions.showMismatchUI"; // The test extension uses an insecure update url. Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); -var Cc = Components.classes; -var Ci = Components.interfaces; -var Cu = Components.utils; -var Cr = Components.results; +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cu = Components.utils; +const Cr = Components.results; -Cu.import("resource://testing-common/MockRegistrar.jsm"); +Cu.import("resource://testing-common/httpd.js"); var testserver; const profileDir = gProfD.clone(); @@ -26,14 +26,14 @@ var gCheckUpdates = false; // This will be called to show the compatibility update dialog. var WindowWatcher = { expected: false, - args: null, + arguments: null, openWindow: function(parent, url, name, features, args) { do_check_true(Services.startup.interrupted); do_check_eq(url, URI_EXTENSION_UPDATE_DIALOG); do_check_true(this.expected); this.expected = false; - this.args = args.QueryInterface(AM_Ci.nsIVariant); + this.arguments = args.QueryInterface(AM_Ci.nsIVariant); var updated = !gCheckUpdates; if (gCheckUpdates) { @@ -77,7 +77,18 @@ var WindowWatcher = { } } -MockRegistrar.register("@mozilla.org/embedcomp/window-watcher;1", WindowWatcher); +var WindowWatcherFactory = { + createInstance: function createInstance(outer, iid) { + if (outer != null) + throw Components.results.NS_ERROR_NO_AGGREGATION; + return WindowWatcher.QueryInterface(iid); + } +}; + +var registrar = Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar); +registrar.registerFactory(Components.ID("{1dfeb90a-2193-45d5-9cb8-864928b2af55}"), + "Fake Window Watcher", + "@mozilla.org/embedcomp/window-watcher;1", WindowWatcherFactory); function check_state_v1([a1, a2, a3, a4, a5, a6]) { do_check_neq(a1, null); @@ -295,9 +306,10 @@ add_task(function* init() { }, profileDir); // Create and configure the HTTP server. - testserver = createHttpServer(4444); + testserver = new HttpServer(); testserver.registerDirectory("/data/", do_get_file("data")); testserver.registerDirectory("/addons/", do_get_file("addons")); + testserver.start(4444); startupManager(); @@ -385,9 +397,9 @@ add_task(function* run_test_1() { "override1x2-1x3@tests.mozilla.org"]); check_state_v3(addons); - do_check_eq(WindowWatcher.args.length, 2); - do_check_true(WindowWatcher.args.indexOf("upgradeable1x2-3@tests.mozilla.org") >= 0); - do_check_true(WindowWatcher.args.indexOf("override1x2-1x3@tests.mozilla.org") >= 0); + do_check_eq(WindowWatcher.arguments.length, 2); + do_check_true(WindowWatcher.arguments.indexOf("upgradeable1x2-3@tests.mozilla.org") >= 0); + do_check_true(WindowWatcher.arguments.indexOf("override1x2-1x3@tests.mozilla.org") >= 0); }); // Downgrade to version 2 which will remove appDisable from two add-ons @@ -438,8 +450,8 @@ add_task(function* run_test_5() { "override1x2-1x3@tests.mozilla.org"]); check_state_v3_2(addons); - do_check_eq(WindowWatcher.args.length, 1); - do_check_true(WindowWatcher.args.indexOf("upgradeable1x2-3@tests.mozilla.org") >= 0); + do_check_eq(WindowWatcher.arguments.length, 1); + do_check_true(WindowWatcher.arguments.indexOf("upgradeable1x2-3@tests.mozilla.org") >= 0); }); // Downgrade to version 1 which will appEnable all the add-ons @@ -462,3 +474,13 @@ add_task(function* run_test_6() { "override1x2-1x3@tests.mozilla.org"]); check_state_v1_2(addons); }); + +add_task(function* cleanup() { + return new Promise((resolve, reject) => { + testserver.stop(resolve); + }); +}); + +function run_test() { + run_next_test(); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug559800.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug559800.js index 866ad3ad7..41057cd76 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug559800.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug559800.js @@ -10,7 +10,7 @@ profileDir.append("extensions"); // getting an unused port Components.utils.import("resource://testing-common/httpd.js"); -var gServer = new HttpServer(); +let gServer = new HttpServer(); gServer.start(-1); gPort = gServer.identity.primaryPort; diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug563256.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug563256.js index 497e66526..2437cf748 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug563256.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug563256.js @@ -39,7 +39,7 @@ function run_test() { }, profileDir); startupManager(); - + do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "classic/1.0"); AddonManager.getAddonsByIDs(["default@tests.mozilla.org", @@ -236,22 +236,22 @@ function check_test_2() { do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "classic/1.0"); AddonManager.getAddonsByIDs(["default@tests.mozilla.org", - "alternate@tests.mozilla.org"], function([d2, a2]) { - do_check_neq(d2, null); - do_check_false(d2.userDisabled); - do_check_false(d2.appDisabled); - do_check_true(d2.isActive); - do_check_true(isThemeInAddonsList(profileDir, d2.id)); - do_check_false(hasFlag(d2.permissions, AddonManager.PERM_CAN_DISABLE)); - do_check_false(hasFlag(d2.permissions, AddonManager.PERM_CAN_ENABLE)); - - do_check_neq(a2, null); - do_check_true(a2.userDisabled); - do_check_false(a2.appDisabled); - do_check_false(a2.isActive); - do_check_false(isThemeInAddonsList(profileDir, a2.id)); - do_check_false(hasFlag(a2.permissions, AddonManager.PERM_CAN_DISABLE)); - do_check_true(hasFlag(a2.permissions, AddonManager.PERM_CAN_ENABLE)); + "alternate@tests.mozilla.org"], function([d, a]) { + do_check_neq(d, null); + do_check_false(d.userDisabled); + do_check_false(d.appDisabled); + do_check_true(d.isActive); + do_check_true(isThemeInAddonsList(profileDir, d.id)); + do_check_false(hasFlag(d.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_false(hasFlag(d.permissions, AddonManager.PERM_CAN_ENABLE)); + + do_check_neq(a, null); + do_check_true(a.userDisabled); + do_check_false(a.appDisabled); + do_check_false(a.isActive); + do_check_false(isThemeInAddonsList(profileDir, a.id)); + do_check_false(hasFlag(a.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_true(hasFlag(a.permissions, AddonManager.PERM_CAN_ENABLE)); end_test(); }); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug564030.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug564030.js index 92ba3d68f..b5ac157c7 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug564030.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug564030.js @@ -49,13 +49,13 @@ function run_test() { restartManager(); - AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a2) { - do_check_neq(a2, null); - do_check_eq(a2.version, "2.0"); - do_check_false(a2.userDisabled); - do_check_false(a2.appDisabled); - do_check_true(a2.isActive); - do_check_true(isExtensionInAddonsList(profileDir, a2.id)); + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a) { + do_check_neq(a, null); + do_check_eq(a.version, "2.0"); + do_check_false(a.userDisabled); + do_check_false(a.appDisabled); + do_check_true(a.isActive); + do_check_true(isExtensionInAddonsList(profileDir, a.id)); do_execute_soon(do_test_finished); }); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug570173.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug570173.js index 2c87d8c79..70de3b426 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug570173.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug570173.js @@ -7,6 +7,7 @@ // The test extension uses an insecure update url. Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); +Components.utils.import("resource://testing-common/httpd.js"); var testserver; const profileDir = gProfD.clone(); profileDir.append("extensions"); @@ -15,47 +16,65 @@ function run_test() { createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); // Create and configure the HTTP server. - testserver = createHttpServer(); + testserver = new HttpServer(); testserver.registerDirectory("/data/", do_get_file("data")); testserver.registerDirectory("/addons/", do_get_file("addons")); + testserver.start(-1); gPort = testserver.identity.primaryPort; - run_next_test(); + writeInstallRDFForExtension({ + id: "addon1@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_missing.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 1", + }, profileDir); + + startupManager(); + + do_test_pending(); + run_test_1(); +} + +function end_test() { + testserver.stop(do_test_finished); } // Verify that an update check returns the correct errors. -add_task(function* () { - for (let manifestType of ["rdf", "json"]) { - writeInstallRDFForExtension({ - id: "addon1@tests.mozilla.org", - version: "1.0", - updateURL: `http://localhost:${gPort}/data/test_missing.${manifestType}`, - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "1", - maxVersion: "1" - }], - name: "Test Addon 1", - bootstrap: "true", - }, profileDir); - - yield promiseRestartManager(); - - let addon = yield promiseAddonByID("addon1@tests.mozilla.org"); - - ok(addon); - ok(addon.updateURL.endsWith(manifestType)); - equal(addon.version, "1.0"); - - // We're expecting an error, so resolve when the promise is rejected. - let update = yield promiseFindAddonUpdates(addon, AddonManager.UPDATE_WHEN_USER_REQUESTED) - .catch(Promise.resolve); - - ok(!update.compatibilityUpdate, "not expecting a compatibility update"); - ok(!update.updateAvailable, "not expecting a compatibility update"); - - equal(update.error, AddonManager.UPDATE_STATUS_DOWNLOAD_ERROR); - - addon.uninstall(); - } -}); +function run_test_1() { + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.version, "1.0"); + + let sawCompat = false; + let sawUpdate = false; + a1.findUpdates({ + onNoCompatibilityUpdateAvailable: function(addon) { + sawCompat = true; + }, + + onCompatibilityUpdateAvailable: function(addon) { + do_throw("Should not have seen a compatibility update"); + }, + + onNoUpdateAvailable: function(addon) { + sawUpdate = true; + }, + + onUpdateAvailable: function(addon, install) { + do_throw("Should not have seen an update"); + }, + + onUpdateFinished: function(addon, error) { + do_check_true(sawCompat); + do_check_true(sawUpdate); + do_check_eq(error, AddonManager.UPDATE_STATUS_DOWNLOAD_ERROR); + end_test(); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug576735.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug576735.js index df64e159d..007e82706 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug576735.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug576735.js @@ -53,12 +53,12 @@ function run_test() { AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", "addon2@tests.mozilla.org"], - function([a1_2, a2_2]) { + function([a1, a2]) { // Addon1 should no longer be installed - do_check_eq(a1_2, null); + do_check_eq(a1, null); // Addon2 should have been detected - do_check_neq(a2_2, null); + do_check_neq(a2, null); do_execute_soon(do_test_finished); }); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug587088.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug587088.js index 8d9857e7f..01de80634 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug587088.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug587088.js @@ -96,22 +96,22 @@ function run_test_1() { restartManager(); - AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1_2) { - check_addon_upgrading(a1_2); + AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) { + check_addon_upgrading(a1); restartManager(); - AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1_3) { - check_addon_upgrading(a1_3); + AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) { + check_addon_upgrading(a1); fstream.close(); restartManager(); - AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1_4) { - check_addon(a1_4, "2.0"); + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + check_addon(a1, "2.0"); - a1_4.uninstall(); + a1.uninstall(); do_execute_soon(run_test_2); }); })); @@ -146,20 +146,20 @@ function run_test_2() { restartManager(); - AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1_2) { - check_addon_uninstalling(a1_2, true); + AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) { + check_addon_uninstalling(a1, true); restartManager(); - AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1_3) { - check_addon_uninstalling(a1_3, true); + AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) { + check_addon_uninstalling(a1, true); fstream.close(); restartManager(); - AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1_4) { - do_check_eq(a1_4, null); + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_eq(a1, null); var dir = profileDir.clone(); dir.append(do_get_expected_addon_name("addon1@tests.mozilla.org")); do_check_false(dir.exists()); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug594058.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug594058.js index 858579815..9bbda59a8 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug594058.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug594058.js @@ -10,9 +10,7 @@ Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); // Allow the mismatch UI to show Services.prefs.setBoolPref("extensions.showMismatchUI", true); -Components.utils.import("resource://testing-common/MockRegistrar.jsm"); - -var Ci = Components.interfaces; +const Ci = Components.interfaces; const extDir = gProfD.clone(); extDir.append("extensions"); @@ -20,7 +18,7 @@ var gCachePurged = false; // Override the window watcher var WindowWatcher = { - openWindow: function(parent, url, name, features, args) { + openWindow: function(parent, url, name, features, arguments) { do_check_false(gCachePurged); }, @@ -33,7 +31,18 @@ var WindowWatcher = { } } -MockRegistrar.register("@mozilla.org/embedcomp/window-watcher;1", WindowWatcher); +var WindowWatcherFactory = { + createInstance: function createInstance(outer, iid) { + if (outer != null) + throw Components.results.NS_ERROR_NO_AGGREGATION; + return WindowWatcher.QueryInterface(iid); + } +}; + +var registrar = Components.manager.QueryInterface(AM_Ci.nsIComponentRegistrar); +registrar.registerFactory(Components.ID("{1dfeb90a-2193-45d5-9cb8-864928b2af55}"), + "Fake Window Watcher", + "@mozilla.org/embedcomp/window-watcher;1", WindowWatcherFactory); /** * Start the test by installing extensions. @@ -84,5 +93,5 @@ function run_test() { do_check_false(gCachePurged); do_test_finished(); - }); + }); } diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug596343.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug596343.js new file mode 100644 index 000000000..96e95c5ad --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug596343.js @@ -0,0 +1,86 @@ +/* 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/. + */ + +const URI_EXTENSION_SELECT_DIALOG = "chrome://mozapps/content/extensions/selectAddons.xul"; +const URI_EXTENSION_UPDATE_DIALOG = "chrome://mozapps/content/extensions/update.xul"; +const PREF_EM_SHOW_MISMATCH_UI = "extensions.showMismatchUI"; +const PREF_SHOWN_SELECTION_UI = "extensions.shownSelectionUI"; + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +var gExpectedURL = null; + +// This will be called to show the any update dialog. +var WindowWatcher = { + openWindow: function(parent, url, name, features, arguments) { + do_check_eq(url, gExpectedURL); + gExpectedURL = null; + }, + + QueryInterface: function(iid) { + if (iid.equals(AM_Ci.nsIWindowWatcher) + || iid.equals(AM_Ci.nsISupports)) + return this; + + throw Components.results.NS_ERROR_NO_INTERFACE; + } +} + +var WindowWatcherFactory = { + createInstance: function createInstance(outer, iid) { + if (outer != null) + throw Components.results.NS_ERROR_NO_AGGREGATION; + return WindowWatcher.QueryInterface(iid); + } +}; + +var registrar = Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar); +registrar.registerFactory(Components.ID("{1dfeb90a-2193-45d5-9cb8-864928b2af55}"), + "Fake Window Watcher", + "@mozilla.org/embedcomp/window-watcher;1", WindowWatcherFactory); + +// Tests that the selection UI is displayed when upgrading an existing profile +function run_test() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1"); + + Services.prefs.setBoolPref(PREF_EM_SHOW_MISMATCH_UI, true); + + var dest = writeInstallRDFForExtension({ + id: "addon1@tests.mozilla.org", + version: "1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "2" + }], + name: "Test Addon 1", + }, profileDir); + + // For a new profile it should disable showing the selection UI in the future + // without showing the selection UI + gExpectedURL = URI_EXTENSION_SELECT_DIALOG; + startupManager(); + + do_check_true(Services.prefs.getBoolPref(PREF_SHOWN_SELECTION_UI)); + do_check_eq(gExpectedURL, URI_EXTENSION_SELECT_DIALOG); + + // Reset the 'already shown' pref so that we can test that the first upgrade of + // an existing profile shows the selection UI + Services.prefs.clearUserPref(PREF_SHOWN_SELECTION_UI); + + restartManager("2"); + + do_check_true(Services.prefs.getBoolPref(PREF_SHOWN_SELECTION_UI)); + do_check_eq(gExpectedURL, null); + + // Once we've seen the selection UI once, future upgrades will show the update dialog + // but only if this upgrade disabled an add-on + gExpectedURL = URI_EXTENSION_UPDATE_DIALOG; + + restartManager("3"); + + do_check_eq(gExpectedURL, null); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug596607.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug596607.js index bdcf93a1f..3e655dc87 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug596607.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug596607.js @@ -38,18 +38,11 @@ const addon2Dir = writeInstallRDFForExtension(addon2, gProfD, "addon2"); const addon3Dir = gProfD.clone(); addon3Dir.append("addon3@tests.mozilla.org"); -let registry; - function run_test() { // This test only works where there is a registry. if (!("nsIWindowsRegKey" in AM_Ci)) return; - registry = new MockRegistry(); - do_register_cleanup(() => { - registry.shutdown(); - }); - do_test_pending(); run_test_1(); @@ -57,15 +50,15 @@ function run_test() { // Tests whether starting a fresh profile with a bad entry works function run_test_1() { - registry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE, - "SOFTWARE\\Mozilla\\XPCShell\\Extensions", - "addon1@tests.mozilla.org", addon1Dir.path); - registry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, - "SOFTWARE\\Mozilla\\XPCShell\\Extensions", - "addon2@tests.mozilla.org", addon2Dir.path); - registry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, - "SOFTWARE\\Mozilla\\XPCShell\\Extensions", - "addon3@tests.mozilla.org", addon3Dir.path); + MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE, + "SOFTWARE\\Mozilla\\XPCShell\\Extensions", + "addon1@tests.mozilla.org", addon1Dir.path); + MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, + "SOFTWARE\\Mozilla\\XPCShell\\Extensions", + "addon2@tests.mozilla.org", addon2Dir.path); + MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, + "SOFTWARE\\Mozilla\\XPCShell\\Extensions", + "addon3@tests.mozilla.org", addon3Dir.path); startupManager(); @@ -92,9 +85,9 @@ function run_test_1() { function run_test_2() { shutdownManager(); - registry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, - "SOFTWARE\\Mozilla\\XPCShell\\Extensions", - "addon3@tests.mozilla.org", addon3Dir.path); + MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, + "SOFTWARE\\Mozilla\\XPCShell\\Extensions", + "addon3@tests.mozilla.org", addon3Dir.path); startupManager(false); @@ -121,9 +114,9 @@ function run_test_2() { function run_test_3() { shutdownManager(); - registry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, - "SOFTWARE\\Mozilla\\XPCShell\\Extensions", - "addon3@tests.mozilla.org", null); + MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, + "SOFTWARE\\Mozilla\\XPCShell\\Extensions", + "addon3@tests.mozilla.org", null); startupManager(false); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug619730.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug619730.js index 1c21385e0..761daf4eb 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug619730.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug619730.js @@ -3,9 +3,9 @@ */ // Tests whether -var Cc = Components.classes; -var Ci = Components.interfaces; -var Cu = Components.utils; +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cu = Components.utils; Cu.import("resource://testing-common/httpd.js"); @@ -20,7 +20,7 @@ function load_blocklist(file, aCallback) { do_execute_soon(aCallback); }, "blocklist-updated", false); - + Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" + gPort + "/data/" + file); var blocklist = Cc["@mozilla.org/extensions/blocklist;1"]. diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug655254.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug655254.js index 449c59065..45274b734 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug655254.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug655254.js @@ -84,11 +84,11 @@ function run_test_1() { onUpdateFinished: function() { restartManager(); - AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1_2) { - do_check_neq(a1_2, null); - do_check_false(a1_2.appDisabled); - do_check_true(a1_2.isActive); - do_check_true(isExtensionInAddonsList(userDir, a1_2.id)); + AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) { + do_check_neq(a1, null); + do_check_false(a1.appDisabled); + do_check_true(a1.isActive); + do_check_true(isExtensionInAddonsList(userDir, a1.id)); shutdownManager(); @@ -103,16 +103,16 @@ function run_test_1() { startupManager(false); AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", - "addon2@tests.mozilla.org"], function([a1_3, a2_3]) { - do_check_neq(a1_3, null); - do_check_false(a1_3.appDisabled); - do_check_true(a1_3.isActive); - do_check_true(isExtensionInAddonsList(userDir, a1_3.id)); - - do_check_neq(a2_3, null); - do_check_false(a2_3.appDisabled); - do_check_true(a2_3.isActive); - do_check_false(isExtensionInAddonsList(userDir, a2_3.id)); + "addon2@tests.mozilla.org"], function([a1, a2]) { + do_check_neq(a1, null); + do_check_false(a1.appDisabled); + do_check_true(a1.isActive); + do_check_true(isExtensionInAddonsList(userDir, a1.id)); + + do_check_neq(a2, null); + do_check_false(a2.appDisabled); + do_check_true(a2.isActive); + do_check_false(isExtensionInAddonsList(userDir, a2.id)); do_check_eq(Services.prefs.getIntPref("bootstraptest.active_version"), 1); do_execute_soon(run_test_2); @@ -123,7 +123,7 @@ function run_test_1() { }); } -// Set up the profile +//Set up the profile function run_test_2() { AddonManager.getAddonByID("addon2@tests.mozilla.org", callback_soon(function(a2) { do_check_neq(a2, null); @@ -146,16 +146,16 @@ function run_test_2() { startupManager(false); AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", - "addon2@tests.mozilla.org"], function([a1_2, a2_2]) { - do_check_neq(a1_2, null); - do_check_false(a1_2.appDisabled); - do_check_true(a1_2.isActive); - do_check_true(isExtensionInAddonsList(userDir, a1_2.id)); - - do_check_neq(a2_2, null); - do_check_true(a2_2.userDisabled); - do_check_false(a2_2.isActive); - do_check_false(isExtensionInAddonsList(userDir, a2_2.id)); + "addon2@tests.mozilla.org"], function([a1, a2]) { + do_check_neq(a1, null); + do_check_false(a1.appDisabled); + do_check_true(a1.isActive); + do_check_true(isExtensionInAddonsList(userDir, a1.id)); + + do_check_neq(a2, null); + do_check_true(a2.userDisabled); + do_check_false(a2.isActive); + do_check_false(isExtensionInAddonsList(userDir, a2.id)); do_check_eq(Services.prefs.getIntPref("bootstraptest.active_version"), 0); end_test(); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug659772.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug659772.js index 6e98a69a4..c6e8ab4e2 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug659772.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug659772.js @@ -148,45 +148,45 @@ function run_test_1() { "addon2@tests.mozilla.org", "addon3@tests.mozilla.org", "addon4@tests.mozilla.org"], - function([a1_2, a2_2, a3_2, a4_2]) { - do_check_neq(a1_2, null); - do_check_eq(a1_2.version, "2.0"); - do_check_false(a1_2.appDisabled); - do_check_false(a1_2.userDisabled); - do_check_true(a1_2.isActive); + function([a1, a2, a3, a4]) { + do_check_neq(a1, null); + do_check_eq(a1.version, "2.0"); + do_check_false(a1.appDisabled); + do_check_false(a1.userDisabled); + do_check_true(a1.isActive); do_check_true(isExtensionInAddonsList(profileDir, addon1.id)); - do_check_neq(a2_2, null); - do_check_eq(a2_2.version, "2.0"); - do_check_false(a2_2.appDisabled); - do_check_false(a2_2.userDisabled); - do_check_true(a2_2.isActive); + do_check_neq(a2, null); + do_check_eq(a2.version, "2.0"); + do_check_false(a2.appDisabled); + do_check_false(a2.userDisabled); + do_check_true(a2.isActive); do_check_true(isExtensionInAddonsList(profileDir, addon2.id)); // Should stay enabled because we migrate the compat info from // the previous version of the DB - do_check_neq(a3_2, null); - do_check_eq(a3_2.version, "2.0"); - todo_check_false(a3_2.appDisabled); // XXX unresolved issue - do_check_false(a3_2.userDisabled); - todo_check_true(a3_2.isActive); // XXX same + do_check_neq(a3, null); + do_check_eq(a3.version, "2.0"); + todo_check_false(a3.appDisabled); // XXX unresolved issue + do_check_false(a3.userDisabled); + todo_check_true(a3.isActive); // XXX same todo_check_true(isExtensionInAddonsList(profileDir, addon3.id)); // XXX same - do_check_neq(a4_2, null); - do_check_eq(a4_2.version, "2.0"); - do_check_true(a4_2.appDisabled); - do_check_false(a4_2.userDisabled); - do_check_false(a4_2.isActive); + do_check_neq(a4, null); + do_check_eq(a4.version, "2.0"); + do_check_true(a4.appDisabled); + do_check_false(a4.userDisabled); + do_check_false(a4.isActive); do_check_false(isExtensionInAddonsList(profileDir, addon4.id)); // Check that install and uninstall haven't been called on the bootstrapped addon do_check_false(Services.prefs.prefHasUserValue("bootstraptest.install_reason")); do_check_false(Services.prefs.prefHasUserValue("bootstraptest.uninstall_reason")); - a1_2.uninstall(); - a2_2.uninstall(); - a3_2.uninstall(); - a4_2.uninstall(); + a1.uninstall(); + a2.uninstall(); + a3.uninstall(); + a4.uninstall(); do_execute_soon(run_test_2); }); }); @@ -290,51 +290,51 @@ function run_test_2() { "addon2@tests.mozilla.org", "addon3@tests.mozilla.org", "addon4@tests.mozilla.org"], - callback_soon(function([a1_2, a2_2, a3_2, a4_2]) { - do_check_neq(a1_2, null); - do_check_eq(a1_2.version, "2.0"); - do_check_true(a1_2.appDisabled); - do_check_false(a1_2.userDisabled); - do_check_false(a1_2.isActive); + callback_soon(function([a1, a2, a3, a4]) { + do_check_neq(a1, null); + do_check_eq(a1.version, "2.0"); + do_check_true(a1.appDisabled); + do_check_false(a1.userDisabled); + do_check_false(a1.isActive); do_check_false(isExtensionInAddonsList(profileDir, addon1.id)); - do_check_neq(a2_2, null); - do_check_eq(a2_2.version, "2.0"); - do_check_false(a2_2.appDisabled); - do_check_false(a2_2.userDisabled); - do_check_true(a2_2.isActive); + do_check_neq(a2, null); + do_check_eq(a2.version, "2.0"); + do_check_false(a2.appDisabled); + do_check_false(a2.userDisabled); + do_check_true(a2.isActive); do_check_true(isExtensionInAddonsList(profileDir, addon2.id)); // Should become appDisabled because we migrate the compat info from // the previous version of the DB - do_check_neq(a3_2, null); - do_check_eq(a3_2.version, "2.0"); - todo_check_true(a3_2.appDisabled); - do_check_false(a3_2.userDisabled); - todo_check_false(a3_2.isActive); + do_check_neq(a3, null); + do_check_eq(a3.version, "2.0"); + todo_check_true(a3.appDisabled); + do_check_false(a3.userDisabled); + todo_check_false(a3.isActive); todo_check_false(isExtensionInAddonsList(profileDir, addon3.id)); - do_check_neq(a4_2, null); - do_check_eq(a4_2.version, "2.0"); - do_check_false(a4_2.appDisabled); - do_check_false(a4_2.userDisabled); - do_check_true(a4_2.isActive); + do_check_neq(a4, null); + do_check_eq(a4.version, "2.0"); + do_check_false(a4.appDisabled); + do_check_false(a4.userDisabled); + do_check_true(a4.isActive); do_check_true(isExtensionInAddonsList(profileDir, addon4.id)); // Check that install and uninstall haven't been called on the bootstrapped addon do_check_false(Services.prefs.prefHasUserValue("bootstraptest.install_reason")); do_check_false(Services.prefs.prefHasUserValue("bootstraptest.uninstall_reason")); - a1_2.uninstall(); - a2_2.uninstall(); - a3_2.uninstall(); - a4_2.uninstall(); + a1.uninstall(); + a2.uninstall(); + a3.uninstall(); + a4.uninstall(); restartManager(); shutdownManager(); do_test_finished(); })); - } + }; }); } diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug675371.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug675371.js index 6f2a5e7cd..579335d8a 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug675371.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug675371.js @@ -35,7 +35,7 @@ function check_test() { do_check_true(addon.isActive); // Tests that chrome.manifest is registered when the addon is installed. - var target = { }; + var target = { active: false }; Services.scriptloader.loadSubScript("chrome://bug675371/content/test.js", target); do_check_true(target.active); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug757663.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug757663.js index 54cee0839..648c7acc3 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug757663.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug757663.js @@ -1,112 +1,112 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -// This test verifies that removing a listener during a callback for that type -// of listener still results in all listeners being called. - -var addon1 = { - id: "addon1@tests.mozilla.org", - version: "2.0", - name: "Test 1", - bootstrap: "true", - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "1", - maxVersion: "1" - }] -}; - -var listener1 = { - sawEvent: false, - onDisabling: function() { - this.sawEvent = true; - AddonManager.removeAddonListener(this); - }, - onNewInstall: function() { - this.sawEvent = true; - AddonManager.removeInstallListener(this); - } -}; -var listener2 = { - sawEvent: false, - onDisabling: function() { - this.sawEvent = true; - }, - onNewInstall: function() { - this.sawEvent = true; - } -}; -var listener3 = { - sawEvent: false, - onDisabling: function() { - this.sawEvent = true; - }, - onNewInstall: function() { - this.sawEvent = true; - } -}; - -const profileDir = gProfD.clone(); -profileDir.append("extensions"); - - -function run_test() { - do_test_pending(); - createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); - - writeInstallRDFForExtension(addon1, profileDir); - startupManager(); - - run_test_1(); -} - -function run_test_1() { - AddonManager.addAddonListener(listener1); - AddonManager.addAddonListener(listener2); - AddonManager.addAddonListener(listener3); - - AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org"], function([a1]) { - do_check_neq(a1, null); - do_check_false(a1.userDisabled); - do_check_true(a1.isActive); - - a1.userDisabled = true; - - do_check_true(listener1.sawEvent); - listener1.sawEvent = false; - do_check_true(listener2.sawEvent); - listener2.sawEvent = false; - do_check_true(listener3.sawEvent); - listener3.sawEvent = false; - - AddonManager.removeAddonListener(listener1); - AddonManager.removeAddonListener(listener2); - AddonManager.removeAddonListener(listener3); - - a1.uninstall(); - run_test_2(); - }); -} - -function run_test_2() { - AddonManager.addInstallListener(listener1); - AddonManager.addInstallListener(listener2); - AddonManager.addInstallListener(listener3); - - AddonManager.getInstallForFile(do_get_addon("test_bug757663"), function(aInstall) { - - do_check_true(listener1.sawEvent); - listener1.sawEvent = false; - do_check_true(listener2.sawEvent); - listener2.sawEvent = false; - do_check_true(listener3.sawEvent); - listener3.sawEvent = false; - - AddonManager.removeInstallListener(listener1); - AddonManager.removeInstallListener(listener2); - AddonManager.removeInstallListener(listener3); - - do_execute_soon(do_test_finished); - }); -} +/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// This test verifies that removing a listener during a callback for that type
+// of listener still results in all listeners being called.
+
+var addon1 = {
+ id: "addon1@tests.mozilla.org",
+ version: "2.0",
+ name: "Test 1",
+ bootstrap: "true",
+ targetApplications: [{
+ id: "xpcshell@tests.mozilla.org",
+ minVersion: "1",
+ maxVersion: "1"
+ }]
+};
+
+var listener1 = {
+ sawEvent: false,
+ onDisabling: function() {
+ this.sawEvent = true;
+ AddonManager.removeAddonListener(this);
+ },
+ onNewInstall: function() {
+ this.sawEvent = true;
+ AddonManager.removeInstallListener(this);
+ }
+};
+var listener2 = {
+ sawEvent: false,
+ onDisabling: function() {
+ this.sawEvent = true;
+ },
+ onNewInstall: function() {
+ this.sawEvent = true;
+ }
+};
+var listener3 = {
+ sawEvent: false,
+ onDisabling: function() {
+ this.sawEvent = true;
+ },
+ onNewInstall: function() {
+ this.sawEvent = true;
+ }
+};
+
+const profileDir = gProfD.clone();
+profileDir.append("extensions");
+
+
+function run_test() {
+ do_test_pending();
+ createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
+
+ writeInstallRDFForExtension(addon1, profileDir);
+ startupManager();
+
+ run_test_1();
+}
+
+function run_test_1() {
+ AddonManager.addAddonListener(listener1);
+ AddonManager.addAddonListener(listener2);
+ AddonManager.addAddonListener(listener3);
+
+ AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org"], function([a1]) {
+ do_check_neq(a1, null);
+ do_check_false(a1.userDisabled);
+ do_check_true(a1.isActive);
+
+ a1.userDisabled = true;
+
+ do_check_true(listener1.sawEvent);
+ listener1.sawEvent = false;
+ do_check_true(listener2.sawEvent);
+ listener2.sawEvent = false;
+ do_check_true(listener3.sawEvent);
+ listener3.sawEvent = false;
+
+ AddonManager.removeAddonListener(listener1);
+ AddonManager.removeAddonListener(listener2);
+ AddonManager.removeAddonListener(listener3);
+
+ a1.uninstall();
+ run_test_2();
+ });
+}
+
+function run_test_2() {
+ AddonManager.addInstallListener(listener1);
+ AddonManager.addInstallListener(listener2);
+ AddonManager.addInstallListener(listener3);
+
+ AddonManager.getInstallForFile(do_get_addon("test_bug757663"), function(aInstall) {
+
+ do_check_true(listener1.sawEvent);
+ listener1.sawEvent = false;
+ do_check_true(listener2.sawEvent);
+ listener2.sawEvent = false;
+ do_check_true(listener3.sawEvent);
+ listener3.sawEvent = false;
+
+ AddonManager.removeInstallListener(listener1);
+ AddonManager.removeInstallListener(listener2);
+ AddonManager.removeInstallListener(listener3);
+
+ do_execute_soon(do_test_finished);
+ });
+}
diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_cache_certdb.js b/toolkit/mozapps/extensions/test/xpcshell/test_cache_certdb.js deleted file mode 100644 index edb442aad..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_cache_certdb.js +++ /dev/null @@ -1,82 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -// We require signature checks for this test -Services.prefs.setBoolPref(PREF_XPI_SIGNATURES_REQUIRED, true); -gUseRealCertChecks = true; - -const CERT = `MIIDITCCAgmgAwIBAgIJALAv8fydd6nBMA0GCSqGSIb3DQEBBQUAMCcxJTAjBgNV -BAMMHGJvb3RzdHJhcDFAdGVzdHMubW96aWxsYS5vcmcwHhcNMTYwMjAyMjMxNjUy -WhcNMjYwMTMwMjMxNjUyWjAnMSUwIwYDVQQDDBxib290c3RyYXAxQHRlc3RzLm1v -emlsbGEub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5caNuLTu -H8dEqNntLlhKi4y09hrgcF3cb6n5Xx9DIHA8CKiZxt9qGXKeeiDwEiiQ8ibJYzdc -jLkbzJUyPVUaH9ygrWynSpSTOvv/Ys3+ERrCo9W7Zuzwdmzt6TTEjFMS4lVx06us -3uUqkdp3JMgCqCEbOFZiztICiSKrp8QFJkAfApZzBqmJOPOWH0yZ2CRRzvbQZ6af -hqQDUalJQjWfsenyUWphhbREqExetxHJFR3OrmJt/shXVyz6dD7TBuE3PPUh1RpE -3ejVufcTzjV3XmK79PxsKLM9V2+ww9e9V3OET57kyvn+bpSWdUYm3X4DA8dxNW6+ -kTFWRnQNZ+zQVQIDAQABo1AwTjAdBgNVHQ4EFgQUac36ccv+99N5HxYa8dCDYRaF -HNQwHwYDVR0jBBgwFoAUac36ccv+99N5HxYa8dCDYRaFHNQwDAYDVR0TBAUwAwEB -/zANBgkqhkiG9w0BAQUFAAOCAQEAFfu3MN8EtY5wcxOFdGShOmGQPm2MJJVE6MG+ -p4RqHrukHZSgKOyWjkRk7t6NXzNcnHco9HFv7FQRAXSJ5zObmyu+TMZlu4jHHCav -GMcV3C/4SUGtlipZbgNe00UAIm6tM3Wh8dr38W7VYg4KGAwXou5XhQ9gCAnSn90o -H/42NqHTjJsR4v18izX2aO25ARQdMby7Lsr5j9RqweHywiSlPusFcKRseqOnIP0d -JT3+qh78LeMbNBO2mYD3SP/zu0TAmkAVNcj2KPw0+a0kVZ15rvslPC/K3xn9msMk -fQthv3rDAcsWvi9YO7T+vylgZBgJfn1ZqpQqy58xN96uh6nPOw==`; - -function overrideCertDB() { - // Unregister the real database. - let registrar = Components.manager.QueryInterface(AM_Ci.nsIComponentRegistrar); - let factory = registrar.getClassObject(CERTDB_CID, AM_Ci.nsIFactory); - registrar.unregisterFactory(CERTDB_CID, factory); - - // Get the real DB - let realCertDB = factory.createInstance(null, AM_Ci.nsIX509CertDB); - - let fakeCert = realCertDB.constructX509FromBase64(CERT.replace(/\n/g, "")); - - let fakeCertDB = { - openSignedAppFileAsync(root, file, callback) { - callback.openSignedAppFileFinished(Components.results.NS_OK, null, fakeCert); - }, - - verifySignedDirectoryAsync(root, dir, callback) { - callback.verifySignedDirectoryFinished(Components.results.NS_OK, fakeCert); - }, - - QueryInterface: XPCOMUtils.generateQI([AM_Ci.nsIX509CertDB]) - }; - - for (let property of Object.keys(realCertDB)) { - if (property in fakeCertDB) { - continue; - } - - if (typeof realCertDB[property] == "function") { - fakeCertDB[property] = realCertDB[property].bind(realCertDB); - } - } - - let certDBFactory = { - createInstance: function(outer, iid) { - if (outer != null) { - throw Components.results.NS_ERROR_NO_AGGREGATION; - } - return fakeCertDB.QueryInterface(iid); - } - }; - registrar.registerFactory(CERTDB_CID, "CertDB", - CERTDB_CONTRACTID, certDBFactory); -} - -add_task(function*() { - createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); - startupManager(); - - // Once the application is started we shouldn't be able to replace the - // certificate database - overrideCertDB(); - - let install = yield new Promise(resolve => AddonManager.getInstallForFile(do_get_addon("test_bootstrap1_1"), resolve)); - do_check_eq(install.state, AddonManager.STATE_DOWNLOAD_FAILED); -}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_cacheflush.js b/toolkit/mozapps/extensions/test/xpcshell/test_cacheflush.js index f3448abd2..4e7da0ee7 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_cacheflush.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_cacheflush.js @@ -11,9 +11,6 @@ var CacheFlushObserver = { observe: function(aSubject, aTopic, aData) { if (aTopic != "flush-cache-entry") return; - // Ignore flushes triggered by the fake cert DB - if (aData == "cert-override") - return; do_check_true(gExpectedFile != null); do_check_true(aSubject instanceof AM_Ci.nsIFile); @@ -88,7 +85,7 @@ function run_test_2() { function run_test_3() { AddonManager.getInstallForFile(do_get_addon("test_cacheflush2"), function(aInstall) { aInstall.addListener({ - onInstallStarted: function() { + onInstallStarted: function(aInstall) { // We should flush the staged XPI when completing the install gExpectedFile = gProfD.clone(); gExpectedFile.append("extensions"); @@ -96,7 +93,7 @@ function run_test_3() { gExpectedFile.append("addon2@tests.mozilla.org.xpi"); }, - onInstallEnded: function() { + onInstallEnded: function(aInstall) { do_check_eq(gCacheFlushCount, 1); gExpectedFile = null; gCacheFlushCount = 0; diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_checkCompatibility_themeOverride.js b/toolkit/mozapps/extensions/test/xpcshell/test_checkCompatibility_themeOverride.js index b6cb13e08..c872d75c3 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_checkCompatibility_themeOverride.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_checkCompatibility_themeOverride.js @@ -1,93 +1,93 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -// This verifies that the (temporary) -// extensions.checkCompatibility.temporaryThemeOverride_minAppVersion -// preference works. - -var ADDONS = [{ - id: "addon1@tests.mozilla.org", - type: 4, - internalName: "theme1/1.0", - version: "1.0", - name: "Test 1", - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "1.0", - maxVersion: "1.0" - }] -}, { - id: "addon2@tests.mozilla.org", - type: 4, - internalName: "theme2/1.0", - version: "1.0", - name: "Test 2", - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "2.0", - maxVersion: "2.0" - }] -}]; - -const profileDir = gProfD.clone(); -profileDir.append("extensions"); - - -function run_test() { - do_test_pending(); - createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3.0", "1"); - - for (let a of ADDONS) { - writeInstallRDFForExtension(a, profileDir); - } - - startupManager(); - - run_test_1(); -} - -function run_test_1() { - AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", - "addon2@tests.mozilla.org"], - function([a1, a2]) { - - do_check_neq(a1, null); - do_check_false(a1.isActive); - do_check_false(a1.isCompatible); - do_check_true(a1.appDisabled); - - do_check_neq(a2, null); - do_check_false(a2.isActive); - do_check_false(a2.isCompatible); - do_check_true(a1.appDisabled); - - do_execute_soon(run_test_2); - }); -} - -function run_test_2() { - Services.prefs.setCharPref("extensions.checkCompatibility.temporaryThemeOverride_minAppVersion", "2.0"); - if (isNightlyChannel()) - Services.prefs.setBoolPref("extensions.checkCompatibility.nightly", false); - else - Services.prefs.setBoolPref("extensions.checkCompatibility.3.0", false); - restartManager(); - - AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", - "addon2@tests.mozilla.org"], - function([a1, a2]) { - - do_check_neq(a1, null); - do_check_false(a1.isActive); - do_check_false(a1.isCompatible); - do_check_true(a1.appDisabled); - - do_check_neq(a2, null); - do_check_false(a2.isActive); - do_check_false(a2.isCompatible); - do_check_false(a2.appDisabled); - - do_execute_soon(do_test_finished); - }); -} +/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// This verifies that the (temporary)
+// extensions.checkCompatibility.temporaryThemeOverride_minAppVersion
+// preference works.
+
+var ADDONS = [{
+ id: "addon1@tests.mozilla.org",
+ type: 4,
+ internalName: "theme1/1.0",
+ version: "1.0",
+ name: "Test 1",
+ targetApplications: [{
+ id: "xpcshell@tests.mozilla.org",
+ minVersion: "1.0",
+ maxVersion: "1.0"
+ }]
+}, {
+ id: "addon2@tests.mozilla.org",
+ type: 4,
+ internalName: "theme2/1.0",
+ version: "1.0",
+ name: "Test 2",
+ targetApplications: [{
+ id: "xpcshell@tests.mozilla.org",
+ minVersion: "2.0",
+ maxVersion: "2.0"
+ }]
+}];
+
+const profileDir = gProfD.clone();
+profileDir.append("extensions");
+
+
+function run_test() {
+ do_test_pending();
+ createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3.0", "1");
+
+ for (let a of ADDONS) {
+ writeInstallRDFForExtension(a, profileDir);
+ }
+
+ startupManager();
+
+ run_test_1();
+}
+
+function run_test_1() {
+ AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
+ "addon2@tests.mozilla.org"],
+ function([a1, a2]) {
+
+ do_check_neq(a1, null);
+ do_check_false(a1.isActive);
+ do_check_false(a1.isCompatible);
+ do_check_true(a1.appDisabled);
+
+ do_check_neq(a2, null);
+ do_check_false(a2.isActive);
+ do_check_false(a2.isCompatible);
+ do_check_true(a1.appDisabled);
+
+ do_execute_soon(run_test_2);
+ });
+}
+
+function run_test_2() {
+ Services.prefs.setCharPref("extensions.checkCompatibility.temporaryThemeOverride_minAppVersion", "2.0");
+ if (isNightlyChannel())
+ Services.prefs.setBoolPref("extensions.checkCompatibility.nightly", false);
+ else
+ Services.prefs.setBoolPref("extensions.checkCompatibility.3.0", false);
+ restartManager();
+
+ AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
+ "addon2@tests.mozilla.org"],
+ function([a1, a2]) {
+
+ do_check_neq(a1, null);
+ do_check_false(a1.isActive);
+ do_check_false(a1.isCompatible);
+ do_check_true(a1.appDisabled);
+
+ do_check_neq(a2, null);
+ do_check_false(a2.isActive);
+ do_check_false(a2.isCompatible);
+ do_check_false(a2.appDisabled);
+
+ do_execute_soon(do_test_finished);
+ });
+}
diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_compatoverrides.js b/toolkit/mozapps/extensions/test/xpcshell/test_compatoverrides.js index c079534c3..ef60306db 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_compatoverrides.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_compatoverrides.js @@ -255,5 +255,5 @@ function run_test_1() { function run_test_2() { do_print("Run test 2"); restartManager(); - check_compat_status(end_test); + check_compat_status(end_test); } diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_corrupt.js b/toolkit/mozapps/extensions/test/xpcshell/test_corrupt.js index 210c6a936..4c8b3750d 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_corrupt.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_corrupt.js @@ -265,73 +265,72 @@ function run_test_1() { "addon7@tests.mozilla.org", "theme1@tests.mozilla.org", "theme2@tests.mozilla.org"], - callback_soon(function([a1_2, a2_2, a3_2, a4_2, a5_2, a6_2, a7_2, t1_2, t2_2]) { + callback_soon(function([a1, a2, a3, a4, a5, a6, a7, t1, t2]) { // Should be correctly recovered - do_check_neq(a1_2, null); - do_check_true(a1_2.isActive); - do_check_false(a1_2.userDisabled); - do_check_false(a1_2.appDisabled); - do_check_eq(a1_2.pendingOperations, AddonManager.PENDING_NONE); + do_check_neq(a1, null); + do_check_true(a1.isActive); + do_check_false(a1.userDisabled); + do_check_false(a1.appDisabled); + do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE); // Should be correctly recovered - do_check_neq(a2_2, null); - do_check_false(a2_2.isActive); - do_check_true(a2_2.userDisabled); - do_check_false(a2_2.appDisabled); - do_check_eq(a2_2.pendingOperations, AddonManager.PENDING_NONE); + do_check_neq(a2, null); + do_check_false(a2.isActive); + do_check_true(a2.userDisabled); + do_check_false(a2.appDisabled); + do_check_eq(a2.pendingOperations, AddonManager.PENDING_NONE); // The compatibility update won't be recovered but it should still be // active for this session - do_check_neq(a3_2, null); - do_check_true(a3_2.isActive); - do_check_false(a3_2.userDisabled); - do_check_false(a3_2.appDisabled); - do_check_eq(a3_2.pendingOperations, AddonManager.PENDING_NONE); + do_check_neq(a3, null); + do_check_true(a3.isActive); + do_check_false(a3.userDisabled); + do_check_false(a3.appDisabled); + do_check_eq(a3.pendingOperations, AddonManager.PENDING_NONE); // The compatibility update won't be recovered and with strict // compatibility it would not have been able to tell that it was // previously userDisabled. However, without strict compat, it wasn't // appDisabled, so it knows it must have been userDisabled. - do_check_neq(a4_2, null); - do_check_false(a4_2.isActive); - do_check_true(a4_2.userDisabled); - do_check_false(a4_2.appDisabled); - do_check_eq(a4_2.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(a5_2, null); - do_check_true(a5_2.isActive); - do_check_false(a5_2.userDisabled); - do_check_false(a5_2.appDisabled); - do_check_eq(a5_2.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(a6_2, null); - do_check_true(a6_2.isActive); - do_check_false(a6_2.userDisabled); - do_check_false(a6_2.appDisabled); - do_check_eq(a6_2.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(a7_2, null); - do_check_false(a7_2.isActive); - do_check_true(a7_2.userDisabled); - do_check_false(a7_2.appDisabled); - do_check_eq(a7_2.pendingOperations, AddonManager.PENDING_NONE); + do_check_neq(a4, null); + do_check_false(a4.isActive); + do_check_true(a4.userDisabled); + do_check_false(a4.appDisabled); + do_check_eq(a4.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a5, null); + do_check_true(a5.isActive); + do_check_false(a5.userDisabled); + do_check_false(a5.appDisabled); + do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a6, null); + do_check_true(a6.isActive); + do_check_false(a6.userDisabled); + do_check_false(a6.appDisabled); + do_check_eq(a6.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a7, null); + do_check_false(a7.isActive); + do_check_true(a7.userDisabled); + do_check_false(a7.appDisabled); + do_check_eq(a7.pendingOperations, AddonManager.PENDING_NONE); // Should be correctly recovered - do_check_neq(t1_2, null); - do_check_false(t1_2.isActive); - do_check_true(t1_2.userDisabled); - do_check_false(t1_2.appDisabled); - do_check_eq(t1_2.pendingOperations, AddonManager.PENDING_NONE); + do_check_neq(t1, null); + do_check_false(t1.isActive); + do_check_true(t1.userDisabled); + do_check_false(t1.appDisabled); + do_check_eq(t1.pendingOperations, AddonManager.PENDING_NONE); // Should be correctly recovered - do_check_neq(t2_2, null); - do_check_true(t2_2.isActive); - do_check_false(t2_2.userDisabled); - do_check_false(t2_2.appDisabled); - do_check_eq(t2_2.pendingOperations, AddonManager.PENDING_NONE); + do_check_neq(t2, null); + do_check_true(t2.isActive); + do_check_false(t2.userDisabled); + do_check_false(t2.appDisabled); + do_check_eq(t2.pendingOperations, AddonManager.PENDING_NONE); - Assert.throws(shutdownManager); - startupManager(false); + restartManager(); AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", "addon2@tests.mozilla.org", @@ -342,62 +341,60 @@ function run_test_1() { "addon7@tests.mozilla.org", "theme1@tests.mozilla.org", "theme2@tests.mozilla.org"], - callback_soon(function([a1_3, a2_3, a3_3, a4_3, a5_3, a6_3, a7_3, t1_3, t2_3]) { - do_check_neq(a1_3, null); - do_check_true(a1_3.isActive); - do_check_false(a1_3.userDisabled); - do_check_false(a1_3.appDisabled); - do_check_eq(a1_3.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(a2_3, null); - do_check_false(a2_3.isActive); - do_check_true(a2_3.userDisabled); - do_check_false(a2_3.appDisabled); - do_check_eq(a2_3.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(a3_3, null); - do_check_true(a3_3.isActive); - do_check_false(a3_3.userDisabled); - do_check_false(a3_3.appDisabled); - do_check_eq(a3_3.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(a4_3, null); - do_check_false(a4_3.isActive); - do_check_true(a4_3.userDisabled); - do_check_false(a4_3.appDisabled); - do_check_eq(a4_3.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(a5_3, null); - do_check_true(a5_3.isActive); - do_check_false(a5_3.userDisabled); - do_check_false(a5_3.appDisabled); - do_check_eq(a5_3.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(a6_3, null); - do_check_true(a6_3.isActive); - do_check_false(a6_3.userDisabled); - do_check_false(a6_3.appDisabled); - do_check_eq(a6_3.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(a7_3, null); - do_check_false(a7_3.isActive); - do_check_true(a7_3.userDisabled); - do_check_false(a7_3.appDisabled); - do_check_eq(a7_3.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(t1_3, null); - do_check_false(t1_3.isActive); - do_check_true(t1_3.userDisabled); - do_check_false(t1_3.appDisabled); - do_check_eq(t1_3.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(t2_3, null); - do_check_true(t2_3.isActive); - do_check_false(t2_3.userDisabled); - do_check_false(t2_3.appDisabled); - do_check_eq(t2_3.pendingOperations, AddonManager.PENDING_NONE); - - Assert.throws(shutdownManager); + callback_soon(function([a1, a2, a3, a4, a5, a6, a7, t1, t2]) { + do_check_neq(a1, null); + do_check_true(a1.isActive); + do_check_false(a1.userDisabled); + do_check_false(a1.appDisabled); + do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a2, null); + do_check_false(a2.isActive); + do_check_true(a2.userDisabled); + do_check_false(a2.appDisabled); + do_check_eq(a2.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a3, null); + do_check_true(a3.isActive); + do_check_false(a3.userDisabled); + do_check_false(a3.appDisabled); + do_check_eq(a3.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a4, null); + do_check_false(a4.isActive); + do_check_true(a4.userDisabled); + do_check_false(a4.appDisabled); + do_check_eq(a4.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a5, null); + do_check_true(a5.isActive); + do_check_false(a5.userDisabled); + do_check_false(a5.appDisabled); + do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a6, null); + do_check_true(a6.isActive); + do_check_false(a6.userDisabled); + do_check_false(a6.appDisabled); + do_check_eq(a6.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a7, null); + do_check_false(a7.isActive); + do_check_true(a7.userDisabled); + do_check_false(a7.appDisabled); + do_check_eq(a7.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(t1, null); + do_check_false(t1.isActive); + do_check_true(t1.userDisabled); + do_check_false(t1.appDisabled); + do_check_eq(t1.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(t2, null); + do_check_true(t2.isActive); + do_check_false(t2.userDisabled); + do_check_false(t2.appDisabled); + do_check_eq(t2.pendingOperations, AddonManager.PENDING_NONE); end_test(); })); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_corrupt_strictcompat.js b/toolkit/mozapps/extensions/test/xpcshell/test_corrupt_strictcompat.js index 622973472..3ba6d213b 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_corrupt_strictcompat.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_corrupt_strictcompat.js @@ -266,71 +266,70 @@ function run_test_1() { "addon7@tests.mozilla.org", "theme1@tests.mozilla.org", "theme2@tests.mozilla.org"], - callback_soon(function([a1_2, a2_2, a3_2, a4_2, a5_2, a6_2, a7_2, t1_2, t2_2]) { + callback_soon(function([a1, a2, a3, a4, a5, a6, a7, t1, t2]) { // Should be correctly recovered - do_check_neq(a1_2, null); - do_check_true(a1_2.isActive); - do_check_false(a1_2.userDisabled); - do_check_false(a1_2.appDisabled); - do_check_eq(a1_2.pendingOperations, AddonManager.PENDING_NONE); + do_check_neq(a1, null); + do_check_true(a1.isActive); + do_check_false(a1.userDisabled); + do_check_false(a1.appDisabled); + do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE); // Should be correctly recovered - do_check_neq(a2_2, null); - do_check_false(a2_2.isActive); - do_check_true(a2_2.userDisabled); - do_check_false(a2_2.appDisabled); - do_check_eq(a2_2.pendingOperations, AddonManager.PENDING_NONE); + do_check_neq(a2, null); + do_check_false(a2.isActive); + do_check_true(a2.userDisabled); + do_check_false(a2.appDisabled); + do_check_eq(a2.pendingOperations, AddonManager.PENDING_NONE); // The compatibility update won't be recovered but it should still be // active for this session - do_check_neq(a3_2, null); - do_check_true(a3_2.isActive); - do_check_false(a3_2.userDisabled); - do_check_true(a3_2.appDisabled); - do_check_eq(a3_2.pendingOperations, AddonManager.PENDING_DISABLE); + do_check_neq(a3, null); + do_check_true(a3.isActive); + do_check_false(a3.userDisabled); + do_check_true(a3.appDisabled); + do_check_eq(a3.pendingOperations, AddonManager.PENDING_DISABLE); // The compatibility update won't be recovered and it will not have been // able to tell that it was previously userDisabled - do_check_neq(a4_2, null); - do_check_false(a4_2.isActive); - do_check_false(a4_2.userDisabled); - do_check_true(a4_2.appDisabled); - do_check_eq(a4_2.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(a5_2, null); - do_check_false(a5_2.isActive); - do_check_false(a5_2.userDisabled); - do_check_true(a5_2.appDisabled); - do_check_eq(a5_2.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(a6_2, null); - do_check_true(a6_2.isActive); - do_check_false(a6_2.userDisabled); - do_check_false(a6_2.appDisabled); - do_check_eq(a6_2.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(a7_2, null); - do_check_false(a7_2.isActive); - do_check_true(a7_2.userDisabled); - do_check_false(a7_2.appDisabled); - do_check_eq(a7_2.pendingOperations, AddonManager.PENDING_NONE); + do_check_neq(a4, null); + do_check_false(a4.isActive); + do_check_false(a4.userDisabled); + do_check_true(a4.appDisabled); + do_check_eq(a4.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a5, null); + do_check_false(a5.isActive); + do_check_false(a5.userDisabled); + do_check_true(a5.appDisabled); + do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a6, null); + do_check_true(a6.isActive); + do_check_false(a6.userDisabled); + do_check_false(a6.appDisabled); + do_check_eq(a6.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a7, null); + do_check_false(a7.isActive); + do_check_true(a7.userDisabled); + do_check_false(a7.appDisabled); + do_check_eq(a7.pendingOperations, AddonManager.PENDING_NONE); // Should be correctly recovered - do_check_neq(t1_2, null); - do_check_false(t1_2.isActive); - do_check_true(t1_2.userDisabled); - do_check_false(t1_2.appDisabled); - do_check_eq(t1_2.pendingOperations, AddonManager.PENDING_NONE); + do_check_neq(t1, null); + do_check_false(t1.isActive); + do_check_true(t1.userDisabled); + do_check_false(t1.appDisabled); + do_check_eq(t1.pendingOperations, AddonManager.PENDING_NONE); // Should be correctly recovered - do_check_neq(t2_2, null); - do_check_true(t2_2.isActive); - do_check_false(t2_2.userDisabled); - do_check_false(t2_2.appDisabled); - do_check_eq(t2_2.pendingOperations, AddonManager.PENDING_NONE); + do_check_neq(t2, null); + do_check_true(t2.isActive); + do_check_false(t2.userDisabled); + do_check_false(t2.appDisabled); + do_check_eq(t2.pendingOperations, AddonManager.PENDING_NONE); - Assert.throws(shutdownManager); - startupManager(false); + restartManager(); AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", "addon2@tests.mozilla.org", @@ -341,62 +340,60 @@ function run_test_1() { "addon7@tests.mozilla.org", "theme1@tests.mozilla.org", "theme2@tests.mozilla.org"], - callback_soon(function([a1_3, a2_3, a3_3, a4_3, a5_3, a6_3, a7_3, t1_3, t2_3]) { - do_check_neq(a1_3, null); - do_check_true(a1_3.isActive); - do_check_false(a1_3.userDisabled); - do_check_false(a1_3.appDisabled); - do_check_eq(a1_3.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(a2_3, null); - do_check_false(a2_3.isActive); - do_check_true(a2_3.userDisabled); - do_check_false(a2_3.appDisabled); - do_check_eq(a2_3.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(a3_3, null); - do_check_false(a3_3.isActive); - do_check_false(a3_3.userDisabled); - do_check_true(a3_3.appDisabled); - do_check_eq(a3_3.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(a4_3, null); - do_check_false(a4_3.isActive); - do_check_false(a4_3.userDisabled); - do_check_true(a4_3.appDisabled); - do_check_eq(a4_3.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(a5_3, null); - do_check_false(a5_3.isActive); - do_check_false(a5_3.userDisabled); - do_check_true(a5_3.appDisabled); - do_check_eq(a5_3.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(a6_3, null); - do_check_true(a6_3.isActive); - do_check_false(a6_3.userDisabled); - do_check_false(a6_3.appDisabled); - do_check_eq(a6_3.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(a7_3, null); - do_check_false(a7_3.isActive); - do_check_true(a7_3.userDisabled); - do_check_false(a7_3.appDisabled); - do_check_eq(a7_3.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(t1_3, null); - do_check_false(t1_3.isActive); - do_check_true(t1_3.userDisabled); - do_check_false(t1_3.appDisabled); - do_check_eq(t1_3.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(t2_3, null); - do_check_true(t2_3.isActive); - do_check_false(t2_3.userDisabled); - do_check_false(t2_3.appDisabled); - do_check_eq(t2_3.pendingOperations, AddonManager.PENDING_NONE); - - Assert.throws(shutdownManager); + callback_soon(function([a1, a2, a3, a4, a5, a6, a7, t1, t2]) { + do_check_neq(a1, null); + do_check_true(a1.isActive); + do_check_false(a1.userDisabled); + do_check_false(a1.appDisabled); + do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a2, null); + do_check_false(a2.isActive); + do_check_true(a2.userDisabled); + do_check_false(a2.appDisabled); + do_check_eq(a2.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a3, null); + do_check_false(a3.isActive); + do_check_false(a3.userDisabled); + do_check_true(a3.appDisabled); + do_check_eq(a3.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a4, null); + do_check_false(a4.isActive); + do_check_false(a4.userDisabled); + do_check_true(a4.appDisabled); + do_check_eq(a4.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a5, null); + do_check_false(a5.isActive); + do_check_false(a5.userDisabled); + do_check_true(a5.appDisabled); + do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a6, null); + do_check_true(a6.isActive); + do_check_false(a6.userDisabled); + do_check_false(a6.appDisabled); + do_check_eq(a6.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a7, null); + do_check_false(a7.isActive); + do_check_true(a7.userDisabled); + do_check_false(a7.appDisabled); + do_check_eq(a7.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(t1, null); + do_check_false(t1.isActive); + do_check_true(t1.userDisabled); + do_check_false(t1.appDisabled); + do_check_eq(t1.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(t2, null); + do_check_true(t2.isActive); + do_check_false(t2.userDisabled); + do_check_false(t2.appDisabled); + do_check_eq(t2.pendingOperations, AddonManager.PENDING_NONE); end_test(); })); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_dataDirectory.js b/toolkit/mozapps/extensions/test/xpcshell/test_dataDirectory.js index bf75818e9..99babc722 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_dataDirectory.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_dataDirectory.js @@ -11,11 +11,11 @@ var ADDON = { addon: "test_data_directory" }; -function run_test() { - var expectedDir = gProfD.clone(); - expectedDir.append("extension-data"); - expectedDir.append(ADDON.id); +var expectedDir = gProfD.clone(); +expectedDir.append("extension-data"); +expectedDir.append(ADDON.id); +function run_test() { do_test_pending(); do_check_false(expectedDir.exists()); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_delay_update.js b/toolkit/mozapps/extensions/test/xpcshell/test_delay_update.js deleted file mode 100644 index 3d7eef051..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_delay_update.js +++ /dev/null @@ -1,260 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -// This verifies that delaying an update works - -// The test extension uses an insecure update url. -Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); - -Components.utils.import("resource://testing-common/httpd.js"); -const profileDir = gProfD.clone(); -profileDir.append("extensions"); -const tempdir = gTmpD.clone(); - -const IGNORE_ID = "test_delay_update_ignore@tests.mozilla.org"; -const COMPLETE_ID = "test_delay_update_complete@tests.mozilla.org"; -const DEFER_ID = "test_delay_update_defer@tests.mozilla.org"; - -const TEST_IGNORE_PREF = "delaytest.ignore"; - -// Note that we would normally use BootstrapMonitor but it currently requires -// the objects in `data` to be serializable, and we need a real reference to the -// `instanceID` symbol to test. - -createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "42"); - -// Create and configure the HTTP server. -let testserver = createHttpServer(); -gPort = testserver.identity.primaryPort; -mapFile("/data/test_delay_updates_complete.rdf", testserver); -mapFile("/data/test_delay_updates_ignore.rdf", testserver); -mapFile("/data/test_delay_updates_defer.rdf", testserver); -testserver.registerDirectory("/addons/", do_get_file("addons")); - -function* createIgnoreAddon() { - writeInstallRDFToDir({ - id: IGNORE_ID, - version: "1.0", - bootstrap: true, - unpack: true, - updateURL: `http://localhost:${gPort}/data/test_delay_updates_ignore.rdf`, - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "1", - maxVersion: "1" - }], - name: "Test Delay Update Ignore", - }, profileDir, IGNORE_ID, "bootstrap.js"); - - let unpacked_addon = profileDir.clone(); - unpacked_addon.append(IGNORE_ID); - do_get_file("data/test_delay_update_ignore/bootstrap.js") - .copyTo(unpacked_addon, "bootstrap.js"); -} - -function* createCompleteAddon() { - writeInstallRDFToDir({ - id: COMPLETE_ID, - version: "1.0", - bootstrap: true, - unpack: true, - updateURL: `http://localhost:${gPort}/data/test_delay_updates_complete.rdf`, - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "1", - maxVersion: "1" - }], - name: "Test Delay Update Complete", - }, profileDir, COMPLETE_ID, "bootstrap.js"); - - let unpacked_addon = profileDir.clone(); - unpacked_addon.append(COMPLETE_ID); - do_get_file("data/test_delay_update_complete/bootstrap.js") - .copyTo(unpacked_addon, "bootstrap.js"); -} - -function* createDeferAddon() { - writeInstallRDFToDir({ - id: DEFER_ID, - version: "1.0", - bootstrap: true, - unpack: true, - updateURL: `http://localhost:${gPort}/data/test_delay_updates_defer.rdf`, - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "1", - maxVersion: "1" - }], - name: "Test Delay Update Defer", - }, profileDir, DEFER_ID, "bootstrap.js"); - - let unpacked_addon = profileDir.clone(); - unpacked_addon.append(DEFER_ID); - do_get_file("data/test_delay_update_defer/bootstrap.js") - .copyTo(unpacked_addon, "bootstrap.js"); -} - -// add-on registers upgrade listener, and ignores update. -add_task(function*() { - - yield createIgnoreAddon(); - - startupManager(); - - let addon = yield promiseAddonByID(IGNORE_ID); - do_check_neq(addon, null); - do_check_eq(addon.version, "1.0"); - do_check_eq(addon.name, "Test Delay Update Ignore"); - do_check_true(addon.isCompatible); - do_check_false(addon.appDisabled); - do_check_true(addon.isActive); - do_check_eq(addon.type, "extension"); - - let update = yield promiseFindAddonUpdates(addon); - let install = update.updateAvailable; - - yield promiseCompleteAllInstalls([install]); - - do_check_eq(install.state, AddonManager.STATE_POSTPONED); - - // addon upgrade has been delayed - let addon_postponed = yield promiseAddonByID(IGNORE_ID); - do_check_neq(addon_postponed, null); - do_check_eq(addon_postponed.version, "1.0"); - do_check_eq(addon_postponed.name, "Test Delay Update Ignore"); - do_check_true(addon_postponed.isCompatible); - do_check_false(addon_postponed.appDisabled); - do_check_true(addon_postponed.isActive); - do_check_eq(addon_postponed.type, "extension"); - do_check_true(Services.prefs.getBoolPref(TEST_IGNORE_PREF)); - - // restarting allows upgrade to proceed - yield promiseRestartManager(); - - let addon_upgraded = yield promiseAddonByID(IGNORE_ID); - do_check_neq(addon_upgraded, null); - do_check_eq(addon_upgraded.version, "2.0"); - do_check_eq(addon_upgraded.name, "Test Delay Update Ignore"); - do_check_true(addon_upgraded.isCompatible); - do_check_false(addon_upgraded.appDisabled); - do_check_true(addon_upgraded.isActive); - do_check_eq(addon_upgraded.type, "extension"); - - yield shutdownManager(); -}); - -// add-on registers upgrade listener, and allows update. -add_task(function*() { - - yield createCompleteAddon(); - - startupManager(); - - let addon = yield promiseAddonByID(COMPLETE_ID); - do_check_neq(addon, null); - do_check_eq(addon.version, "1.0"); - do_check_eq(addon.name, "Test Delay Update Complete"); - do_check_true(addon.isCompatible); - do_check_false(addon.appDisabled); - do_check_true(addon.isActive); - do_check_eq(addon.type, "extension"); - - let update = yield promiseFindAddonUpdates(addon); - let install = update.updateAvailable; - - yield promiseCompleteAllInstalls([install]); - - // upgrade is initially postponed - let addon_postponed = yield promiseAddonByID(COMPLETE_ID); - do_check_neq(addon_postponed, null); - do_check_eq(addon_postponed.version, "1.0"); - do_check_eq(addon_postponed.name, "Test Delay Update Complete"); - do_check_true(addon_postponed.isCompatible); - do_check_false(addon_postponed.appDisabled); - do_check_true(addon_postponed.isActive); - do_check_eq(addon_postponed.type, "extension"); - - // addon upgrade has been allowed - let [addon_allowed] = yield promiseAddonEvent("onInstalled"); - do_check_neq(addon_allowed, null); - do_check_eq(addon_allowed.version, "2.0"); - do_check_eq(addon_allowed.name, "Test Delay Update Complete"); - do_check_true(addon_allowed.isCompatible); - do_check_false(addon_allowed.appDisabled); - do_check_true(addon_allowed.isActive); - do_check_eq(addon_allowed.type, "extension"); - - // restarting changes nothing - yield promiseRestartManager(); - - let addon_upgraded = yield promiseAddonByID(COMPLETE_ID); - do_check_neq(addon_upgraded, null); - do_check_eq(addon_upgraded.version, "2.0"); - do_check_eq(addon_upgraded.name, "Test Delay Update Complete"); - do_check_true(addon_upgraded.isCompatible); - do_check_false(addon_upgraded.appDisabled); - do_check_true(addon_upgraded.isActive); - do_check_eq(addon_upgraded.type, "extension"); - - yield shutdownManager(); -}); - -// add-on registers upgrade listener, initially defers update then allows upgrade -add_task(function*() { - - yield createDeferAddon(); - - startupManager(); - - let addon = yield promiseAddonByID(DEFER_ID); - do_check_neq(addon, null); - do_check_eq(addon.version, "1.0"); - do_check_eq(addon.name, "Test Delay Update Defer"); - do_check_true(addon.isCompatible); - do_check_false(addon.appDisabled); - do_check_true(addon.isActive); - do_check_eq(addon.type, "extension"); - - let update = yield promiseFindAddonUpdates(addon); - let install = update.updateAvailable; - - yield promiseCompleteAllInstalls([install]); - - // upgrade is initially postponed - let addon_postponed = yield promiseAddonByID(DEFER_ID); - do_check_neq(addon_postponed, null); - do_check_eq(addon_postponed.version, "1.0"); - do_check_eq(addon_postponed.name, "Test Delay Update Defer"); - do_check_true(addon_postponed.isCompatible); - do_check_false(addon_postponed.appDisabled); - do_check_true(addon_postponed.isActive); - do_check_eq(addon_postponed.type, "extension"); - - // add-on will not allow upgrade until fake event fires - AddonManagerPrivate.callAddonListeners("onFakeEvent"); - - // addon upgrade has been allowed - let [addon_allowed] = yield promiseAddonEvent("onInstalled"); - do_check_neq(addon_allowed, null); - do_check_eq(addon_allowed.version, "2.0"); - do_check_eq(addon_allowed.name, "Test Delay Update Defer"); - do_check_true(addon_allowed.isCompatible); - do_check_false(addon_allowed.appDisabled); - do_check_true(addon_allowed.isActive); - do_check_eq(addon_allowed.type, "extension"); - - // restarting changes nothing - yield promiseRestartManager(); - - let addon_upgraded = yield promiseAddonByID(DEFER_ID); - do_check_neq(addon_upgraded, null); - do_check_eq(addon_upgraded.version, "2.0"); - do_check_eq(addon_upgraded.name, "Test Delay Update Defer"); - do_check_true(addon_upgraded.isCompatible); - do_check_false(addon_upgraded.appDisabled); - do_check_true(addon_upgraded.isActive); - do_check_eq(addon_upgraded.type, "extension"); - - yield shutdownManager(); -}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_delay_update_webextension.js b/toolkit/mozapps/extensions/test/xpcshell/test_delay_update_webextension.js deleted file mode 100644 index cdfac8f8c..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_delay_update_webextension.js +++ /dev/null @@ -1,344 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -// This verifies that delaying an update works for WebExtensions. - -// The test extension uses an insecure update url. -Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false); - -/* globals browser*/ - -const profileDir = gProfD.clone(); -profileDir.append("extensions"); -const tempdir = gTmpD.clone(); -const stageDir = profileDir.clone(); -stageDir.append("staged"); - -const IGNORE_ID = "test_delay_update_ignore_webext@tests.mozilla.org"; -const COMPLETE_ID = "test_delay_update_complete_webext@tests.mozilla.org"; -const DEFER_ID = "test_delay_update_defer_webext@tests.mozilla.org"; -const NOUPDATE_ID = "test_no_update_webext@tests.mozilla.org"; - -// Create and configure the HTTP server. -let testserver = createHttpServer(); -gPort = testserver.identity.primaryPort; -mapFile("/data/test_delay_updates_complete.json", testserver); -mapFile("/data/test_delay_updates_ignore.json", testserver); -mapFile("/data/test_delay_updates_defer.json", testserver); -mapFile("/data/test_no_update.json", testserver); -testserver.registerDirectory("/addons/", do_get_file("addons")); - -createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "42"); - -const { Management } = Components.utils.import("resource://gre/modules/Extension.jsm", {}); - -function promiseWebExtensionStartup() { - return new Promise(resolve => { - let listener = (event, extension) => { - Management.off("startup", listener); - resolve(extension); - }; - - Management.on("startup", listener); - }); -} - -// add-on registers upgrade listener, and ignores update. -add_task(function* delay_updates_ignore() { - startupManager(); - - let extension = ExtensionTestUtils.loadExtension({ - useAddonManager: "permanent", - manifest: { - "version": "1.0", - "applications": { - "gecko": { - "id": IGNORE_ID, - "update_url": `http://localhost:${gPort}/data/test_delay_updates_ignore.json`, - }, - }, - }, - background() { - browser.runtime.onUpdateAvailable.addListener(details => { - if (details) { - if (details.version) { - // This should be the version of the pending update. - browser.test.assertEq("2.0", details.version, "correct version"); - browser.test.notifyPass("delay"); - } - } else { - browser.test.fail("no details object passed"); - } - }); - browser.test.sendMessage("ready"); - }, - }, IGNORE_ID); - - yield Promise.all([extension.startup(), extension.awaitMessage("ready")]); - - let addon = yield promiseAddonByID(IGNORE_ID); - do_check_neq(addon, null); - do_check_eq(addon.version, "1.0"); - do_check_eq(addon.name, "Generated extension"); - do_check_true(addon.isCompatible); - do_check_false(addon.appDisabled); - do_check_true(addon.isActive); - do_check_eq(addon.type, "extension"); - - let update = yield promiseFindAddonUpdates(addon); - let install = update.updateAvailable; - - yield promiseCompleteAllInstalls([install]); - - do_check_eq(install.state, AddonManager.STATE_POSTPONED); - - // addon upgrade has been delayed - let addon_postponed = yield promiseAddonByID(IGNORE_ID); - do_check_neq(addon_postponed, null); - do_check_eq(addon_postponed.version, "1.0"); - do_check_eq(addon_postponed.name, "Generated extension"); - do_check_true(addon_postponed.isCompatible); - do_check_false(addon_postponed.appDisabled); - do_check_true(addon_postponed.isActive); - do_check_eq(addon_postponed.type, "extension"); - - yield extension.awaitFinish("delay"); - - // restarting allows upgrade to proceed - yield extension.markUnloaded(); - yield promiseRestartManager(); - - let addon_upgraded = yield promiseAddonByID(IGNORE_ID); - yield promiseWebExtensionStartup(); - - do_check_neq(addon_upgraded, null); - do_check_eq(addon_upgraded.version, "2.0"); - do_check_eq(addon_upgraded.name, "Delay Upgrade"); - do_check_true(addon_upgraded.isCompatible); - do_check_false(addon_upgraded.appDisabled); - do_check_true(addon_upgraded.isActive); - do_check_eq(addon_upgraded.type, "extension"); - - yield addon_upgraded.uninstall(); - yield promiseShutdownManager(); -}); - -// add-on registers upgrade listener, and allows update. -add_task(function* delay_updates_complete() { - startupManager(); - - let extension = ExtensionTestUtils.loadExtension({ - useAddonManager: "permanent", - manifest: { - "version": "1.0", - "applications": { - "gecko": { - "id": COMPLETE_ID, - "update_url": `http://localhost:${gPort}/data/test_delay_updates_complete.json`, - }, - }, - }, - background() { - browser.runtime.onUpdateAvailable.addListener(details => { - browser.test.notifyPass("reload"); - browser.runtime.reload(); - }); - browser.test.sendMessage("ready"); - }, - }, COMPLETE_ID); - - yield Promise.all([extension.startup(), extension.awaitMessage("ready")]); - - let addon = yield promiseAddonByID(COMPLETE_ID); - do_check_neq(addon, null); - do_check_eq(addon.version, "1.0"); - do_check_eq(addon.name, "Generated extension"); - do_check_true(addon.isCompatible); - do_check_false(addon.appDisabled); - do_check_true(addon.isActive); - do_check_eq(addon.type, "extension"); - - let update = yield promiseFindAddonUpdates(addon); - let install = update.updateAvailable; - - let promiseInstalled = promiseAddonEvent("onInstalled"); - yield promiseCompleteAllInstalls([install]); - - yield extension.awaitFinish("reload"); - - // addon upgrade has been allowed - let [addon_allowed] = yield promiseInstalled; - yield promiseWebExtensionStartup(); - - do_check_neq(addon_allowed, null); - do_check_eq(addon_allowed.version, "2.0"); - do_check_eq(addon_allowed.name, "Delay Upgrade"); - do_check_true(addon_allowed.isCompatible); - do_check_false(addon_allowed.appDisabled); - do_check_true(addon_allowed.isActive); - do_check_eq(addon_allowed.type, "extension"); - - if (stageDir.exists()) { - do_throw("Staging directory should not exist for formerly-postponed extension"); - } - - yield extension.markUnloaded(); - yield addon_allowed.uninstall(); - yield promiseShutdownManager(); -}); - -// add-on registers upgrade listener, initially defers update then allows upgrade -add_task(function* delay_updates_defer() { - startupManager(); - - let extension = ExtensionTestUtils.loadExtension({ - useAddonManager: "permanent", - manifest: { - "version": "1.0", - "applications": { - "gecko": { - "id": DEFER_ID, - "update_url": `http://localhost:${gPort}/data/test_delay_updates_defer.json`, - }, - }, - }, - background() { - browser.runtime.onUpdateAvailable.addListener(details => { - // Upgrade will only proceed when "allow" message received. - browser.test.onMessage.addListener(msg => { - if (msg == "allow") { - browser.test.notifyPass("allowed"); - browser.runtime.reload(); - } else { - browser.test.fail(`wrong message: ${msg}`); - } - }); - browser.test.sendMessage("truly ready"); - }); - browser.test.sendMessage("ready"); - }, - }, DEFER_ID); - - yield Promise.all([extension.startup(), extension.awaitMessage("ready")]); - - let addon = yield promiseAddonByID(DEFER_ID); - do_check_neq(addon, null); - do_check_eq(addon.version, "1.0"); - do_check_eq(addon.name, "Generated extension"); - do_check_true(addon.isCompatible); - do_check_false(addon.appDisabled); - do_check_true(addon.isActive); - do_check_eq(addon.type, "extension"); - - let update = yield promiseFindAddonUpdates(addon); - let install = update.updateAvailable; - - let promiseInstalled = promiseAddonEvent("onInstalled"); - yield promiseCompleteAllInstalls([install]); - - do_check_eq(install.state, AddonManager.STATE_POSTPONED); - - // upgrade is initially postponed - let addon_postponed = yield promiseAddonByID(DEFER_ID); - do_check_neq(addon_postponed, null); - do_check_eq(addon_postponed.version, "1.0"); - do_check_eq(addon_postponed.name, "Generated extension"); - do_check_true(addon_postponed.isCompatible); - do_check_false(addon_postponed.appDisabled); - do_check_true(addon_postponed.isActive); - do_check_eq(addon_postponed.type, "extension"); - - // add-on will not allow upgrade until message is received - yield extension.awaitMessage("truly ready"); - extension.sendMessage("allow"); - yield extension.awaitFinish("allowed"); - - // addon upgrade has been allowed - let [addon_allowed] = yield promiseInstalled; - yield promiseWebExtensionStartup(); - - do_check_neq(addon_allowed, null); - do_check_eq(addon_allowed.version, "2.0"); - do_check_eq(addon_allowed.name, "Delay Upgrade"); - do_check_true(addon_allowed.isCompatible); - do_check_false(addon_allowed.appDisabled); - do_check_true(addon_allowed.isActive); - do_check_eq(addon_allowed.type, "extension"); - - yield extension.markUnloaded(); - yield promiseRestartManager(); - - // restart changes nothing - addon_allowed = yield promiseAddonByID(DEFER_ID); - yield promiseWebExtensionStartup(); - - do_check_neq(addon_allowed, null); - do_check_eq(addon_allowed.version, "2.0"); - do_check_eq(addon_allowed.name, "Delay Upgrade"); - do_check_true(addon_allowed.isCompatible); - do_check_false(addon_allowed.appDisabled); - do_check_true(addon_allowed.isActive); - do_check_eq(addon_allowed.type, "extension"); - - yield addon_allowed.uninstall(); - yield promiseShutdownManager(); -}); - -// browser.runtime.reload() without a pending upgrade should just reload. -add_task(function* runtime_reload() { - startupManager(); - - let extension = ExtensionTestUtils.loadExtension({ - useAddonManager: "permanent", - manifest: { - "version": "1.0", - "applications": { - "gecko": { - "id": NOUPDATE_ID, - "update_url": `http://localhost:${gPort}/data/test_no_update.json`, - }, - }, - }, - background() { - browser.test.onMessage.addListener(msg => { - if (msg == "reload") { - browser.runtime.reload(); - } else { - browser.test.fail(`wrong message: ${msg}`); - } - }); - browser.test.sendMessage("ready"); - }, - }, NOUPDATE_ID); - - yield Promise.all([extension.startup(), extension.awaitMessage("ready")]); - - let addon = yield promiseAddonByID(NOUPDATE_ID); - do_check_neq(addon, null); - do_check_eq(addon.version, "1.0"); - do_check_eq(addon.name, "Generated extension"); - do_check_true(addon.isCompatible); - do_check_false(addon.appDisabled); - do_check_true(addon.isActive); - do_check_eq(addon.type, "extension"); - - yield promiseFindAddonUpdates(addon); - - extension.sendMessage("reload"); - // Wait for extension to restart, to make sure reload works. - yield promiseWebExtensionStartup(); - - addon = yield promiseAddonByID(NOUPDATE_ID); - do_check_neq(addon, null); - do_check_eq(addon.version, "1.0"); - do_check_eq(addon.name, "Generated extension"); - do_check_true(addon.isCompatible); - do_check_false(addon.appDisabled); - do_check_true(addon.isActive); - do_check_eq(addon.type, "extension"); - - yield extension.markUnloaded(); - yield addon.uninstall(); - yield promiseShutdownManager(); -}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_dependencies.js b/toolkit/mozapps/extensions/test/xpcshell/test_dependencies.js deleted file mode 100644 index 3afc03f84..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_dependencies.js +++ /dev/null @@ -1,144 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -const profileDir = gProfD.clone(); -profileDir.append("extensions"); - -createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1"); -startupManager(); - -const BOOTSTRAP = String.raw` - Components.utils.import("resource://gre/modules/Services.jsm"); - - function startup(data) { - Services.obs.notifyObservers(null, "test-addon-bootstrap-startup", data.id); - } - function shutdown(data) { - Services.obs.notifyObservers(null, "test-addon-bootstrap-shutdown", data.id); - } - function install() {} - function uninstall() {} -`; - -const ADDONS = [ - { - id: "addon1@dependency-test.mozilla.org", - dependencies: ["addon2@dependency-test.mozilla.org"], - }, - { - id: "addon2@dependency-test.mozilla.org", - dependencies: ["addon3@dependency-test.mozilla.org"], - }, - { - id: "addon3@dependency-test.mozilla.org", - }, - { - id: "addon4@dependency-test.mozilla.org", - }, - { - id: "addon5@dependency-test.mozilla.org", - dependencies: ["addon2@dependency-test.mozilla.org"], - }, -]; - -let addonFiles = []; - -let events = []; -add_task(function* setup() { - let startupObserver = (subject, topic, data) => { - events.push(["startup", data]); - }; - let shutdownObserver = (subject, topic, data) => { - events.push(["shutdown", data]); - }; - - Services.obs.addObserver(startupObserver, "test-addon-bootstrap-startup", false); - Services.obs.addObserver(shutdownObserver, "test-addon-bootstrap-shutdown", false); - do_register_cleanup(() => { - Services.obs.removeObserver(startupObserver, "test-addon-bootstrap-startup"); - Services.obs.removeObserver(shutdownObserver, "test-addon-bootstrap-shutdown"); - }); - - for (let addon of ADDONS) { - Object.assign(addon, { - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "1", - maxVersion: "1", - }], - version: "1.0", - name: addon.id, - bootstrap: true, - }); - - addonFiles.push(createTempXPIFile(addon, {"bootstrap.js": BOOTSTRAP})); - } -}); - -add_task(function*() { - deepEqual(events, [], "Should have no events"); - - yield promiseInstallAllFiles([addonFiles[3]]); - - deepEqual(events, [ - ["startup", ADDONS[3].id], - ]); - - events.length = 0; - - yield promiseInstallAllFiles([addonFiles[0]]); - deepEqual(events, [], "Should have no events"); - - yield promiseInstallAllFiles([addonFiles[1]]); - deepEqual(events, [], "Should have no events"); - - yield promiseInstallAllFiles([addonFiles[2]]); - - deepEqual(events, [ - ["startup", ADDONS[2].id], - ["startup", ADDONS[1].id], - ["startup", ADDONS[0].id], - ]); - - events.length = 0; - - yield promiseInstallAllFiles([addonFiles[2]]); - - deepEqual(events, [ - ["shutdown", ADDONS[0].id], - ["shutdown", ADDONS[1].id], - ["shutdown", ADDONS[2].id], - - ["startup", ADDONS[2].id], - ["startup", ADDONS[1].id], - ["startup", ADDONS[0].id], - ]); - - events.length = 0; - - yield promiseInstallAllFiles([addonFiles[4]]); - - deepEqual(events, [ - ["startup", ADDONS[4].id], - ]); - - events.length = 0; - - yield promiseRestartManager(); - - deepEqual(events, [ - ["shutdown", ADDONS[4].id], - ["shutdown", ADDONS[3].id], - ["shutdown", ADDONS[0].id], - ["shutdown", ADDONS[1].id], - ["shutdown", ADDONS[2].id], - - ["startup", ADDONS[2].id], - ["startup", ADDONS[1].id], - ["startup", ADDONS[0].id], - ["startup", ADDONS[3].id], - ["startup", ADDONS[4].id], - ]); -}); - diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_dictionary.js b/toolkit/mozapps/extensions/test/xpcshell/test_dictionary.js index f4b6a0535..c24b5a1b0 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_dictionary.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_dictionary.js @@ -39,7 +39,7 @@ mapFile("/data/test_dictionary.rdf", testserver); var HunspellEngine = { dictionaryDirs: [], listener: null, - + QueryInterface: function hunspell_qi(iid) { if (iid.equals(Components.interfaces.nsISupports) || iid.equals(Components.interfaces.nsIFactory) || @@ -89,7 +89,7 @@ var HunspellEngine = { Components.manager.nsIComponentRegistrar.registerFactory(this.classID, "Test hunspell", this.contractID, this); }, - + deactivate: function hunspell_deactivate() { Components.manager.nsIComponentRegistrar.unregisterFactory(this.classID, this); Components.manager.nsIComponentRegistrar.registerFactory(this.origClassID, @@ -175,16 +175,6 @@ function check_test_1() { let dir = do_get_addon_root_uri(profileDir, "ab-CD@dictionaries.addons.mozilla.org"); - let chromeReg = AM_Cc["@mozilla.org/chrome/chrome-registry;1"]. - getService(AM_Ci.nsIChromeRegistry); - try { - chromeReg.convertChromeURL(NetUtil.newURI("chrome://dict/content/dict.xul")); - do_throw("Chrome manifest should not have been registered"); - } - catch (e) { - // Expected the chrome url to not be registered - } - AddonManager.getAddonsWithOperationsByTypes(null, function(list) { do_check_eq(list.length, 0); @@ -348,7 +338,7 @@ function run_test_8() { let dir = profileDir.clone(); dir.append("ab-CD@dictionaries.addons.mozilla.org"); - dir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0o755); + dir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0755); let zip = AM_Cc["@mozilla.org/libjar/zip-reader;1"]. createInstance(AM_Ci.nsIZipReader); zip.open(do_get_addon("test_dictionary")); @@ -356,7 +346,7 @@ function run_test_8() { zip.extract("install.rdf", dir); dir = dir.parent; dir.append("dictionaries"); - dir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0o755); + dir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0755); dir.append("ab-CD.dic"); zip.extract("dictionaries/ab-CD.dic", dir); zip.close(); @@ -401,7 +391,7 @@ function run_test_12() { let dir = profileDir.clone(); dir.append("ab-CD@dictionaries.addons.mozilla.org"); - dir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0o755); + dir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0755); let zip = AM_Cc["@mozilla.org/libjar/zip-reader;1"]. createInstance(AM_Ci.nsIZipReader); zip.open(do_get_addon("test_dictionary")); @@ -409,7 +399,7 @@ function run_test_12() { zip.extract("install.rdf", dir); dir = dir.parent; dir.append("dictionaries"); - dir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0o755); + dir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0755); dir.append("ab-CD.dic"); zip.extract("dictionaries/ab-CD.dic", dir); zip.close(); @@ -452,10 +442,10 @@ function run_test_16() { startupManager(false); AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", - callback_soon(function(b1_2) { + callback_soon(function(b1) { // Should still be stopped do_check_false(HunspellEngine.isDictionaryEnabled("ab-CD.dic")); - do_check_false(b1_2.isActive); + do_check_false(b1.isActive); shutdownManager(); gAppInfo.inSafeMode = false; @@ -464,8 +454,8 @@ function run_test_16() { // Should have started do_check_true(HunspellEngine.isDictionaryEnabled("ab-CD.dic")); - AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1_3) { - b1_3.uninstall(); + AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1) { + b1.uninstall(); do_execute_soon(run_test_17); }); @@ -481,7 +471,7 @@ function run_test_17() { let dir = userExtDir.clone(); dir.append("ab-CD@dictionaries.addons.mozilla.org"); - dir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0o755); + dir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0755); let zip = AM_Cc["@mozilla.org/libjar/zip-reader;1"]. createInstance(AM_Ci.nsIZipReader); zip.open(do_get_addon("test_dictionary")); @@ -489,7 +479,7 @@ function run_test_17() { zip.extract("install.rdf", dir); dir = dir.parent; dir.append("dictionaries"); - dir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0o755); + dir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0755); dir.append("ab-CD.dic"); zip.extract("dictionaries/ab-CD.dic", dir); zip.close(); @@ -583,8 +573,8 @@ function check_test_23() { do_check_eq(list.length, 0); restartManager(); - AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1_2) { - b1_2.uninstall(); + AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1) { + b1.uninstall(); do_execute_soon(run_test_25); }); })); @@ -617,11 +607,11 @@ function run_test_25() { do_check_false(HunspellEngine.isDictionaryEnabled("ab-CD.dic")); - AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1_2) { - do_check_neq(b1_2, null); - do_check_eq(b1_2.version, "2.0"); - do_check_true(b1_2.isActive); - do_check_eq(b1_2.pendingOperations, AddonManager.PENDING_NONE); + AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "2.0"); + do_check_true(b1.isActive); + do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE); do_execute_soon(run_test_26); }); @@ -650,14 +640,14 @@ function run_test_26() { do_check_true(HunspellEngine.isDictionaryEnabled("ab-CD.dic")); - AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1_2) { - do_check_neq(b1_2, null); - do_check_eq(b1_2.version, "1.0"); - do_check_true(b1_2.isActive); - do_check_eq(b1_2.pendingOperations, AddonManager.PENDING_NONE); + AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "1.0"); + do_check_true(b1.isActive); + do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE); HunspellEngine.deactivate(); - b1_2.uninstall(); + b1.uninstall(); do_execute_soon(run_test_27); }); })); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_distribution.js b/toolkit/mozapps/extensions/test/xpcshell/test_distribution.js index 720b454cc..9f5bfacca 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_distribution.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_distribution.js @@ -68,7 +68,7 @@ function setOldModificationTime() { extension.append("addon1@tests.mozilla.org"); else extension.append("addon1@tests.mozilla.org.xpi"); - setExtensionModifiedTime(extension, Date.now() - MAKE_FILE_OLD_DIFFERENCE); + setExtensionModifiedTime(extension, Date.now - 10000); startupManager(false); } @@ -78,11 +78,9 @@ function run_test() { run_test_1(); } -// Tests that on the first startup the add-on gets installed, with now as the -// profile modifiedTime. +// Tests that on the first startup the add-on gets installed function run_test_1() { - let extension = writeInstallRDFForExtension(addon1_1, distroDir); - setExtensionModifiedTime(extension, Date.now() - MAKE_FILE_OLD_DIFFERENCE); + writeInstallRDFForExtension(addon1_1, distroDir); startupManager(); @@ -93,15 +91,6 @@ function run_test_1() { do_check_eq(a1.scope, AddonManager.SCOPE_PROFILE); do_check_false(a1.foreignInstall); - // Modification time should be updated when the addon is copied to the - // profile. - let testURI = a1.getResourceURI(TEST_UNPACKED ? "install.rdf" : ""); - let testFile = testURI.QueryInterface(Components.interfaces.nsIFileURL).file; - - do_check_true(testFile.exists()); - let difference = testFile.lastModifiedTime - Date.now(); - do_check_true(Math.abs(difference) < MAX_TIME_DIFFERENCE); - do_execute_soon(run_test_2); }); } @@ -165,8 +154,8 @@ function run_test_5() { restartManager(); - AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1_2) { - do_check_eq(a1_2, null); + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_eq(a1, null); do_execute_soon(run_test_6); }); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_dss.js b/toolkit/mozapps/extensions/test/xpcshell/test_dss.js index b408cc9c7..7b171212a 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_dss.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_dss.js @@ -6,7 +6,7 @@ Components.utils.import("resource://gre/modules/NetUtil.jsm"); // using a dynamic port in the addon metadata Components.utils.import("resource://testing-common/httpd.js"); -var gServer = new HttpServer(); +let gServer = new HttpServer(); gServer.start(-1); gPort = gServer.identity.primaryPort; diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_duplicateplugins.js b/toolkit/mozapps/extensions/test/xpcshell/test_duplicateplugins.js index 4d1848ea4..bad560306 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_duplicateplugins.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_duplicateplugins.js @@ -2,9 +2,7 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -Components.utils.import("resource://testing-common/MockRegistrar.jsm"); - -var Ci = Components.interfaces; +const Ci = Components.interfaces; // This verifies that duplicate plugins are coalesced and maintain their ID // across restarts. @@ -15,9 +13,7 @@ var PLUGINS = [{ version: "1", blocklisted: false, enabledState: Ci.nsIPluginTag.STATE_ENABLED, - get disabled() { - return this.enabledState == Ci.nsIPluginTag.STATE_DISABLED; - }, + get disabled() this.enabledState == Ci.nsIPluginTag.STATE_DISABLED, filename: "/home/mozilla/.plugins/dupplugin1.so" }, { name: "Duplicate Plugin 1", @@ -25,9 +21,8 @@ var PLUGINS = [{ version: "1", blocklisted: false, enabledState: Ci.nsIPluginTag.STATE_ENABLED, - get disabled() { - return this.enabledState == Ci.nsIPluginTag.STATE_DISABLED; - }, + get disabled() this.enabledState == Ci.nsIPluginTag.STATE_DISABLED, + filename: "", filename: "/usr/lib/plugins/dupplugin1.so" }, { name: "Duplicate Plugin 2", @@ -35,9 +30,7 @@ var PLUGINS = [{ version: "1", blocklisted: false, enabledState: Ci.nsIPluginTag.STATE_ENABLED, - get disabled() { - return this.enabledState == Ci.nsIPluginTag.STATE_DISABLED; - }, + get disabled() this.enabledState == Ci.nsIPluginTag.STATE_DISABLED, filename: "/home/mozilla/.plugins/dupplugin2.so" }, { name: "Duplicate Plugin 2", @@ -45,9 +38,8 @@ var PLUGINS = [{ version: "1", blocklisted: false, enabledState: Ci.nsIPluginTag.STATE_ENABLED, - get disabled() { - return this.enabledState == Ci.nsIPluginTag.STATE_DISABLED; - }, + get disabled() this.enabledState == Ci.nsIPluginTag.STATE_DISABLED, + filename: "", filename: "/usr/lib/plugins/dupplugin2.so" }, { name: "Non-duplicate Plugin", // 3 @@ -55,9 +47,7 @@ var PLUGINS = [{ version: "1", blocklisted: false, enabledState: Ci.nsIPluginTag.STATE_ENABLED, - get disabled() { - return this.enabledState == Ci.nsIPluginTag.STATE_DISABLED; - }, + get disabled() this.enabledState == Ci.nsIPluginTag.STATE_DISABLED, filename: "/home/mozilla/.plugins/dupplugin3.so" }, { name: "Non-duplicate Plugin", // 4 @@ -65,9 +55,8 @@ var PLUGINS = [{ version: "1", blocklisted: false, enabledState: Ci.nsIPluginTag.STATE_ENABLED, - get disabled() { - return this.enabledState == Ci.nsIPluginTag.STATE_DISABLED; - }, + get disabled() this.enabledState == Ci.nsIPluginTag.STATE_DISABLED, + filename: "", filename: "/usr/lib/plugins/dupplugin4.so" }, { name: "Another Non-duplicate Plugin", // 5 @@ -75,9 +64,7 @@ var PLUGINS = [{ version: "1", blocklisted: false, enabledState: Ci.nsIPluginTag.STATE_ENABLED, - get disabled() { - return this.enabledState == Ci.nsIPluginTag.STATE_DISABLED; - }, + get disabled() this.enabledState == Ci.nsIPluginTag.STATE_DISABLED, filename: "/home/mozilla/.plugins/dupplugin5.so" }]; @@ -92,12 +79,23 @@ var PluginHost = { if (iid.equals(Components.interfaces.nsIPluginHost) || iid.equals(Components.interfaces.nsISupports)) return this; - + throw Components.results.NS_ERROR_NO_INTERFACE; } } -MockRegistrar.register("@mozilla.org/plugin/host;1", PluginHost); +var PluginHostFactory = { + createInstance: function (outer, iid) { + if (outer != null) + throw Components.results.NS_ERROR_NO_AGGREGATION; + return PluginHost.QueryInterface(iid); + } +}; + +var registrar = Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar); +registrar.registerFactory(Components.ID("{721c3e73-969e-474b-a6dc-059fd288c428}"), + "Fake Plugin Host", + "@mozilla.org/plugin/host;1", PluginHostFactory); var gPluginIDs = [null, null, null, null, null]; @@ -176,10 +174,10 @@ function run_test_3() { [PLUGINS[0], PLUGINS[1]] = [PLUGINS[1], PLUGINS[0]]; restartManager(); - AddonManager.getAddonByID(gPluginIDs[0], function(p_2) { - do_check_neq(p_2, null); - do_check_eq(p_2.name, "Duplicate Plugin 1"); - do_check_eq(p_2.description, "A duplicate plugin"); + AddonManager.getAddonByID(gPluginIDs[0], function(p) { + do_check_neq(p, null); + do_check_eq(p.name, "Duplicate Plugin 1"); + do_check_eq(p.description, "A duplicate plugin"); do_execute_soon(do_test_finished); }); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_e10s_restartless.js b/toolkit/mozapps/extensions/test/xpcshell/test_e10s_restartless.js deleted file mode 100644 index 1a3a0e747..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_e10s_restartless.js +++ /dev/null @@ -1,429 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -const ID = "bootstrap1@tests.mozilla.org"; -const ID2 = "bootstrap2@tests.mozilla.org"; - -const APP_STARTUP = 1; -const ADDON_INSTALL = 5; - -function getStartupReason(id) { - let info = BootstrapMonitor.started.get(id); - return info ? info.reason : undefined; -} - -BootstrapMonitor.init(); - -createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); - -startupManager(); - -function* check_normal() { - let install = yield new Promise(resolve => AddonManager.getInstallForFile(do_get_addon("test_bootstrap1_1"), resolve)); - yield promiseCompleteAllInstalls([install]); - do_check_eq(install.state, AddonManager.STATE_INSTALLED); - do_check_false(hasFlag(install.addon.pendingOperations, AddonManager.PENDING_INSTALL)); - - BootstrapMonitor.checkAddonInstalled(ID); - BootstrapMonitor.checkAddonStarted(ID); - - let addon = yield promiseAddonByID(ID); - do_check_eq(addon, install.addon); - - do_check_false(hasFlag(addon.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_DISABLE)); - addon.userDisabled = true; - BootstrapMonitor.checkAddonNotStarted(ID); - do_check_false(addon.isActive); - do_check_false(hasFlag(addon.pendingOperations, AddonManager.PENDING_DISABLE)); - - do_check_false(hasFlag(addon.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_ENABLE)); - addon.userDisabled = false; - BootstrapMonitor.checkAddonStarted(ID); - do_check_true(addon.isActive); - do_check_false(hasFlag(addon.pendingOperations, AddonManager.PENDING_ENABLE)); - - do_check_false(hasFlag(addon.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_UNINSTALL)); - addon.uninstall(); - BootstrapMonitor.checkAddonNotStarted(ID); - BootstrapMonitor.checkAddonNotInstalled(ID); - - yield promiseRestartManager(); -} - -// Installing the add-on normally doesn't require a restart -add_task(function*() { - gAppInfo.browserTabsRemoteAutostart = false; - Services.prefs.setBoolPref("extensions.e10sBlocksEnabling", false); - - yield check_normal(); -}); - -// Enabling the pref doesn't change anything -add_task(function*() { - gAppInfo.browserTabsRemoteAutostart = false; - Services.prefs.setBoolPref("extensions.e10sBlocksEnabling", true); - - yield check_normal(); -}); - -// Default e10s doesn't change anything -add_task(function*() { - gAppInfo.browserTabsRemoteAutostart = true; - Services.prefs.setBoolPref("extensions.e10sBlocksEnabling", false); - - yield check_normal(); -}); - -// Pref and e10s blocks install -add_task(function*() { - gAppInfo.browserTabsRemoteAutostart = true; - Services.prefs.setBoolPref("extensions.e10sBlocksEnabling", true); - - let install = yield new Promise(resolve => AddonManager.getInstallForFile(do_get_addon("test_bootstrap1_1"), resolve)); - yield promiseCompleteAllInstalls([install]); - do_check_eq(install.state, AddonManager.STATE_INSTALLED); - do_check_true(hasFlag(install.addon.pendingOperations, AddonManager.PENDING_INSTALL)); - - let addon = yield promiseAddonByID(ID); - do_check_eq(addon, null); - - yield promiseRestartManager(); - - BootstrapMonitor.checkAddonInstalled(ID); - BootstrapMonitor.checkAddonStarted(ID); - do_check_eq(getStartupReason(ID), ADDON_INSTALL); - - addon = yield promiseAddonByID(ID); - do_check_neq(addon, null); - - do_check_false(hasFlag(addon.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_DISABLE)); - addon.userDisabled = true; - BootstrapMonitor.checkAddonNotStarted(ID); - do_check_false(addon.isActive); - do_check_false(hasFlag(addon.pendingOperations, AddonManager.PENDING_DISABLE)); - - do_check_true(hasFlag(addon.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_ENABLE)); - addon.userDisabled = false; - BootstrapMonitor.checkAddonNotStarted(ID); - do_check_false(addon.isActive); - do_check_true(hasFlag(addon.pendingOperations, AddonManager.PENDING_ENABLE)); - - yield promiseRestartManager(); - - addon = yield promiseAddonByID(ID); - do_check_neq(addon, null); - - do_check_true(addon.isActive); - BootstrapMonitor.checkAddonStarted(ID); - - do_check_false(hasFlag(addon.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_UNINSTALL)); - addon.uninstall(); - BootstrapMonitor.checkAddonNotStarted(ID); - BootstrapMonitor.checkAddonNotInstalled(ID); - - yield promiseRestartManager(); -}); - -add_task(function*() { - gAppInfo.browserTabsRemoteAutostart = true; - Services.prefs.setBoolPref("extensions.e10sBlocksEnabling", true); - - let install = yield new Promise(resolve => AddonManager.getInstallForFile(do_get_addon("test_bootstrap1_1"), resolve)); - yield promiseCompleteAllInstalls([install]); - do_check_eq(install.state, AddonManager.STATE_INSTALLED); - do_check_true(hasFlag(install.addon.pendingOperations, AddonManager.PENDING_INSTALL)); - - let addon = yield promiseAddonByID(ID); - do_check_eq(addon, null); - - yield promiseRestartManager(); - - // After install and restart we should block. - let blocked = Services.prefs.getBoolPref("extensions.e10sBlockedByAddons"); - do_check_true(blocked); - - BootstrapMonitor.checkAddonInstalled(ID); - BootstrapMonitor.checkAddonStarted(ID); - do_check_eq(getStartupReason(ID), ADDON_INSTALL); - - addon = yield promiseAddonByID(ID); - do_check_neq(addon, null); - - do_check_false(hasFlag(addon.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_DISABLE)); - addon.userDisabled = true; - BootstrapMonitor.checkAddonNotStarted(ID); - do_check_false(addon.isActive); - do_check_false(hasFlag(addon.pendingOperations, AddonManager.PENDING_DISABLE)); - do_check_true(hasFlag(addon.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_ENABLE)); - - yield promiseRestartManager(); - - // After disable and restart we should not block. - blocked = Services.prefs.getBoolPref("extensions.e10sBlockedByAddons"); - do_check_false(blocked); - - addon = yield promiseAddonByID(ID); - addon.userDisabled = false; - BootstrapMonitor.checkAddonNotStarted(ID); - do_check_false(addon.isActive); - do_check_true(hasFlag(addon.pendingOperations, AddonManager.PENDING_ENABLE)); - - yield promiseRestartManager(); - - // After re-enable and restart we should block. - blocked = Services.prefs.getBoolPref("extensions.e10sBlockedByAddons"); - do_check_true(blocked); - - addon = yield promiseAddonByID(ID); - do_check_neq(addon, null); - - do_check_true(addon.isActive); - BootstrapMonitor.checkAddonStarted(ID); - // This should probably be ADDON_ENABLE, but its not easy to make - // that happen. See bug 1304392 for discussion. - do_check_eq(getStartupReason(ID), APP_STARTUP); - - do_check_false(hasFlag(addon.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_UNINSTALL)); - addon.uninstall(); - BootstrapMonitor.checkAddonNotStarted(ID); - BootstrapMonitor.checkAddonNotInstalled(ID); - - yield promiseRestartManager(); - - // After uninstall and restart we should not block. - blocked = Services.prefs.getBoolPref("extensions.e10sBlockedByAddons"); - do_check_false(blocked); - - restartManager(); -}); - -add_task(function*() { - gAppInfo.browserTabsRemoteAutostart = true; - Services.prefs.setBoolPref("extensions.e10sBlocksEnabling", true); - - let install1 = yield new Promise(resolve => AddonManager.getInstallForFile(do_get_addon("test_bootstrap1_1"), resolve)); - let install2 = yield new Promise(resolve => AddonManager.getInstallForFile(do_get_addon("test_bootstrap2_1"), resolve)); - yield promiseCompleteAllInstalls([install1, install2]); - do_check_eq(install1.state, AddonManager.STATE_INSTALLED); - do_check_eq(install2.state, AddonManager.STATE_INSTALLED); - do_check_true(hasFlag(install1.addon.pendingOperations, AddonManager.PENDING_INSTALL)); - do_check_true(hasFlag(install2.addon.pendingOperations, AddonManager.PENDING_INSTALL)); - - let addon = yield promiseAddonByID(ID); - let addon2 = yield promiseAddonByID(ID2); - - do_check_eq(addon, null); - do_check_eq(addon2, null); - - yield promiseRestartManager(); - - // After install and restart we should block. - let blocked = Services.prefs.getBoolPref("extensions.e10sBlockedByAddons"); - do_check_true(blocked); - - BootstrapMonitor.checkAddonInstalled(ID); - BootstrapMonitor.checkAddonStarted(ID); - do_check_eq(getStartupReason(ID), ADDON_INSTALL); - - BootstrapMonitor.checkAddonInstalled(ID2); - BootstrapMonitor.checkAddonStarted(ID2); - do_check_eq(getStartupReason(ID2), ADDON_INSTALL); - - addon = yield promiseAddonByID(ID); - do_check_neq(addon, null); - addon2 = yield promiseAddonByID(ID2); - do_check_neq(addon2, null); - - do_check_false(hasFlag(addon.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_DISABLE)); - addon.userDisabled = true; - BootstrapMonitor.checkAddonNotStarted(ID); - do_check_false(addon.isActive); - do_check_false(hasFlag(addon.pendingOperations, AddonManager.PENDING_DISABLE)); - do_check_true(hasFlag(addon.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_ENABLE)); - - yield promiseRestartManager(); - - // After disable one addon and restart we should block. - blocked = Services.prefs.getBoolPref("extensions.e10sBlockedByAddons"); - do_check_true(blocked); - - addon2 = yield promiseAddonByID(ID2); - - do_check_false(hasFlag(addon2.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_DISABLE)); - addon2.userDisabled = true; - BootstrapMonitor.checkAddonNotStarted(ID2); - do_check_false(addon2.isActive); - do_check_false(hasFlag(addon2.pendingOperations, AddonManager.PENDING_DISABLE)); - do_check_true(hasFlag(addon2.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_ENABLE)); - - yield promiseRestartManager(); - - // After disable both addons and restart we should not block. - blocked = Services.prefs.getBoolPref("extensions.e10sBlockedByAddons"); - do_check_false(blocked); - - addon = yield promiseAddonByID(ID); - addon.userDisabled = false; - BootstrapMonitor.checkAddonNotStarted(ID); - do_check_false(addon.isActive); - do_check_true(hasFlag(addon.pendingOperations, AddonManager.PENDING_ENABLE)); - - yield promiseRestartManager(); - - // After re-enable one addon and restart we should block. - blocked = Services.prefs.getBoolPref("extensions.e10sBlockedByAddons"); - do_check_true(blocked); - - addon = yield promiseAddonByID(ID); - do_check_neq(addon, null); - - do_check_true(addon.isActive); - BootstrapMonitor.checkAddonStarted(ID); - // Bug 1304392 again (see comment above) - do_check_eq(getStartupReason(ID), APP_STARTUP); - - do_check_false(hasFlag(addon.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_UNINSTALL)); - addon.uninstall(); - BootstrapMonitor.checkAddonNotStarted(ID); - BootstrapMonitor.checkAddonNotInstalled(ID); - - yield promiseRestartManager(); - - // After uninstall the only enabled addon and restart we should not block. - blocked = Services.prefs.getBoolPref("extensions.e10sBlockedByAddons"); - do_check_false(blocked); - - addon2 = yield promiseAddonByID(ID2); - addon2.uninstall(); - - restartManager(); -}); - -// Check that the rollout policy sets work as expected -add_task(function*() { - gAppInfo.browserTabsRemoteAutostart = true; - Services.prefs.setBoolPref("extensions.e10sBlocksEnabling", true); - Services.prefs.setCharPref("extensions.e10s.rollout.policy", "xpcshell-test"); - - // Both 'bootstrap1' and 'bootstrap2' addons are listed in the allowed policy - // set, so they should install and start normally. - yield check_normal(); - - // Check that the two add-ons can be installed together correctly as - // check_normal() only perform checks on bootstrap1. - let install1 = yield new Promise(resolve => AddonManager.getInstallForFile(do_get_addon("test_bootstrap1_1"), resolve)); - let install2 = yield new Promise(resolve => AddonManager.getInstallForFile(do_get_addon("test_bootstrap2_1"), resolve)); - yield promiseCompleteAllInstalls([install1, install2]); - - do_check_eq(install1.state, AddonManager.STATE_INSTALLED); - do_check_eq(install2.state, AddonManager.STATE_INSTALLED); - do_check_false(hasFlag(install1.addon.pendingOperations, AddonManager.PENDING_INSTALL)); - do_check_false(hasFlag(install2.addon.pendingOperations, AddonManager.PENDING_INSTALL)); - - let addon = yield promiseAddonByID(ID); - let addon2 = yield promiseAddonByID(ID2); - - do_check_neq(addon, null); - do_check_neq(addon2, null); - - BootstrapMonitor.checkAddonInstalled(ID); - BootstrapMonitor.checkAddonStarted(ID); - - BootstrapMonitor.checkAddonInstalled(ID2); - BootstrapMonitor.checkAddonStarted(ID2); - - yield promiseRestartManager(); - - // After install and restart e10s should not be blocked. - let blocked = Services.prefs.getBoolPref("extensions.e10sBlockedByAddons"); - do_check_false(blocked); - - // Check that adding bootstrap2 to the blocklist will trigger a disable of e10s. - Services.prefs.setCharPref("extensions.e10s.rollout.blocklist", ID2); - blocked = Services.prefs.getBoolPref("extensions.e10sBlockedByAddons"); - do_check_true(blocked); - - yield promiseRestartManager(); - - // Check that after restarting, e10s continues to be blocked. - blocked = Services.prefs.getBoolPref("extensions.e10sBlockedByAddons"); - do_check_true(blocked); - - // Check that uninstalling bootstrap2 (which is in the blocklist) will - // cause e10s to be re-enabled. - addon2 = yield promiseAddonByID(ID2); - do_check_false(hasFlag(addon2.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_UNINSTALL)); - addon2.uninstall(); - BootstrapMonitor.checkAddonNotStarted(ID2); - BootstrapMonitor.checkAddonNotInstalled(ID2); - - yield promiseRestartManager(); - - // After uninstall the blocklisted addon and restart we should not block. - blocked = Services.prefs.getBoolPref("extensions.e10sBlockedByAddons"); - do_check_false(blocked); - - - // Let's perform similar checks again, now that bootstrap2 is in the blocklist. - // The bootstrap1 add-on should install and start correctly, but bootstrap2 should not. - addon = yield promiseAddonByID(ID); - addon.uninstall(); - BootstrapMonitor.checkAddonNotStarted(ID); - BootstrapMonitor.checkAddonNotInstalled(ID); - - yield promiseRestartManager(); - - install1 = yield new Promise(resolve => AddonManager.getInstallForFile(do_get_addon("test_bootstrap1_1"), resolve)); - install2 = yield new Promise(resolve => AddonManager.getInstallForFile(do_get_addon("test_bootstrap2_1"), resolve)); - yield promiseCompleteAllInstalls([install1, install2]); - - do_check_eq(install1.state, AddonManager.STATE_INSTALLED); - do_check_eq(install2.state, AddonManager.STATE_INSTALLED); - do_check_false(hasFlag(install1.addon.pendingOperations, AddonManager.PENDING_INSTALL)); - do_check_true(hasFlag(install2.addon.pendingOperations, AddonManager.PENDING_INSTALL)); - - addon = yield promiseAddonByID(ID); - addon2 = yield promiseAddonByID(ID2); - - do_check_neq(addon, null); - do_check_eq(addon2, null); - - BootstrapMonitor.checkAddonInstalled(ID); - BootstrapMonitor.checkAddonStarted(ID); - - BootstrapMonitor.checkAddonNotInstalled(ID2); - BootstrapMonitor.checkAddonNotStarted(ID2); - - yield promiseRestartManager(); - - blocked = Services.prefs.getBoolPref("extensions.e10sBlockedByAddons"); - do_check_true(blocked); - - // Clean-up - addon = yield promiseAddonByID(ID); - addon2 = yield promiseAddonByID(ID2); - - addon.uninstall(); - BootstrapMonitor.checkAddonNotStarted(ID); - BootstrapMonitor.checkAddonNotInstalled(ID); - - addon2.uninstall(); - BootstrapMonitor.checkAddonNotStarted(ID2); - BootstrapMonitor.checkAddonNotInstalled(ID2); - - Services.prefs.clearUserPref("extensions.e10s.rollout.policy"); - Services.prefs.clearUserPref("extensions.e10s.rollout.blocklist"); - - yield promiseRestartManager(); -}); - -// The hotfix is unaffected -add_task(function*() { - gAppInfo.browserTabsRemoteAutostart = true; - Services.prefs.setBoolPref("extensions.e10sBlocksEnabling", true); - Services.prefs.setCharPref("extensions.hotfix.id", ID); - Services.prefs.setBoolPref("extensions.hotfix.cert.checkAttributes", false); - - yield check_normal(); -}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_error.js b/toolkit/mozapps/extensions/test/xpcshell/test_error.js index 11a465b55..2184399e2 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_error.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_error.js @@ -66,7 +66,7 @@ function run_test_4() { } // Checks that a file that doesn't exist shows an error -function run_test_5() { +function run_test_4() { let file = do_get_file("data"); file.append("missing.xpi"); AddonManager.getInstallForFile(file, function(install) { @@ -74,12 +74,12 @@ function run_test_5() { do_check_eq(install.state, AddonManager.STATE_DOWNLOAD_FAILED); do_check_eq(install.error, AddonManager.ERROR_NETWORK_FAILURE); - run_test_6(); + run_test_5(); }); } // Checks that an add-on with an illegal ID shows an error -function run_test_6() { +function run_test_5() { AddonManager.getInstallForFile(do_get_addon("test_bug567173"), function(install) { do_check_neq(install, null); do_check_eq(install.state, AddonManager.STATE_DOWNLOAD_FAILED); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_experiment.js b/toolkit/mozapps/extensions/test/xpcshell/test_experiment.js index 3dcd83da8..25172749d 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_experiment.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_experiment.js @@ -1,131 +1,104 @@ /* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ -var scope = Components.utils.import("resource://gre/modules/addons/XPIProvider.jsm"); +let scope = Components.utils.import("resource://gre/modules/addons/XPIProvider.jsm"); const XPIProvider = scope.XPIProvider; -const ID = "experiment1@tests.mozilla.org"; - -var gIsNightly = false; function run_test() { - BootstrapMonitor.init(); createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); startupManager(); - gIsNightly = isNightlyChannel(); - run_next_test(); } -add_task(function* test_experiment() { - BootstrapMonitor.checkAddonNotInstalled(ID); - BootstrapMonitor.checkAddonNotStarted(ID); - - yield promiseInstallAllFiles([do_get_addon("test_experiment1")]); - - BootstrapMonitor.checkAddonInstalled(ID, "1.0"); - BootstrapMonitor.checkAddonNotStarted(ID); - - let addon = yield promiseAddonByID(ID); - Assert.ok(addon, "Addon is found."); - - Assert.ok(addon.userDisabled, "Experiments are userDisabled by default."); - Assert.ok(!addon.appDisabled, "Experiments are not appDisabled by compatibility."); - Assert.equal(addon.isActive, false, "Add-on is not active."); - Assert.equal(addon.updateURL, null, "No updateURL for experiments."); - Assert.equal(addon.applyBackgroundUpdates, AddonManager.AUTOUPDATE_DISABLE, - "Background updates are disabled."); - Assert.equal(addon.permissions, AddonManager.PERM_CAN_UNINSTALL + AddonManager.PERM_CAN_ENABLE, - "Permissions are minimal."); - Assert.ok(!(addon.pendingOperations & AddonManager.PENDING_ENABLE), - "Should not be pending enable"); - Assert.ok(!(addon.pendingOperations & AddonManager.PENDING_DISABLE), - "Should not be pending disable"); - - // Setting applyBackgroundUpdates should not work. - addon.applyBackgroundUpdates = AddonManager.AUTOUPDATE_ENABLE; - Assert.equal(addon.applyBackgroundUpdates, AddonManager.AUTOUPDATE_DISABLE, - "Setting applyBackgroundUpdates shouldn't do anything."); - - let noCompatibleCalled = false; - let noUpdateCalled = false; - let finishedCalled = false; - - let listener = { - onNoCompatibilityUpdateAvailable: () => { noCompatibleCalled = true; }, - onNoUpdateAvailable: () => { noUpdateCalled = true; }, - onUpdateFinished: () => { finishedCalled = true; }, - }; - - addon.findUpdates(listener, "testing", null, null); - Assert.ok(noCompatibleCalled, "Listener called."); - Assert.ok(noUpdateCalled, "Listener called."); - Assert.ok(finishedCalled, "Listener called."); +add_test(function test_experiment() { + AddonManager.getInstallForFile(do_get_addon("test_experiment1"), (install) => { + completeAllInstalls([install], () => { + AddonManager.getAddonByID("experiment1@tests.mozilla.org", (addon) => { + Assert.ok(addon, "Addon is found."); + + Assert.ok(addon.userDisabled, "Experiments are userDisabled by default."); + Assert.equal(addon.isActive, false, "Add-on is not active."); + Assert.equal(addon.updateURL, null, "No updateURL for experiments."); + Assert.equal(addon.applyBackgroundUpdates, AddonManager.AUTOUPDATE_DISABLE, + "Background updates are disabled."); + Assert.equal(addon.permissions, AddonManager.PERM_CAN_UNINSTALL, + "Permissions are minimal."); + Assert.ok(!(addon.pendingOperations & AddonManager.PENDING_ENABLE), + "Should not be pending enable"); + Assert.ok(!(addon.pendingOperations & AddonManager.PENDING_DISABLE), + "Should not be pending disable"); + + // Setting applyBackgroundUpdates should not work. + addon.applyBackgroundUpdates = AddonManager.AUTOUPDATE_ENABLE; + Assert.equal(addon.applyBackgroundUpdates, AddonManager.AUTOUPDATE_DISABLE, + "Setting applyBackgroundUpdates shouldn't do anything."); + + let noCompatibleCalled = false; + let noUpdateCalled = false; + let finishedCalled = false; + + let listener = { + onNoCompatibilityUpdateAvailable: () => { noCompatibleCalled = true; }, + onNoUpdateAvailable: () => { noUpdateCalled = true; }, + onUpdateFinished: () => { finishedCalled = true; }, + }; + + addon.findUpdates(listener, "testing", null, null); + Assert.ok(noCompatibleCalled, "Listener called."); + Assert.ok(noUpdateCalled, "Listener called."); + Assert.ok(finishedCalled, "Listener called."); + + run_next_test(); + }); + }); + }); }); // Changes to userDisabled should not be persisted to the database. -add_task(function* test_userDisabledNotPersisted() { - let addon = yield promiseAddonByID(ID); - Assert.ok(addon, "Add-on is found."); - Assert.ok(addon.userDisabled, "Add-on is user disabled."); - - let promise = promiseAddonEvent("onEnabled"); - addon.userDisabled = false; - let [addon2] = yield promise; - - BootstrapMonitor.checkAddonInstalled(ID, "1.0"); - BootstrapMonitor.checkAddonStarted(ID, "1.0"); - - Assert.equal(addon2.id, addon.id, "Changed add-on matches expected."); - Assert.equal(addon2.userDisabled, false, "Add-on is no longer user disabled."); - Assert.ok(addon2.isActive, "Add-on is active."); - - Assert.ok(ID in XPIProvider.bootstrappedAddons, - "Experiment add-on listed in XPIProvider bootstrapped list."); - - addon = yield promiseAddonByID(ID); - Assert.ok(addon, "Add-on retrieved."); - Assert.equal(addon.userDisabled, false, "Add-on is still enabled after API retrieve."); - Assert.ok(addon.isActive, "Add-on is still active."); - Assert.ok(!(addon.pendingOperations & AddonManager.PENDING_ENABLE), - "Should not be pending enable"); - Assert.ok(!(addon.pendingOperations & AddonManager.PENDING_DISABLE), - "Should not be pending disable"); - - // Now when we restart the manager the add-on should revert state. - yield promiseRestartManager(); - let persisted = JSON.parse(Services.prefs.getCharPref("extensions.bootstrappedAddons")); - Assert.ok(!(ID in persisted), - "Experiment add-on not persisted to bootstrappedAddons."); - - BootstrapMonitor.checkAddonInstalled(ID, "1.0"); - BootstrapMonitor.checkAddonNotStarted(ID); - - addon = yield promiseAddonByID(ID); - Assert.ok(addon, "Add-on retrieved."); - Assert.ok(addon.userDisabled, "Add-on is disabled after restart."); - Assert.equal(addon.isActive, false, "Add-on is not active after restart."); - addon.uninstall(); - - BootstrapMonitor.checkAddonNotInstalled(ID); - BootstrapMonitor.checkAddonNotStarted(ID); -}); - -add_task(function* test_checkCompatibility() { - if (gIsNightly) - Services.prefs.setBoolPref("extensions.checkCompatibility.nightly", false); - else - Services.prefs.setBoolPref("extensions.checkCompatibility.1", false); - - yield promiseRestartManager(); - - yield promiseInstallAllFiles([do_get_addon("test_experiment1")]); - let addon = yield promiseAddonByID(ID); - - BootstrapMonitor.checkAddonInstalled(ID, "1.0"); - BootstrapMonitor.checkAddonNotStarted(ID); - - Assert.ok(addon, "Add-on is found."); - Assert.ok(addon.userDisabled, "Add-on is user disabled."); - Assert.ok(!addon.appDisabled, "Add-on is not app disabled."); +add_test(function test_userDisabledNotPersisted() { + AddonManager.getAddonByID("experiment1@tests.mozilla.org", (addon) => { + Assert.ok(addon, "Add-on is found."); + Assert.ok(addon.userDisabled, "Add-on is user disabled."); + + let listener = { + onEnabled: (addon2) => { + AddonManager.removeAddonListener(listener); + + Assert.equal(addon2.id, addon.id, "Changed add-on matches expected."); + Assert.equal(addon2.userDisabled, false, "Add-on is no longer user disabled."); + Assert.ok(addon2.isActive, "Add-on is active."); + + Assert.ok("experiment1@tests.mozilla.org" in XPIProvider.bootstrappedAddons, + "Experiment add-on listed in XPIProvider bootstrapped list."); + + AddonManager.getAddonByID("experiment1@tests.mozilla.org", (addon) => { + Assert.ok(addon, "Add-on retrieved."); + Assert.equal(addon.userDisabled, false, "Add-on is still enabled after API retrieve."); + Assert.ok(addon.isActive, "Add-on is still active."); + Assert.ok(!(addon.pendingOperations & AddonManager.PENDING_ENABLE), + "Should not be pending enable"); + Assert.ok(!(addon.pendingOperations & AddonManager.PENDING_DISABLE), + "Should not be pending disable"); + + // Now when we restart the manager the add-on should revert state. + restartManager(); + let persisted = JSON.parse(Services.prefs.getCharPref("extensions.bootstrappedAddons")); + Assert.ok(!("experiment1@tests.mozilla.org" in persisted), + "Experiment add-on not persisted to bootstrappedAddons."); + + AddonManager.getAddonByID("experiment1@tests.mozilla.org", (addon) => { + Assert.ok(addon, "Add-on retrieved."); + Assert.ok(addon.userDisabled, "Add-on is disabled after restart."); + Assert.equal(addon.isActive, false, "Add-on is not active after restart."); + + run_next_test(); + }); + }); + }, + }; + + AddonManager.addAddonListener(listener); + addon.userDisabled = false; + }); }); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_ext_management.js b/toolkit/mozapps/extensions/test/xpcshell/test_ext_management.js deleted file mode 100644 index a3b3f477c..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_ext_management.js +++ /dev/null @@ -1,137 +0,0 @@ -"use strict"; - -add_task(function* setup() { - createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "48", "48"); - startupManager(); -}); - -/* eslint-disable no-undef */ -// Shared background function for getSelf tests -function backgroundGetSelf() { - browser.management.getSelf().then(extInfo => { - browser.test.sendMessage("management-getSelf", extInfo); - }, error => { - browser.test.notifyFail(`getSelf rejected with error: ${error}`); - }); -} -/* eslint-enable no-undef */ - -add_task(function* test_management_get_self_complete() { - const id = "get_self_test_complete@tests.mozilla.com"; - const permissions = ["management", "cookies"]; - const hostPermissions = ["*://example.org/", "https://foo.example.org/"]; - - let manifest = { - applications: { - gecko: { - id, - update_url: "https://updates.mozilla.com/", - }, - }, - name: "test extension name", - short_name: "test extension short name", - description: "test extension description", - version: "1.0", - homepage_url: "http://www.example.com/", - options_ui: { - "page": "get_self_options.html", - }, - icons: { - "16": "icons/icon-16.png", - "48": "icons/icon-48.png", - }, - permissions: [...permissions, ...hostPermissions], - }; - - let extension = ExtensionTestUtils.loadExtension({ - manifest, - background: backgroundGetSelf, - useAddonManager: "temporary", - }); - yield extension.startup(); - let extInfo = yield extension.awaitMessage("management-getSelf"); - - equal(extInfo.id, id, "getSelf returned the expected id"); - equal(extInfo.installType, "development", "getSelf returned the expected installType"); - for (let prop of ["name", "description", "version"]) { - equal(extInfo[prop], manifest[prop], `getSelf returned the expected ${prop}`); - } - equal(extInfo.shortName, manifest.short_name, "getSelf returned the expected shortName"); - equal(extInfo.mayDisable, true, "getSelf returned the expected value for mayDisable"); - equal(extInfo.enabled, true, "getSelf returned the expected value for enabled"); - equal(extInfo.homepageUrl, manifest.homepage_url, "getSelf returned the expected homepageUrl"); - equal(extInfo.updateUrl, manifest.applications.gecko.update_url, "getSelf returned the expected updateUrl"); - ok(extInfo.optionsUrl.endsWith(manifest.options_ui.page), "getSelf returned the expected optionsUrl"); - for (let [index, size] of Object.keys(manifest.icons).sort().entries()) { - equal(extInfo.icons[index].size, +size, "getSelf returned the expected icon size"); - equal(extInfo.icons[index].url, manifest.icons[size], "getSelf returned the expected icon url"); - } - deepEqual(extInfo.permissions.sort(), permissions.sort(), "getSelf returned the expected permissions"); - deepEqual(extInfo.hostPermissions.sort(), hostPermissions.sort(), "getSelf returned the expected hostPermissions"); - equal(extInfo.installType, "development", "getSelf returned the expected installType"); - yield extension.unload(); -}); - -add_task(function* test_management_get_self_minimal() { - const id = "get_self_test_minimal@tests.mozilla.com"; - - let manifest = { - applications: { - gecko: { - id, - }, - }, - name: "test extension name", - version: "1.0", - }; - - let extension = ExtensionTestUtils.loadExtension({ - manifest, - background: backgroundGetSelf, - useAddonManager: "temporary", - }); - yield extension.startup(); - let extInfo = yield extension.awaitMessage("management-getSelf"); - - equal(extInfo.id, id, "getSelf returned the expected id"); - equal(extInfo.installType, "development", "getSelf returned the expected installType"); - for (let prop of ["name", "version"]) { - equal(extInfo[prop], manifest[prop], `getSelf returned the expected ${prop}`); - } - for (let prop of ["shortName", "description", "optionsUrl"]) { - equal(extInfo[prop], "", `getSelf returned the expected ${prop}`); - } - for (let prop of ["homepageUrl", " updateUrl", "icons"]) { - equal(Reflect.getOwnPropertyDescriptor(extInfo, prop), undefined, `getSelf did not return a ${prop} property`); - } - for (let prop of ["permissions", "hostPermissions"]) { - deepEqual(extInfo[prop], [], `getSelf returned the expected ${prop}`); - } - yield extension.unload(); -}); - -add_task(function* test_management_get_self_permanent() { - const id = "get_self_test_permanent@tests.mozilla.com"; - - let manifest = { - applications: { - gecko: { - id, - }, - }, - name: "test extension name", - version: "1.0", - }; - - let extension = ExtensionTestUtils.loadExtension({ - manifest, - background: backgroundGetSelf, - useAddonManager: "permanent", - }); - yield extension.startup(); - let extInfo = yield extension.awaitMessage("management-getSelf"); - - equal(extInfo.id, id, "getSelf returned the expected id"); - equal(extInfo.installType, "normal", "getSelf returned the expected installType"); - yield extension.unload(); -}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_filepointer.js b/toolkit/mozapps/extensions/test/xpcshell/test_filepointer.js index 406489e40..cb661e495 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_filepointer.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_filepointer.js @@ -40,7 +40,7 @@ var addon2 = { const profileDir = gProfD.clone(); profileDir.append("extensions"); -profileDir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0o755); +profileDir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0755); const sourceDir = gProfD.clone(); sourceDir.append("source"); @@ -123,7 +123,7 @@ function run_test_1() { do_check_eq(uri.spec, rootUri); uri = a1.getResourceURI("install.rdf"); do_check_eq(uri.spec, rootUri + "install.rdf"); - + // Check that upgrade is disabled for addons installed by file-pointers. do_check_eq(a1.permissions & AddonManager.PERM_CAN_UPGRADE, 0); run_test_2(); @@ -247,9 +247,9 @@ function run_test_5() { restartManager(); AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", - "addon2@tests.mozilla.org"], function([a1_2, a2_2]) { - do_check_eq(a1_2, null); - do_check_eq(a2_2, null); + "addon2@tests.mozilla.org"], function([a1, a2]) { + do_check_eq(a1, null); + do_check_eq(a2, null); let source = sourceDir.clone(); source.append(addon1.id); @@ -283,8 +283,8 @@ function run_test_6() { restartManager(); - AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1_2) { - do_check_eq(a1_2, null); + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_eq(a1, null); do_execute_soon(run_test_7); }); @@ -309,11 +309,11 @@ function run_test_7() { restartManager(); - AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1_2) { - do_check_neq(a1_2, null); - do_check_eq(a1_2.version, "2.0"); + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.version, "2.0"); - a1_2.uninstall(); + a1.uninstall(); do_execute_soon(run_test_8); }); @@ -336,11 +336,11 @@ function run_test_8() { restartManager(); - AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1_2) { - do_check_neq(a1_2, null); - do_check_eq(a1_2.version, "2.0"); + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.version, "2.0"); - a1_2.uninstall(); + a1.uninstall(); do_execute_soon(run_test_9); }); @@ -364,8 +364,8 @@ function run_test_9() { restartManager(); - AddonManager.getAddonByID(addon1.id, function(a1_2) { - do_check_eq(a1_2, null); + AddonManager.getAddonByID(addon1.id, function(a1) { + do_check_eq(a1, null); let pointer = profileDir.clone(); pointer.append(addon1.id); @@ -395,7 +395,7 @@ function run_test_10() { do_check_eq(uri.spec, rootUri); uri = a1.getResourceURI("install.rdf"); do_check_eq(uri.spec, rootUri + "install.rdf"); - + // Check that upgrade is disabled for addons installed by file-pointers. do_check_eq(a1.permissions & AddonManager.PERM_CAN_UPGRADE, 0); end_test(); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_fuel.js b/toolkit/mozapps/extensions/test/xpcshell/test_fuel.js index 0c3035f76..800933220 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_fuel.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_fuel.js @@ -101,7 +101,7 @@ function run_test() { // PREF TESTING // Reset the install event preference, so that we can test it again later - // inspector.prefs.get("install-event-fired").reset(); + //inspector.prefs.get("install-event-fired").reset(); // test the value of the preference root do_check_eq(extensions.all[0].prefs.root, "extensions.addon1@tests.mozilla.org."); @@ -129,7 +129,7 @@ function run_test() { // test resetting a pref [since there is no default value, the pref should disappear] inspector.prefs.get(testdata.dummy).reset(); - itemValue = inspector.prefs.getValue(testdata.dummy, "default"); + var itemValue = inspector.prefs.getValue(testdata.dummy, "default"); do_check_eq(itemValue, "default"); // test to see if a non-existant property exists @@ -141,7 +141,6 @@ function run_test() { }); } -var gLastEvent; function onGenericEvent(event) { gLastEvent = event.type; } diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_getresource.js b/toolkit/mozapps/extensions/test/xpcshell/test_getresource.js index c83638d54..4dce15aec 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_getresource.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_getresource.js @@ -76,9 +76,9 @@ function run_test() { } AddonManager.getInstallForFile(do_get_addon("test_getresource"), - callback_soon(function(aInstall_2) { + callback_soon(function(aInstall) { do_check_false(a1.hasResource("icon.png")); - do_check_true(aInstall_2.addon.hasResource("icon.png")); + do_check_true(aInstall.addon.hasResource("icon.png")); restartManager(); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Device.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Device.js index 9b0eb54a7..5f781edf4 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Device.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Device.js @@ -2,14 +2,11 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -// This should eventually be moved to head_addons.js -var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; - // Test whether a machine which differs only on device ID, but otherwise // exactly matches the blacklist entry, is not blocked. // Uses test_gfxBlacklist.xml -Cu.import("resource://testing-common/httpd.js"); +Components.utils.import("resource://testing-common/httpd.js"); var gTestserver = new HttpServer(); gTestserver.start(-1); @@ -17,8 +14,8 @@ gPort = gTestserver.identity.primaryPort; mapFile("/data/test_gfxBlacklist.xml", gTestserver); function get_platform() { - var xulRuntime = Cc["@mozilla.org/xre/app-info;1"] - .getService(Ci.nsIXULRuntime); + var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"] + .getService(Components.interfaces.nsIXULRuntime); return xulRuntime.OS; } @@ -32,7 +29,12 @@ function load_blocklist(file) { // Performs the initial setup function run_test() { - var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + try { + var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + } catch (e) { + do_test_finished(); + return; + } // We can't do anything if we can't spoof the stuff we need. if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) { @@ -58,7 +60,7 @@ function run_test() { case "Darwin": gfxInfo.spoofVendorID("0xabcd"); gfxInfo.spoofDeviceID("0x9876"); - gfxInfo.spoofOSVersion(0x1090); + gfxInfo.spoofOSVersion(0x1050); break; case "Android": gfxInfo.spoofVendorID("abcd"); @@ -80,9 +82,6 @@ function run_test() { status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT3D_9_LAYERS); do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); - status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_CANVAS2D_ACCELERATION); - do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); - gTestserver.stop(do_test_finished); } diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_DriverNew.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_DriverNew.js index f8b783ff2..802fe11e2 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_DriverNew.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_DriverNew.js @@ -2,14 +2,11 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -// This should eventually be moved to head_addons.js -var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; - // Test whether a new-enough driver bypasses the blacklist, even if the rest of // the attributes match the blacklist entry. // Uses test_gfxBlacklist.xml -Cu.import("resource://testing-common/httpd.js"); +Components.utils.import("resource://testing-common/httpd.js"); var gTestserver = new HttpServer(); gTestserver.start(-1); @@ -17,8 +14,8 @@ gPort = gTestserver.identity.primaryPort; mapFile("/data/test_gfxBlacklist.xml", gTestserver); function get_platform() { - var xulRuntime = Cc["@mozilla.org/xre/app-info;1"] - .getService(Ci.nsIXULRuntime); + var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"] + .getService(Components.interfaces.nsIXULRuntime); return xulRuntime.OS; } @@ -32,7 +29,12 @@ function load_blocklist(file) { // Performs the initial setup function run_test() { - var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + try { + var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + } catch (e) { + do_test_finished(); + return; + } // We can't do anything if we can't spoof the stuff we need. if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) { diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_DriverNew.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_DriverNew.js index 1b3410e87..08e87c38c 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_DriverNew.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_DriverNew.js @@ -2,14 +2,11 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -// This should eventually be moved to head_addons.js -var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; - // Test whether a machine which is newer than the equal // blacklist entry is allowed. // Uses test_gfxBlacklist.xml -Cu.import("resource://testing-common/httpd.js"); +Components.utils.import("resource://testing-common/httpd.js"); var gTestserver = new HttpServer(); gTestserver.start(-1); @@ -17,8 +14,8 @@ gPort = gTestserver.identity.primaryPort; mapFile("/data/test_gfxBlacklist.xml", gTestserver); function get_platform() { - var xulRuntime = Cc["@mozilla.org/xre/app-info;1"] - .getService(Ci.nsIXULRuntime); + var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"] + .getService(Components.interfaces.nsIXULRuntime); return xulRuntime.OS; } @@ -32,7 +29,12 @@ function load_blocklist(file) { // Performs the initial setup function run_test() { - var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + try { + var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + } catch (e) { + do_test_finished(); + return; + } // We can't do anything if we can't spoof the stuff we need. if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) { @@ -56,7 +58,7 @@ function run_test() { do_test_finished(); return; case "Darwin": - // We don't support driver versions on OS X. + // We don't support driver versions on Darwin. do_test_finished(); return; case "Android": @@ -66,7 +68,7 @@ function run_test() { break; } - createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "15.0", "8"); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3", "8"); startupManager(); do_test_pending(); @@ -80,36 +82,6 @@ function run_test() { status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT3D_9_LAYERS); do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); - status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT3D_11_LAYERS); - do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); - - status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_OPENGL_LAYERS); - do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); - - status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT3D_11_ANGLE); - do_check_eq(status, Ci.nsIGfxInfo.FEATURE_BLOCKED_DRIVER_VERSION); - - status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_HARDWARE_VIDEO_DECODING); - do_check_eq(status, Ci.nsIGfxInfo.FEATURE_BLOCKED_DRIVER_VERSION); - - status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_WEBRTC_HW_ACCELERATION); - do_check_eq(status, Ci.nsIGfxInfo.FEATURE_BLOCKED_DRIVER_VERSION); - - status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_WEBRTC_HW_ACCELERATION_DECODE); - do_check_eq(status, Ci.nsIGfxInfo.FEATURE_BLOCKED_DRIVER_VERSION); - - status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_WEBRTC_HW_ACCELERATION_ENCODE); - do_check_eq(status, Ci.nsIGfxInfo.FEATURE_BLOCKED_DRIVER_VERSION); - - status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_WEBGL_MSAA); - do_check_eq(status, Ci.nsIGfxInfo.FEATURE_BLOCKED_DRIVER_VERSION); - - status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_WEBGL_ANGLE); - do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); - - status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_CANVAS2D_ACCELERATION); - do_check_eq(status, Ci.nsIGfxInfo.FEATURE_BLOCKED_DRIVER_VERSION); - gTestserver.stop(do_test_finished); } diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_DriverOld.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_DriverOld.js index 248c9e7f6..73253c89b 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_DriverOld.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_DriverOld.js @@ -2,14 +2,11 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -// This should eventually be moved to head_addons.js -var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; - // Test whether a machine which is older than the equal // blacklist entry is correctly allowed. // Uses test_gfxBlacklist.xml -Cu.import("resource://testing-common/httpd.js"); +Components.utils.import("resource://testing-common/httpd.js"); var gTestserver = new HttpServer(); gTestserver.start(-1); @@ -17,8 +14,8 @@ gPort = gTestserver.identity.primaryPort; mapFile("/data/test_gfxBlacklist.xml", gTestserver); function get_platform() { - var xulRuntime = Cc["@mozilla.org/xre/app-info;1"] - .getService(Ci.nsIXULRuntime); + var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"] + .getService(Components.interfaces.nsIXULRuntime); return xulRuntime.OS; } @@ -32,7 +29,12 @@ function load_blocklist(file) { // Performs the initial setup function run_test() { - var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + try { + var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + } catch (e) { + do_test_finished(); + return; + } // We can't do anything if we can't spoof the stuff we need. if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) { diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_OK.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_OK.js index 8b8928bb8..2dde268a3 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_OK.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_OK.js @@ -2,14 +2,11 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -// This should eventually be moved to head_addons.js -var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; - // Test whether a machine which exactly matches the equal // blacklist entry is successfully blocked. // Uses test_gfxBlacklist.xml -Cu.import("resource://testing-common/httpd.js"); +Components.utils.import("resource://testing-common/httpd.js"); var gTestserver = new HttpServer(); gTestserver.start(-1); @@ -17,8 +14,8 @@ gPort = gTestserver.identity.primaryPort; mapFile("/data/test_gfxBlacklist.xml", gTestserver); function get_platform() { - var xulRuntime = Cc["@mozilla.org/xre/app-info;1"] - .getService(Ci.nsIXULRuntime); + var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"] + .getService(Components.interfaces.nsIXULRuntime); return xulRuntime.OS; } @@ -32,7 +29,12 @@ function load_blocklist(file) { // Performs the initial setup function run_test() { - var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + try { + var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + } catch (e) { + do_test_finished(); + return; + } // We can't do anything if we can't spoof the stuff we need. if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) { diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_GTE_DriverOld.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_GTE_DriverOld.js index bd5858023..fd3145f5a 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_GTE_DriverOld.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_GTE_DriverOld.js @@ -2,14 +2,11 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -// This should eventually be moved to head_addons.js -var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; - // Test whether a machine which is lower than the greater-than-or-equal // blacklist entry is allowed. // Uses test_gfxBlacklist.xml -Cu.import("resource://testing-common/httpd.js"); +Components.utils.import("resource://testing-common/httpd.js"); var gTestserver = new HttpServer(); gTestserver.start(-1); @@ -17,8 +14,8 @@ gPort = gTestserver.identity.primaryPort; mapFile("/data/test_gfxBlacklist.xml", gTestserver); function get_platform() { - var xulRuntime = Cc["@mozilla.org/xre/app-info;1"] - .getService(Ci.nsIXULRuntime); + var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"] + .getService(Components.interfaces.nsIXULRuntime); return xulRuntime.OS; } @@ -32,7 +29,12 @@ function load_blocklist(file) { // Performs the initial setup function run_test() { - var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + try { + var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + } catch (e) { + do_test_finished(); + return; + } // We can't do anything if we can't spoof the stuff we need. if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) { diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_GTE_OK.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_GTE_OK.js index b5c5ed2a6..0c2c65572 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_GTE_OK.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_GTE_OK.js @@ -2,14 +2,11 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -// This should eventually be moved to head_addons.js -var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; - // Test whether a machine which exactly matches the greater-than-or-equal // blacklist entry is successfully blocked. // Uses test_gfxBlacklist.xml -Cu.import("resource://testing-common/httpd.js"); +Components.utils.import("resource://testing-common/httpd.js"); var gTestserver = new HttpServer(); gTestserver.start(-1); @@ -17,8 +14,8 @@ gPort = gTestserver.identity.primaryPort; mapFile("/data/test_gfxBlacklist.xml", gTestserver); function get_platform() { - var xulRuntime = Cc["@mozilla.org/xre/app-info;1"] - .getService(Ci.nsIXULRuntime); + var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"] + .getService(Components.interfaces.nsIXULRuntime); return xulRuntime.OS; } @@ -32,7 +29,12 @@ function load_blocklist(file) { // Performs the initial setup function run_test() { - var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + try { + var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + } catch (e) { + do_test_finished(); + return; + } // We can't do anything if we can't spoof the stuff we need. if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) { diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_No_Comparison.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_No_Comparison.js index ff37e6676..61372cff8 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_No_Comparison.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_No_Comparison.js @@ -2,14 +2,11 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -// This should eventually be moved to head_addons.js -var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; - // Test whether a machine which exactly matches the blacklist entry is // successfully blocked. // Uses test_gfxBlacklist.xml -Cu.import("resource://testing-common/httpd.js"); +Components.utils.import("resource://testing-common/httpd.js"); var gTestserver = new HttpServer(); gTestserver.start(-1); @@ -17,8 +14,8 @@ gPort = gTestserver.identity.primaryPort; mapFile("/data/test_gfxBlacklist.xml", gTestserver); function get_platform() { - var xulRuntime = Cc["@mozilla.org/xre/app-info;1"] - .getService(Ci.nsIXULRuntime); + var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"] + .getService(Components.interfaces.nsIXULRuntime); return xulRuntime.OS; } @@ -32,7 +29,12 @@ function load_blocklist(file) { // Performs the initial setup function run_test() { - var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + try { + var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + } catch (e) { + do_test_finished(); + return; + } // We can't do anything if we can't spoof the stuff we need. if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) { @@ -54,7 +56,7 @@ function run_test() { case "Linux": break; case "Darwin": - gfxInfo.spoofOSVersion(0x1090); + gfxInfo.spoofOSVersion(0x1050); break; case "Android": break; @@ -67,15 +69,13 @@ function run_test() { function checkBlacklist() { - var driverVersion = gfxInfo.adapterDriverVersion; - if (driverVersion) { - var status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT2D); - do_check_eq(status, Ci.nsIGfxInfo.FEATURE_BLOCKED_DEVICE); - - // Make sure unrelated features aren't affected - status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT3D_9_LAYERS); - do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); - } + var status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT2D); + do_check_eq(status, Ci.nsIGfxInfo.FEATURE_BLOCKED_DEVICE); + + // Make sure unrelated features aren't affected + status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT3D_9_LAYERS); + do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); + gTestserver.stop(do_test_finished); } diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OK.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OK.js index 72b2a2bdc..dcd578dfb 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OK.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OK.js @@ -2,14 +2,11 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -// This should eventually be moved to head_addons.js -var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; - // Test whether a machine which exactly matches the blacklist entry is // successfully blocked. // Uses test_gfxBlacklist.xml -Cu.import("resource://testing-common/httpd.js"); +Components.utils.import("resource://testing-common/httpd.js"); var gTestserver = new HttpServer(); gTestserver.start(-1); @@ -17,8 +14,8 @@ gPort = gTestserver.identity.primaryPort; mapFile("/data/test_gfxBlacklist.xml", gTestserver); function get_platform() { - var xulRuntime = Cc["@mozilla.org/xre/app-info;1"] - .getService(Ci.nsIXULRuntime); + var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"] + .getService(Components.interfaces.nsIXULRuntime); return xulRuntime.OS; } @@ -32,7 +29,12 @@ function load_blocklist(file) { // Performs the initial setup function run_test() { - var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + try { + var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + } catch (e) { + do_test_finished(); + return; + } // We can't do anything if we can't spoof the stuff we need. if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) { @@ -58,7 +60,7 @@ function run_test() { case "Darwin": gfxInfo.spoofVendorID("0xabcd"); gfxInfo.spoofDeviceID("0x1234"); - gfxInfo.spoofOSVersion(0x1090); + gfxInfo.spoofOSVersion(0x1050); break; case "Android": gfxInfo.spoofVendorID("abcd"); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OS.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OS.js index fa0deb19a..81edc9cd1 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OS.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OS.js @@ -2,14 +2,11 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -// This should eventually be moved to head_addons.js -var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; - // Test whether a machine which differs only on OS version, but otherwise // exactly matches the blacklist entry, is not blocked. // Uses test_gfxBlacklist.xml -Cu.import("resource://testing-common/httpd.js"); +Components.utils.import("resource://testing-common/httpd.js"); var gTestserver = new HttpServer(); gTestserver.start(-1); @@ -17,8 +14,8 @@ gPort = gTestserver.identity.primaryPort; mapFile("/data/test_gfxBlacklist.xml", gTestserver); function get_platform() { - var xulRuntime = Cc["@mozilla.org/xre/app-info;1"] - .getService(Ci.nsIXULRuntime); + var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"] + .getService(Components.interfaces.nsIXULRuntime); return xulRuntime.OS; } @@ -32,7 +29,12 @@ function load_blocklist(file) { // Performs the initial setup function run_test() { - var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + try { + var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + } catch (e) { + do_test_finished(); + return; + } // We can't do anything if we can't spoof the stuff we need. if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) { @@ -58,7 +60,8 @@ function run_test() { case "Darwin": gfxInfo.spoofVendorID("0xabcd"); gfxInfo.spoofDeviceID("0x1234"); - gfxInfo.spoofOSVersion(0x1080); + // Snow Leopard + gfxInfo.spoofOSVersion(0x1060); break; case "Android": // On Android, the driver version is used as the OS version (because diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OSVersion_match.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OSVersion_match.js index f01329b45..3472c6d7e 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OSVersion_match.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OSVersion_match.js @@ -2,22 +2,18 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -// This should eventually be moved to head_addons.js -var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; - // Test whether new OS versions are matched properly. // Uses test_gfxBlacklist_OS.xml -Cu.import("resource://testing-common/httpd.js"); +Components.utils.import("resource://testing-common/httpd.js"); var gTestserver = new HttpServer(); gTestserver.start(-1); gPort = gTestserver.identity.primaryPort; -mapFile("/data/test_gfxBlacklist_OSVersion.xml", gTestserver); function get_platform() { - var xulRuntime = Cc["@mozilla.org/xre/app-info;1"] - .getService(Ci.nsIXULRuntime); + var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"] + .getService(Components.interfaces.nsIXULRuntime); return xulRuntime.OS; } @@ -31,7 +27,12 @@ function load_blocklist(file) { // Performs the initial setup function run_test() { - var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + try { + var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + } catch (e) { + do_test_finished(); + return; + } // We can't do anything if we can't spoof the stuff we need. if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) { @@ -58,7 +59,7 @@ function run_test() { return; case "Darwin": // Mountain Lion - gfxInfo.spoofOSVersion(0x1090); + gfxInfo.spoofOSVersion(0x1080); break; case "Android": // On Android, the driver version is used as the OS version (because @@ -91,5 +92,5 @@ function run_test() { do_execute_soon(checkBlacklist); }, "blocklist-data-gfxItems", false); - load_blocklist("test_gfxBlacklist_OSVersion.xml"); + load_blocklist("test_gfxBlacklist_OS.xml"); } diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OSVersion_mismatch_DriverVersion.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OSVersion_mismatch_DriverVersion.js index 4b1069dc6..fb25b9509 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OSVersion_mismatch_DriverVersion.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OSVersion_mismatch_DriverVersion.js @@ -2,23 +2,19 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -// This should eventually be moved to head_addons.js -var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; - // Test whether blocklists specifying new OSeswcorrectly don't block if driver // versions are appropriately up-to-date. // Uses test_gfxBlacklist_OS.xml -Cu.import("resource://testing-common/httpd.js"); +Components.utils.import("resource://testing-common/httpd.js"); var gTestserver = new HttpServer(); gTestserver.start(-1); gPort = gTestserver.identity.primaryPort; -mapFile("/data/test_gfxBlacklist_OSVersion.xml", gTestserver); function get_platform() { - var xulRuntime = Cc["@mozilla.org/xre/app-info;1"] - .getService(Ci.nsIXULRuntime); + var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"] + .getService(Components.interfaces.nsIXULRuntime); return xulRuntime.OS; } @@ -32,7 +28,12 @@ function load_blocklist(file) { // Performs the initial setup function run_test() { - var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + try { + var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + } catch (e) { + do_test_finished(); + return; + } // We can't do anything if we can't spoof the stuff we need. if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) { @@ -58,6 +59,7 @@ function run_test() { do_test_finished(); return; case "Darwin": + // Mountain Lion gfxInfo.spoofOSVersion(0x1080); break; case "Android": @@ -91,5 +93,5 @@ function run_test() { do_execute_soon(checkBlacklist); }, "blocklist-data-gfxItems", false); - load_blocklist("test_gfxBlacklist_OSVersion.xml"); + load_blocklist("test_gfxBlacklist_OS.xml"); } diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OSVersion_mismatch_OSVersion.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OSVersion_mismatch_OSVersion.js index 0c5a0dcb7..4fb162262 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OSVersion_mismatch_OSVersion.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OSVersion_mismatch_OSVersion.js @@ -2,23 +2,19 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -// This should eventually be moved to head_addons.js -var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; - // Test whether old OS versions are not matched when the blacklist contains // only new OS versions. // Uses test_gfxBlacklist_OS.xml -Cu.import("resource://testing-common/httpd.js"); +Components.utils.import("resource://testing-common/httpd.js"); var gTestserver = new HttpServer(); gTestserver.start(-1); gPort = gTestserver.identity.primaryPort; -mapFile("/data/test_gfxBlacklist_OSVersion.xml", gTestserver); function get_platform() { - var xulRuntime = Cc["@mozilla.org/xre/app-info;1"] - .getService(Ci.nsIXULRuntime); + var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"] + .getService(Components.interfaces.nsIXULRuntime); return xulRuntime.OS; } @@ -32,7 +28,12 @@ function load_blocklist(file) { // Performs the initial setup function run_test() { - var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + try { + var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + } catch (e) { + do_test_finished(); + return; + } // We can't do anything if we can't spoof the stuff we need. if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) { @@ -59,7 +60,7 @@ function run_test() { return; case "Darwin": // Lion - gfxInfo.spoofOSVersion(0x1080); + gfxInfo.spoofOSVersion(0x1070); break; case "Android": // On Android, the driver version is used as the OS version (because @@ -92,5 +93,5 @@ function run_test() { do_execute_soon(checkBlacklist); }, "blocklist-data-gfxItems", false); - load_blocklist("test_gfxBlacklist_OSVersion.xml"); + load_blocklist("test_gfxBlacklist_OS.xml"); } diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Vendor.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Vendor.js index 868c48149..a5d1c71cf 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Vendor.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Vendor.js @@ -2,14 +2,11 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -// This should eventually be moved to head_addons.js -var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; - // Test whether a machine which differs only on vendor, but otherwise // exactly matches the blacklist entry, is not blocked. // Uses test_gfxBlacklist.xml -Cu.import("resource://testing-common/httpd.js"); +Components.utils.import("resource://testing-common/httpd.js"); var gTestserver = new HttpServer(); gTestserver.start(-1); @@ -17,8 +14,8 @@ gPort = gTestserver.identity.primaryPort; mapFile("/data/test_gfxBlacklist.xml", gTestserver); function get_platform() { - var xulRuntime = Cc["@mozilla.org/xre/app-info;1"] - .getService(Ci.nsIXULRuntime); + var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"] + .getService(Components.interfaces.nsIXULRuntime); return xulRuntime.OS; } @@ -32,7 +29,12 @@ function load_blocklist(file) { // Performs the initial setup function run_test() { - var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + try { + var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + } catch (e) { + do_test_finished(); + return; + } // We can't do anything if we can't spoof the stuff we need. if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) { @@ -58,7 +60,7 @@ function run_test() { case "Darwin": gfxInfo.spoofVendorID("0xdcba"); gfxInfo.spoofDeviceID("0x1234"); - gfxInfo.spoofOSVersion(0x1090); + gfxInfo.spoofOSVersion(0x1050); break; case "Android": gfxInfo.spoofVendorID("dcba"); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Version.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Version.js deleted file mode 100755 index 48174b772..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Version.js +++ /dev/null @@ -1,145 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; - -// Test whether a machine which exactly matches the blacklist entry is -// successfully blocked. -// Uses test_gfxBlacklist_AllOS.xml - -Cu.import("resource://testing-common/httpd.js"); - -var gTestserver = new HttpServer(); -gTestserver.start(-1); -gPort = gTestserver.identity.primaryPort; -mapFile("/data/test_gfxBlacklist_AllOS.xml", gTestserver); - -function get_platform() { - var xulRuntime = Cc["@mozilla.org/xre/app-info;1"] - .getService(Ci.nsIXULRuntime); - return xulRuntime.OS; -} - -function load_blocklist(file) { - Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" + - gPort + "/data/" + file); - var blocklist = Cc["@mozilla.org/extensions/blocklist;1"]. - getService(Ci.nsITimerCallback); - blocklist.notify(null); -} - -// Performs the initial setup -function run_test() { - var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); - - // We can't do anything if we can't spoof the stuff we need. - if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) { - do_test_finished(); - return; - } - - gfxInfo.QueryInterface(Ci.nsIGfxInfoDebug); - - // Set the vendor/device ID, etc, to match the test file. - switch (get_platform()) { - case "WINNT": - gfxInfo.spoofVendorID("0xabcd"); - gfxInfo.spoofDeviceID("0x1234"); - gfxInfo.spoofDriverVersion("8.52.322.2201"); - // Windows 7 - gfxInfo.spoofOSVersion(0x60001); - break; - case "Linux": - gfxInfo.spoofVendorID("0xabcd"); - gfxInfo.spoofDeviceID("0x1234"); - break; - case "Darwin": - gfxInfo.spoofVendorID("0xabcd"); - gfxInfo.spoofDeviceID("0x1234"); - gfxInfo.spoofOSVersion(0x1090); - break; - case "Android": - gfxInfo.spoofVendorID("abcd"); - gfxInfo.spoofDeviceID("asdf"); - gfxInfo.spoofDriverVersion("5"); - break; - } - - createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "15.0", "8"); - startupManager(); - - do_test_pending(); - - function checkBlacklist() - { - var failureId = {}; - var status; - - status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT2D, failureId); - do_check_eq(status, Ci.nsIGfxInfo.FEATURE_BLOCKED_DRIVER_VERSION); - do_check_eq(failureId.value, "FEATURE_FAILURE_DL_BLACKLIST_g1"); - - status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT3D_9_LAYERS, failureId); - do_check_eq(status, Ci.nsIGfxInfo.FEATURE_BLOCKED_DRIVER_VERSION); - do_check_eq(failureId.value, "FEATURE_FAILURE_DL_BLACKLIST_g2"); - - status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT3D_10_LAYERS, failureId); - do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); - do_check_eq(failureId.value, ""); - - status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT3D_10_1_LAYERS, failureId); - do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); - do_check_eq(failureId.value, ""); - - // These four pass on Linux independent of the blocklist XML file as the - // try machines don't have support. - status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_OPENGL_LAYERS); - do_check_eq(status, Ci.nsIGfxInfo.FEATURE_BLOCKED_DRIVER_VERSION); - - status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_WEBGL_OPENGL, failureId); - do_check_eq(status, Ci.nsIGfxInfo.FEATURE_BLOCKED_DRIVER_VERSION); - do_check_eq(failureId.value, "FEATURE_FAILURE_DL_BLACKLIST_g11"); - - status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_WEBGL_ANGLE, failureId); - do_check_eq(status, Ci.nsIGfxInfo.FEATURE_BLOCKED_DRIVER_VERSION); - do_check_eq(failureId.value, "FEATURE_FAILURE_DL_BLACKLIST_NO_ID"); - - status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_WEBGL_MSAA, failureId); - do_check_eq(status, Ci.nsIGfxInfo.FEATURE_BLOCKED_DRIVER_VERSION); - - status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_STAGEFRIGHT, failureId); - do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); - - status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_WEBRTC_HW_ACCELERATION, failureId); - do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); - - status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_WEBRTC_HW_ACCELERATION_ENCODE, failureId); - do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); - - status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_WEBRTC_HW_ACCELERATION_DECODE, failureId); - do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); - - status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT3D_11_LAYERS, failureId); - do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); - - status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_HARDWARE_VIDEO_DECODING, failureId); - do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); - - status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT3D_11_ANGLE, failureId); - do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); - - status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DX_INTEROP2, failureId); - do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); - - gTestserver.stop(do_test_finished); - } - - Services.obs.addObserver(function(aSubject, aTopic, aData) { - // If we wait until after we go through the event loop, gfxInfo is sure to - // have processed the gfxItems event. - do_execute_soon(checkBlacklist); - }, "blocklist-data-gfxItems", false); - - load_blocklist("test_gfxBlacklist_AllOS.xml"); -} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_prefs.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_prefs.js index fbb992879..bb0e55e2c 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_prefs.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_prefs.js @@ -2,8 +2,6 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -var { classes: Cc, interfaces: Ci } = Components; - // Test whether the blacklist succesfully adds and removes the prefs that store // its decisions when the remote blacklist is changed. // Uses test_gfxBlacklist.xml and test_gfxBlacklist2.xml @@ -14,7 +12,6 @@ var gTestserver = new HttpServer(); gTestserver.start(-1); gPort = gTestserver.identity.primaryPort; mapFile("/data/test_gfxBlacklist.xml", gTestserver); -mapFile("/data/test_gfxBlacklist2.xml", gTestserver); function get_platform() { var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"] @@ -63,7 +60,7 @@ function run_test() { case "Darwin": gfxInfo.spoofVendorID("0xabcd"); gfxInfo.spoofDeviceID("0x1234"); - gfxInfo.spoofOSVersion(0x1090); + gfxInfo.spoofOSVersion(0x1050); break; case "Android": gfxInfo.spoofVendorID("abcd"); @@ -123,7 +120,7 @@ function run_test() { try { prefs.getIntPref("gfx.blacklist.direct2d"); exists = true; - } catch (e) {} + } catch(e) {} do_check_false(exists); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gmpProvider.js b/toolkit/mozapps/extensions/test/xpcshell/test_gmpProvider.js index 545d7d666..8de3ab4a2 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_gmpProvider.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gmpProvider.js @@ -3,19 +3,14 @@ "use strict"; -var {classes: Cc, interfaces: Ci, utils: Cu} = Components; -var GMPScope = Cu.import("resource://gre/modules/addons/GMPProvider.jsm"); -Cu.import("resource://gre/modules/AppConstants.jsm"); -Cu.import("resource://gre/modules/UpdateUtils.jsm"); +const {classes: Cc, interfaces: Ci, utils: Cu} = Components; +let GMPScope = Cu.import("resource://gre/modules/addons/GMPProvider.jsm"); XPCOMUtils.defineLazyGetter(this, "pluginsBundle", () => Services.strings.createBundle("chrome://global/locale/plugins.properties")); -XPCOMUtils.defineLazyModuleGetter(this, "FileUtils", - "resource://gre/modules/FileUtils.jsm"); - -var gMockAddons = new Map(); -var gMockEmeAddons = new Map(); +let gMockAddons = new Map(); +let gMockEmeAddons = new Map(); for (let plugin of GMPScope.GMP_PLUGINS) { let mockAddon = Object.freeze({ @@ -24,28 +19,22 @@ for (let plugin of GMPScope.GMP_PLUGINS) { isInstalled: false, nameId: plugin.name, descriptionId: plugin.description, - missingKey: plugin.missingKey, - missingFilesKey: plugin.missingFilesKey, }); gMockAddons.set(mockAddon.id, mockAddon); - if (mockAddon.id == "gmp-widevinecdm" || - mockAddon.id.indexOf("gmp-eme-") == 0) { + if (mockAddon.id.indexOf("gmp-eme-") == 0) { gMockEmeAddons.set(mockAddon.id, mockAddon); } } -var gInstalledAddonId = ""; -var gPrefs = Services.prefs; -var gGetKey = GMPScope.GMPPrefs.getPrefKey; +let gInstalledAddonId = ""; +let gPrefs = Services.prefs; +let gGetKey = GMPScope.GMPPrefs.getPrefKey; function MockGMPInstallManager() { } MockGMPInstallManager.prototype = { - checkForAddons: () => Promise.resolve({ - usedFallback: true, - gmpAddons: [...gMockAddons.values()] - }), + checkForAddons: () => Promise.resolve([...gMockAddons.values()]), installAddon: addon => { gInstalledAddonId = addon.id; @@ -62,9 +51,7 @@ function run_test() { gPrefs.setIntPref(GMPScope.GMPPrefs.KEY_LOGGING_LEVEL, 0); gPrefs.setBoolPref(GMPScope.GMPPrefs.KEY_EME_ENABLED, true); for (let addon of gMockAddons.values()) { - gPrefs.setBoolPref(gGetKey(GMPScope.GMPPrefs.KEY_PLUGIN_VISIBLE, addon.id), - true); - gPrefs.setBoolPref(gGetKey(GMPScope.GMPPrefs.KEY_PLUGIN_FORCE_SUPPORTED, addon.id), + gPrefs.setBoolPref(gGetKey(GMPScope.GMPPrefs.KEY_PLUGIN_FORCEVISIBLE, addon.id), true); } GMPScope.GMPProvider.shutdown(); @@ -229,42 +216,11 @@ add_task(function* test_autoUpdatePrefPersistance() { } }); -function createMockPluginFilesIfNeeded(aFile, aPluginId) { - function createFile(aFileName) { - let f = aFile.clone(); - f.append(aFileName); - if (!f.exists()) { - f.create(Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); - } - } - - let id = aPluginId.substring(4); - let libName = AppConstants.DLL_PREFIX + id + AppConstants.DLL_SUFFIX; - - createFile(libName); - if (aPluginId == "gmp-widevinecdm") { - createFile("manifest.json"); - } else { - createFile(id + ".info"); - } - if (aPluginId == "gmp-eme-adobe") - createFile(id + ".voucher"); -} - -// Array.includes() is only in Nightly channel, so polyfill so we don't fail -// on other branches. -if (![].includes) { - Array.prototype.includes = function(element) { - return Object(this).indexOf(element) != -1; - } -} - add_task(function* test_pluginRegistration() { const TEST_VERSION = "1.2.3.4"; - let profD = do_get_profile(); for (let addon of gMockAddons.values()) { - let file = profD.clone(); + let file = Services.dirsvc.get("ProfD", Ci.nsIFile); file.append(addon.id); file.append(TEST_VERSION); @@ -273,58 +229,18 @@ add_task(function* test_pluginRegistration() { let clearPaths = () => { addedPaths = []; removedPaths = []; } let MockGMPService = { - addPluginDirectory: path => { - if (!addedPaths.includes(path)) { - addedPaths.push(path); - } - }, - removePluginDirectory: path => { - if (!removedPaths.includes(path)) { - removedPaths.push(path); - } - }, - removeAndDeletePluginDirectory: path => { - if (!removedPaths.includes(path)) { - removedPaths.push(path); - } - }, + addPluginDirectory: path => addedPaths.push(path), + removePluginDirectory: path => removedPaths.push(path), + removeAndDeletePluginDirectory: path => removedPaths.push(path), }; - GMPScope.gmpService = MockGMPService; + GMPScope.gmpService = MockGMPService; gPrefs.setBoolPref(gGetKey(GMPScope.GMPPrefs.KEY_PLUGIN_ENABLED, addon.id), true); - // Test that plugin registration fails if the plugin dynamic library and - // info files are not present. + // Check that the plugin gets registered after startup. gPrefs.setCharPref(gGetKey(GMPScope.GMPPrefs.KEY_PLUGIN_VERSION, addon.id), - TEST_VERSION); - clearPaths(); - yield promiseRestartManager(); - Assert.equal(addedPaths.indexOf(file.path), -1); - Assert.deepEqual(removedPaths, [file.path]); - - // Create dummy GMP library/info files, and test that plugin registration - // succeeds during startup, now that we've added GMP info/lib files. - createMockPluginFilesIfNeeded(file, addon.id); - - gPrefs.setCharPref(gGetKey(GMPScope.GMPPrefs.KEY_PLUGIN_VERSION, addon.id), - TEST_VERSION); - clearPaths(); - yield promiseRestartManager(); - Assert.notEqual(addedPaths.indexOf(file.path), -1); - Assert.deepEqual(removedPaths, []); - - // Setting the ABI to something invalid should cause plugin to be removed at startup. - clearPaths(); - gPrefs.setCharPref(gGetKey(GMPScope.GMPPrefs.KEY_PLUGIN_ABI, addon.id), "invalid-ABI"); - yield promiseRestartManager(); - Assert.equal(addedPaths.indexOf(file.path), -1); - Assert.deepEqual(removedPaths, [file.path]); - - // Setting the ABI to expected ABI should cause registration at startup. + TEST_VERSION); clearPaths(); - gPrefs.setCharPref(gGetKey(GMPScope.GMPPrefs.KEY_PLUGIN_VERSION, addon.id), - TEST_VERSION); - gPrefs.setCharPref(gGetKey(GMPScope.GMPPrefs.KEY_PLUGIN_ABI, addon.id), UpdateUtils.ABI); yield promiseRestartManager(); Assert.notEqual(addedPaths.indexOf(file.path), -1); Assert.deepEqual(removedPaths, []); @@ -343,7 +259,7 @@ add_task(function* test_pluginRegistration() { // Changing the pref mid-session should cause unregistration and registration. gPrefs.setCharPref(gGetKey(GMPScope.GMPPrefs.KEY_PLUGIN_VERSION, addon.id), - TEST_VERSION); + TEST_VERSION); clearPaths(); const TEST_VERSION_2 = "5.6.7.8"; let file2 = Services.dirsvc.get("ProfD", Ci.nsIFile); @@ -356,7 +272,7 @@ add_task(function* test_pluginRegistration() { // Disabling the plugin should cause unregistration. gPrefs.setCharPref(gGetKey(GMPScope.GMPPrefs.KEY_PLUGIN_VERSION, addon.id), - TEST_VERSION); + TEST_VERSION); clearPaths(); gPrefs.setBoolPref(gGetKey(GMPScope.GMPPrefs.KEY_PLUGIN_ENABLED, addon.id), false); Assert.deepEqual(addedPaths, []); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_hasbinarycomponents.js b/toolkit/mozapps/extensions/test/xpcshell/test_hasbinarycomponents.js index 925e63626..598e06ed0 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_hasbinarycomponents.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_hasbinarycomponents.js @@ -12,7 +12,7 @@ function run_test() { createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "2"); startupManager(); - + installAllFiles([do_get_addon("test_chromemanifest_1"), do_get_addon("test_chromemanifest_2"), do_get_addon("test_chromemanifest_3"), diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_hotfix.js b/toolkit/mozapps/extensions/test/xpcshell/test_hotfix.js deleted file mode 100644 index c9303897f..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_hotfix.js +++ /dev/null @@ -1,309 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -// This verifies that hotfix installation works - -// The test extension uses an insecure update url. -Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); -// Ignore any certificate requirements the app has set -Services.prefs.setBoolPref("extensions.hotfix.cert.checkAttributes", false); - -Components.utils.import("resource://testing-common/httpd.js"); -var testserver = new HttpServer(); -testserver.start(-1); -gPort = testserver.identity.primaryPort; -testserver.registerDirectory("/addons/", do_get_file("addons")); -mapFile("/data/test_hotfix_1.rdf", testserver); -mapFile("/data/test_hotfix_2.rdf", testserver); -mapFile("/data/test_hotfix_3.rdf", testserver); - -const profileDir = gProfD.clone(); -profileDir.append("extensions"); - -function run_test() { - createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); - - startupManager(); - - do_test_pending(); - run_test_1(); -} - -function end_test() { - testserver.stop(do_test_finished); -} - -// Test that background updates find and install any available hotfix -function run_test_1() { - Services.prefs.setCharPref("extensions.hotfix.id", "hotfix@tests.mozilla.org"); - Services.prefs.setCharPref("extensions.update.background.url", "http://localhost:" + - gPort + "/data/test_hotfix_1.rdf"); - - prepare_test({ - "hotfix@tests.mozilla.org": [ - "onInstalling" - ] - }, [ - "onNewInstall", - "onDownloadStarted", - "onDownloadEnded", - "onInstallStarted", - "onInstallEnded", - ], callback_soon(check_test_1)); - - // We don't need to wait on the promise, just waiting for the install to finish is enough. - AddonManagerInternal.backgroundUpdateCheck(); -} - -function check_test_1() { - restartManager(); - - AddonManager.getAddonByID("hotfix@tests.mozilla.org", function(aAddon) { - do_check_neq(aAddon, null); - do_check_eq(aAddon.version, "1.0"); - - aAddon.uninstall(); - do_execute_soon(run_test_2); - }); -} - -// Don't install an already used hotfix -function run_test_2() { - restartManager(); - - AddonManager.addInstallListener({ - onNewInstall: function() { - do_throw("Should not have seen a new install created"); - } - }); - - // Run the background update - AddonManagerInternal.backgroundUpdateCheck().then(run_test_3); -} - -// Install a newer hotfix -function run_test_3() { - restartManager(); - Services.prefs.setCharPref("extensions.hotfix.url", "http://localhost:" + - gPort + "/data/test_hotfix_2.rdf"); - - prepare_test({ - "hotfix@tests.mozilla.org": [ - "onInstalling" - ] - }, [ - "onNewInstall", - "onDownloadStarted", - "onDownloadEnded", - "onInstallStarted", - "onInstallEnded", - ], callback_soon(check_test_3)); - - AddonManagerInternal.backgroundUpdateCheck(); -} - -function check_test_3() { - restartManager(); - - AddonManager.getAddonByID("hotfix@tests.mozilla.org", function(aAddon) { - do_check_neq(aAddon, null); - do_check_eq(aAddon.version, "2.0"); - - aAddon.uninstall(); - do_execute_soon(run_test_4); - }); -} - -// Don't install an incompatible hotfix -function run_test_4() { - restartManager(); - - Services.prefs.setCharPref("extensions.hotfix.url", "http://localhost:" + - gPort + "/data/test_hotfix_3.rdf"); - - AddonManager.addInstallListener({ - onNewInstall: function() { - do_throw("Should not have seen a new install created"); - } - }); - - AddonManagerInternal.backgroundUpdateCheck().then(run_test_5); -} - -// Don't install an older hotfix -function run_test_5() { - restartManager(); - - Services.prefs.setCharPref("extensions.hotfix.url", "http://localhost:" + - gPort + "/data/test_hotfix_1.rdf"); - - AddonManager.addInstallListener({ - onNewInstall: function() { - do_throw("Should not have seen a new install created"); - } - }); - - AddonManagerInternal.backgroundUpdateCheck().then(run_test_6); -} - -// Don't re-download an already pending install -function run_test_6() { - restartManager(); - - Services.prefs.setCharPref("extensions.hotfix.lastVersion", "0"); - Services.prefs.setCharPref("extensions.hotfix.url", "http://localhost:" + - gPort + "/data/test_hotfix_1.rdf"); - - prepare_test({ - "hotfix@tests.mozilla.org": [ - "onInstalling" - ] - }, [ - "onNewInstall", - "onDownloadStarted", - "onDownloadEnded", - "onInstallStarted", - "onInstallEnded", - ], callback_soon(check_test_6)); - - AddonManagerInternal.backgroundUpdateCheck(); -} - -function check_test_6() { - AddonManager.addInstallListener({ - onNewInstall: function() { - do_throw("Should not have seen a new install created"); - } - }); - - AddonManagerInternal.backgroundUpdateCheck() - .then(promiseRestartManager) - .then(() => promiseAddonByID("hotfix@tests.mozilla.org")) - .then(aAddon => { - aAddon.uninstall(); - run_test_7(); - }); -} - -// Start downloading again if something cancels the install -function run_test_7() { - restartManager(); - - Services.prefs.setCharPref("extensions.hotfix.lastVersion", "0"); - - prepare_test({ - "hotfix@tests.mozilla.org": [ - "onInstalling" - ] - }, [ - "onNewInstall", - "onDownloadStarted", - "onDownloadEnded", - "onInstallStarted", - "onInstallEnded", - ], check_test_7); - - AddonManagerInternal.backgroundUpdateCheck(); -} - -function check_test_7(aInstall) { - prepare_test({ - "hotfix@tests.mozilla.org": [ - "onOperationCancelled" - ] - }, [ - "onInstallCancelled", - ]); - - aInstall.cancel(); - - prepare_test({ - "hotfix@tests.mozilla.org": [ - "onInstalling" - ] - }, [ - "onNewInstall", - "onDownloadStarted", - "onDownloadEnded", - "onInstallStarted", - "onInstallEnded", - ], callback_soon(finish_test_7)); - - AddonManagerInternal.backgroundUpdateCheck(); -} - -function finish_test_7() { - restartManager(); - - AddonManager.getAddonByID("hotfix@tests.mozilla.org", function(aAddon) { - do_check_neq(aAddon, null); - do_check_eq(aAddon.version, "1.0"); - - aAddon.uninstall(); - do_execute_soon(run_test_8); - }); -} - -// Cancel a pending install when a newer version is already available -function run_test_8() { - restartManager(); - - Services.prefs.setCharPref("extensions.hotfix.lastVersion", "0"); - Services.prefs.setCharPref("extensions.hotfix.url", "http://localhost:" + - gPort + "/data/test_hotfix_1.rdf"); - - prepare_test({ - "hotfix@tests.mozilla.org": [ - "onInstalling" - ] - }, [ - "onNewInstall", - "onDownloadStarted", - "onDownloadEnded", - "onInstallStarted", - "onInstallEnded", - ], check_test_8); - - AddonManagerInternal.backgroundUpdateCheck(); -} - -function check_test_8() { - Services.prefs.setCharPref("extensions.hotfix.url", "http://localhost:" + - gPort + "/data/test_hotfix_2.rdf"); - - prepare_test({ - "hotfix@tests.mozilla.org": [ - "onOperationCancelled", - "onInstalling" - ] - }, [ - "onNewInstall", - "onDownloadStarted", - "onDownloadEnded", - "onInstallStarted", - "onInstallCancelled", - "onInstallEnded", - ], finish_test_8); - - AddonManagerInternal.backgroundUpdateCheck(); -} - -function finish_test_8() { - AddonManager.getAllInstalls(callback_soon(function(aInstalls) { - do_check_eq(aInstalls.length, 1); - do_check_eq(aInstalls[0].version, "2.0"); - - restartManager(); - - AddonManager.getAddonByID("hotfix@tests.mozilla.org", callback_soon(function(aAddon) { - do_check_neq(aAddon, null); - do_check_eq(aAddon.version, "2.0"); - - aAddon.uninstall(); - restartManager(); - - end_test(); - })); - })); -} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_hotfix_cert.js b/toolkit/mozapps/extensions/test/xpcshell/test_hotfix_cert.js deleted file mode 100644 index 42ee59740..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_hotfix_cert.js +++ /dev/null @@ -1,167 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -// This verifies that hotfix installation works -const PREF_EM_HOTFIX_ID = "extensions.hotfix.id"; -const PREF_EM_HOTFIX_LASTVERSION = "extensions.hotfix.lastVersion"; -const PREF_EM_HOTFIX_URL = "extensions.hotfix.url"; -const PREF_EM_CERT_CHECKATTRIBUTES = "extensions.hotfix.cert.checkAttributes"; -const PREF_EM_HOTFIX_CERTS = "extensions.hotfix.certs."; - -// Derived from "openssl x509 -in firefox-hotfix.crt -fingerprint -sha1" -const GOOD_FINGERPRINT = "39:E7:2B:7A:5B:CF:37:78:F9:5D:4A:E0:53:2D:2F:3D:68:53:C5:60"; -const BAD_FINGERPRINT = "40:E7:2B:7A:5B:CF:37:78:F9:5D:4A:E0:53:2D:2F:3D:68:53:C5:60"; - -Components.utils.import("resource://testing-common/httpd.js"); -var testserver = new HttpServer(); -testserver.start(-1); -gPort = testserver.identity.primaryPort; -testserver.registerDirectory("/data/", do_get_file("data")); - -// The test extension uses an insecure update url. -Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); -// Ignore any certificate requirements the app has set -Services.prefs.setBoolPref(PREF_EM_CERT_CHECKATTRIBUTES, true); -Services.prefs.setCharPref(PREF_EM_HOTFIX_URL, "http://localhost:" + gPort + "/hotfix.rdf"); -// Clear out all hotfix cert prefs to make sure only the test prefs apply. -var defaults = Services.prefs.getDefaultBranch(""); -defaults.deleteBranch(PREF_EM_HOTFIX_CERTS); - -/* - * Register an addon install listener and return a promise that: - * resolves with the AddonInstall object if the install succeeds - * rejects with the AddonInstall if the install fails - */ -function promiseInstallListener() { - return new Promise((resolve, reject) => { - let listener = { - onDownloadFailed: ai => { - AddonManager.removeInstallListener(listener); - reject(ai); - }, - onInstallEnded: ai => { - AddonManager.removeInstallListener(listener); - resolve(ai); - }, - onDownloadCancelled: ai => { - AddonManager.removeInstallListener(listener); - reject(ai); - } - }; - AddonManager.addInstallListener(listener); - }); -} - -function promiseSuccessfulInstall() { - return promiseInstallListener().then( - aInstall => { - do_check_true(true); - do_check_eq(aInstall.addon.id, Services.prefs.getCharPref(PREF_EM_HOTFIX_ID)); - aInstall.addon.uninstall(); - Services.prefs.clearUserPref(PREF_EM_HOTFIX_LASTVERSION); - }, - aInstall => { - do_throw("Install should not have failed"); - }); -} - -function promiseFailedInstall() { - return promiseInstallListener().then( - aInstall => { - do_throw("Install should not have succeeded"); - aInstall.addon.uninstall(); - Services.prefs.clearUserPref(PREF_EM_HOTFIX_LASTVERSION); - }, - aInstall => { - do_check_true(true); - }); -} - -var tryInstallHotfix = Task.async(function*(id, file, installListener) { - Services.prefs.setCharPref(PREF_EM_HOTFIX_ID, id); - - testserver.registerPathHandler("/hotfix.rdf", function(request, response) { - response.write(createUpdateRDF({ - [id]: [{ - version: "1.0", - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "0", - maxVersion: "*", - updateLink: "http://localhost:" + gPort + "/data/signing_checks/" + file, - }] - }] - })); - }); - - yield Promise.all([ - installListener, - AddonManagerPrivate.backgroundUpdateCheck() - ]); - - testserver.registerPathHandler("/hotfix.rdf", null); - Services.prefs.clearUserPref(PREF_EM_HOTFIX_ID); -}); - -// Test valid AMO hotfix signed add-ons doesn't work if the fingerprint pref is wrong -add_task(function* amo_signed_hotfix() { - Services.prefs.setCharPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint", BAD_FINGERPRINT); - - yield tryInstallHotfix("firefox-hotfix@mozilla.org", - "hotfix_good.xpi", - promiseFailedInstall()); -}); - -// Test valid AMO hotfix signed add-ons works -add_task(function* amo_signed_hotfix() { - Services.prefs.setCharPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint", GOOD_FINGERPRINT); - - yield tryInstallHotfix("firefox-hotfix@mozilla.org", - "hotfix_good.xpi", - promiseSuccessfulInstall()); -}); - -// A hotfix altered after signing should fail -add_task(function* amo_broken_hotfix() { - yield tryInstallHotfix("firefox-hotfix@mozilla.org", - "hotfix_broken.xpi", - promiseFailedInstall()); -}); - -// Test an add-on with the wrong ID but signed by the right cert fails -add_task(function* amo_wrongID_rightcert() { - yield tryInstallHotfix("test@tests.mozilla.org", - "hotfix_badid.xpi", - promiseFailedInstall()); -}); - -// It shouldn't matter that it requested the ID matching the cert to begin with -// if the embedded cert's ID doesn't match the add-on's ID -add_task(function* amo_wrongID_rightcert2() { - yield tryInstallHotfix("firefox-hotfix@mozilla.org", - "hotfix_badid.xpi", - promiseFailedInstall()); -}); - -// Test something signed by a regular AMO cert doesn't work -add_task(function* amo_signed_addon() { - yield tryInstallHotfix("test@tests.mozilla.org", - "signed_bootstrap_1.xpi", - promiseFailedInstall()); -}); - -// Test totally unsigned add-on fails -add_task(function* unsigned() { - yield tryInstallHotfix("test@tests.mozilla.org", - "unsigned_bootstrap_2.xpi", - promiseFailedInstall()); -}); - -function run_test() { - createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "2"); - - startupManager(); - - run_next_test(); -} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_install.js b/toolkit/mozapps/extensions/test/xpcshell/test_install.js index 60af3a9fd..16db604c5 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_install.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_install.js @@ -3,9 +3,14 @@ */ // This verifies that add-ons can be installed from XPI files -var Cc = Components.classes; -var Ci = Components.interfaces; -var Cu = Components.utils; +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cu = Components.utils; + +// Maximum error in file modification times. Some file systems don't store +// modification times exactly. As long as we are closer than this then it +// still passes. +const MAX_TIME_DIFFERENCE = 3000; // install.rdf size, icon.png, icon64.png size const ADDON1_SIZE = 705 + 16 + 16; @@ -140,8 +145,6 @@ function check_test_1(installSyncGUID) { else { let iconFile = uri.QueryInterface(AM_Ci.nsIFileURL).file; do_check_true(iconFile.exists()); - // Make the iconFile predictably old. - iconFile.lastModifiedTime = Date.now() - MAKE_FILE_OLD_DIFFERENCE; } // Make the pending install have a sensible date @@ -186,23 +189,14 @@ function check_test_1(installSyncGUID) { do_check_true(a1.hasResource("install.rdf")); do_check_false(a1.hasResource("foo.bar")); - let uri2 = do_get_addon_root_uri(profileDir, "addon1@tests.mozilla.org"); - do_check_eq(a1.getResourceURI("install.rdf").spec, uri2 + "install.rdf"); - do_check_eq(a1.iconURL, uri2 + "icon.png"); - do_check_eq(a1.icon64URL, uri2 + "icon64.png"); - - // Ensure that extension bundle (or icon if unpacked) has updated - // lastModifiedDate. - let testURI = a1.getResourceURI(TEST_UNPACKED ? "icon.png" : ""); - let testFile = testURI.QueryInterface(Components.interfaces.nsIFileURL).file; - do_check_true(testFile.exists()); - difference = testFile.lastModifiedTime - Date.now(); - do_check_true(Math.abs(difference) < MAX_TIME_DIFFERENCE); + let uri = do_get_addon_root_uri(profileDir, "addon1@tests.mozilla.org"); + do_check_eq(a1.getResourceURI("install.rdf").spec, uri + "install.rdf"); + do_check_eq(a1.iconURL, uri + "icon.png"); + do_check_eq(a1.icon64URL, uri + "icon64.png"); a1.uninstall(); - let { id, version } = a1; restartManager(); - do_check_not_in_crash_annotation(id, version); + do_check_not_in_crash_annotation(a1.id, a1.version); do_execute_soon(run_test_2); })); @@ -233,7 +227,7 @@ function run_test_2() { ], check_test_2); install.addListener({ - onDownloadProgress: function() { + onDownloadProgress: function(install) { do_execute_soon(function() { Components.utils.forceGC(); }); @@ -387,8 +381,8 @@ function check_test_5(install) { do_check_eq(installs[0].addon, olda2.pendingUpgrade); restartManager(); - AddonManager.getInstallsByTypes(null, function(installs2) { - do_check_eq(installs2.length, 0); + AddonManager.getInstallsByTypes(null, function(installs) { + do_check_eq(installs.length, 0); AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { do_check_neq(a2, null); @@ -656,8 +650,6 @@ function run_test_11() { "onNewInstall", "onNewInstall", "onNewInstall", - "onNewInstall", - "onNewInstall", "onNewInstall" ]); @@ -665,22 +657,11 @@ function run_test_11() { ensure_test_completed(); do_check_neq(install, null); do_check_neq(install.linkedInstalls, null); - do_check_eq(install.linkedInstalls.length, 5); + do_check_eq(install.linkedInstalls.length, 3); // Might be in any order so sort them based on ID let installs = [install].concat(install.linkedInstalls); installs.sort(function(a, b) { - if (a.state != b.state) { - if (a.state == AddonManager.STATE_DOWNLOAD_FAILED) - return 1; - else if (b.state == AddonManager.STATE_DOWNLOAD_FAILED) - return -1; - } - - // Don't care what order the failed installs show up in - if (a.state == AddonManager.STATE_DOWNLOAD_FAILED) - return 0; - if (a.addon.id < b.addon.id) return -1; if (a.addon.id > b.addon.id) @@ -728,12 +709,6 @@ function run_test_11() { do_check_true(hasFlag(installs[3].addon.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_INSTALL)); - do_check_eq(installs[4].state, AddonManager.STATE_DOWNLOAD_FAILED); - do_check_eq(installs[4].error, AddonManager.ERROR_CORRUPT_FILE); - - do_check_eq(installs[5].state, AddonManager.STATE_DOWNLOAD_FAILED); - do_check_eq(installs[5].error, AddonManager.ERROR_CORRUPT_FILE); - AddonManager.getAllInstalls(function(aInstalls) { do_check_eq(aInstalls.length, 4); @@ -840,8 +815,6 @@ function run_test_12() { "onNewInstall", "onNewInstall", "onNewInstall", - "onNewInstall", - "onNewInstall", "onDownloadEnded" ], "addon4@tests.mozilla.org": [ @@ -866,22 +839,11 @@ function run_test_12() { } function check_test_12() { - do_check_eq(gInstall.linkedInstalls.length, 5); + do_check_eq(gInstall.linkedInstalls.length, 3); // Might be in any order so sort them based on ID let installs = [gInstall].concat(gInstall.linkedInstalls); installs.sort(function(a, b) { - if (a.state != b.state) { - if (a.state == AddonManager.STATE_DOWNLOAD_FAILED) - return 1; - else if (b.state == AddonManager.STATE_DOWNLOAD_FAILED) - return -1; - } - - // Don't care what order the failed installs show up in - if (a.state == AddonManager.STATE_DOWNLOAD_FAILED) - return 0; - if (a.addon.id < b.addon.id) return -1; if (a.addon.id > b.addon.id) @@ -921,12 +883,6 @@ function check_test_12() { do_check_eq(installs[3].name, "Multi Test 4"); do_check_eq(installs[3].state, AddonManager.STATE_INSTALLED); - do_check_eq(installs[4].state, AddonManager.STATE_DOWNLOAD_FAILED); - do_check_eq(installs[4].error, AddonManager.ERROR_CORRUPT_FILE); - - do_check_eq(installs[5].state, AddonManager.STATE_DOWNLOAD_FAILED); - do_check_eq(installs[5].error, AddonManager.ERROR_CORRUPT_FILE); - restartManager(); AddonManager.getAddonsByIDs(["addon4@tests.mozilla.org", @@ -1148,26 +1104,26 @@ function run_test_16() { do_check_true(a2.userDisabled); do_check_false(a2.isActive); - let url_2 = "http://localhost:" + gPort + "/addons/test_install2_2.xpi"; - AddonManager.getInstallForURL(url_2, function(aInstall_2) { - aInstall_2.addListener({ + let url = "http://localhost:" + gPort + "/addons/test_install2_2.xpi"; + AddonManager.getInstallForURL(url, function(aInstall) { + aInstall.addListener({ onInstallEnded: function() { do_execute_soon(function install2_2_ended() { - do_check_true(aInstall_2.addon.userDisabled); + do_check_true(aInstall.addon.userDisabled); restartManager(); - AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2_2) { - do_check_true(a2_2.userDisabled); - do_check_false(a2_2.isActive); + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { + do_check_true(a2.userDisabled); + do_check_false(a2.isActive); - a2_2.uninstall(); + a2.uninstall(); do_execute_soon(run_test_17); }); }); } }); - aInstall_2.install(); + aInstall.install(); }, "application/x-xpinstall"); }); }); @@ -1194,29 +1150,29 @@ function run_test_17() { do_check_false(a2.userDisabled); do_check_true(a2.isActive); - let url_2 = "http://localhost:" + gPort + "/addons/test_install2_2.xpi"; - AddonManager.getInstallForURL(url_2, function(aInstall_2) { - aInstall_2.addListener({ + let url = "http://localhost:" + gPort + "/addons/test_install2_2.xpi"; + AddonManager.getInstallForURL(url, function(aInstall) { + aInstall.addListener({ onInstallStarted: function() { - do_check_false(aInstall_2.addon.userDisabled); - aInstall_2.addon.userDisabled = true; + do_check_false(aInstall.addon.userDisabled); + aInstall.addon.userDisabled = true; }, onInstallEnded: function() { do_execute_soon(function install2_2_ended2() { restartManager(); - AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2_2) { - do_check_true(a2_2.userDisabled); - do_check_false(a2_2.isActive); + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { + do_check_true(a2.userDisabled); + do_check_false(a2.isActive); - a2_2.uninstall(); + a2.uninstall(); do_execute_soon(run_test_18); }); }); } }); - aInstall_2.install(); + aInstall.install(); }, "application/x-xpinstall"); }); }); @@ -1246,29 +1202,29 @@ function run_test_18() { do_check_true(a2.userDisabled); do_check_false(a2.isActive); - let url_2 = "http://localhost:" + gPort + "/addons/test_install2_2.xpi"; - AddonManager.getInstallForURL(url_2, function(aInstall_2) { - aInstall_2.addListener({ + let url = "http://localhost:" + gPort + "/addons/test_install2_2.xpi"; + AddonManager.getInstallForURL(url, function(aInstall) { + aInstall.addListener({ onInstallStarted: function() { - do_check_true(aInstall_2.addon.userDisabled); - aInstall_2.addon.userDisabled = false; + do_check_true(aInstall.addon.userDisabled); + aInstall.addon.userDisabled = false; }, onInstallEnded: function() { do_execute_soon(function install_2_2_ended3() { restartManager(); - AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2_2) { - do_check_false(a2_2.userDisabled); - do_check_true(a2_2.isActive); + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { + do_check_false(a2.userDisabled); + do_check_true(a2.isActive); - a2_2.uninstall(); + a2.uninstall(); do_execute_soon(run_test_18_1); }); }); } }); - aInstall_2.install(); + aInstall.install(); }, "application/x-xpinstall"); }); }); @@ -1292,7 +1248,7 @@ function run_test_18_1() { let url = "http://localhost:" + gPort + "/addons/test_install2_1.xpi"; AddonManager.getInstallForURL(url, function(aInstall) { aInstall.addListener({ - onInstallEnded: function(unused, aAddon) { + onInstallEnded: function(aInstall, aAddon) { do_execute_soon(function test18_1_install_ended() { do_check_neq(aAddon.fullDescription, "Repository description"); @@ -1320,7 +1276,7 @@ function run_test_19() { let url = "http://localhost:" + gPort + "/addons/test_install2_1.xpi"; AddonManager.getInstallForURL(url, function(aInstall) { aInstall.addListener({ - onInstallEnded: function(unused, aAddon) { + onInstallEnded: function(aInstall, aAddon) { do_execute_soon(function test19_install_ended() { do_check_eq(aAddon.fullDescription, "Repository description"); @@ -1346,7 +1302,7 @@ function run_test_20() { let url = "http://localhost:" + gPort + "/addons/test_install2_1.xpi"; AddonManager.getInstallForURL(url, function(aInstall) { aInstall.addListener({ - onInstallEnded: function(unused, aAddon) { + onInstallEnded: function(aInstall, aAddon) { do_execute_soon(function test20_install_ended() { do_check_eq(aAddon.fullDescription, "Repository description"); @@ -1633,8 +1589,8 @@ function run_test_26() { let url = "http://localhost:" + gPort + "/redirect?/addons/test_install1.xpi"; AddonManager.getInstallForURL(url, function(aInstall) { aInstall.addListener({ - onDownloadProgress: function(aDownloadProgressInstall) { - aDownloadProgressInstall.cancel(); + onDownloadProgress: function(aInstall) { + aInstall.cancel(); } }); @@ -1791,7 +1747,7 @@ function run_test_29() { } function check_test_29(install) { - // ensure_test_completed(); + //ensure_test_completed(); do_check_eq(install.state, AddonManager.STATE_DOWNLOADED); do_check_neq(install.addon, null); do_check_false(install.addon.isCompatible); @@ -1799,45 +1755,7 @@ function check_test_29(install) { prepare_test({}, [ "onDownloadCancelled" - ], run_test_30); + ], do_test_finished); install.cancel(); return false; } - -// Tests that a multi-package XPI with no add-ons inside shows up as a -// corrupt file -function run_test_30() { - prepare_test({ }, [ - "onNewInstall" - ]); - - AddonManager.getInstallForFile(do_get_addon("test_install7"), function(install) { - ensure_test_completed(); - - do_check_neq(install, null); - do_check_eq(install.state, AddonManager.STATE_DOWNLOAD_FAILED); - do_check_eq(install.error, AddonManager.ERROR_CORRUPT_FILE); - do_check_eq(install.linkedInstalls, null); - - run_test_31(); - }); -} - -// Tests that a multi-package XPI with no valid add-ons inside shows up as a -// corrupt file -function run_test_31() { - prepare_test({ }, [ - "onNewInstall" - ]); - - AddonManager.getInstallForFile(do_get_addon("test_install8"), function(install) { - ensure_test_completed(); - - do_check_neq(install, null); - do_check_eq(install.state, AddonManager.STATE_DOWNLOAD_FAILED); - do_check_eq(install.error, AddonManager.ERROR_CORRUPT_FILE); - do_check_eq(install.linkedInstalls, null); - - end_test(); - }); -} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_install_from_sources.js b/toolkit/mozapps/extensions/test/xpcshell/test_install_from_sources.js deleted file mode 100644 index 18bb7d74e..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_install_from_sources.js +++ /dev/null @@ -1,80 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -const ID = "bootstrap1@tests.mozilla.org"; -createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "42"); -startupManager(); - -BootstrapMonitor.init(); - -// Partial list of bootstrap reasons from XPIProvider.jsm -const BOOTSTRAP_REASONS = { - ADDON_INSTALL: 5, - ADDON_UPGRADE: 7, - ADDON_DOWNGRADE: 8, -}; - -// Install an unsigned add-on with no existing add-on present. -// Restart and make sure it is still around. -add_task(function*() { - let extInstallCalled = false; - AddonManager.addInstallListener({ - onExternalInstall: (aInstall) => { - do_check_eq(aInstall.id, ID); - do_check_eq(aInstall.version, "1.0"); - extInstallCalled = true; - }, - }); - - let installingCalled = false; - let installedCalled = false; - AddonManager.addAddonListener({ - onInstalling: (aInstall) => { - do_check_eq(aInstall.id, ID); - do_check_eq(aInstall.version, "1.0"); - installingCalled = true; - }, - onInstalled: (aInstall) => { - do_check_eq(aInstall.id, ID); - do_check_eq(aInstall.version, "1.0"); - installedCalled = true; - }, - onInstallStarted: (aInstall) => { - do_throw("onInstallStarted called unexpectedly"); - } - }); - - yield AddonManager.installAddonFromSources(do_get_file("data/from_sources/")); - - do_check_true(extInstallCalled); - do_check_true(installingCalled); - do_check_true(installedCalled); - - let install = BootstrapMonitor.checkAddonInstalled(ID, "1.0"); - equal(install.reason, BOOTSTRAP_REASONS.ADDON_INSTALL); - BootstrapMonitor.checkAddonStarted(ID, "1.0"); - - let addon = yield promiseAddonByID(ID); - - do_check_neq(addon, null); - do_check_eq(addon.version, "1.0"); - do_check_eq(addon.name, "Test Bootstrap 1"); - do_check_true(addon.isCompatible); - do_check_false(addon.appDisabled); - do_check_true(addon.isActive); - do_check_eq(addon.type, "extension"); - do_check_eq(addon.signedState, mozinfo.addon_signing ? AddonManager.SIGNEDSTATE_SIGNED : AddonManager.SIGNEDSTATE_NOT_REQUIRED); - - yield promiseRestartManager(); - - install = BootstrapMonitor.checkAddonInstalled(ID, "1.0"); - equal(install.reason, BOOTSTRAP_REASONS.ADDON_INSTALL); - BootstrapMonitor.checkAddonStarted(ID, "1.0"); - - addon = yield promiseAddonByID(ID); - do_check_neq(addon, null); - - yield promiseRestartManager(); -}); - diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_install_strictcompat.js b/toolkit/mozapps/extensions/test/xpcshell/test_install_strictcompat.js index 77f806ba2..0c7003d59 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_install_strictcompat.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_install_strictcompat.js @@ -3,9 +3,14 @@ */ // This verifies that add-ons can be installed from XPI files -var Cc = Components.classes; -var Ci = Components.interfaces; -var Cu = Components.utils; +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cu = Components.utils; + +// Maximum error in file modification times. Some file systems don't store +// modification times exactly. As long as we are closer than this then it +// still passes. +const MAX_TIME_DIFFERENCE = 3000; // install.rdf size, icon.png, icon64.png size const ADDON1_SIZE = 705 + 16 + 16; @@ -177,13 +182,13 @@ function check_test_1() { do_check_true(a1.hasResource("install.rdf")); do_check_false(a1.hasResource("foo.bar")); - let root_uri = do_get_addon_root_uri(profileDir, "addon1@tests.mozilla.org"); - do_check_eq(a1.getResourceURI("install.rdf").spec, root_uri + "install.rdf"); - do_check_eq(a1.iconURL, root_uri + "icon.png"); - do_check_eq(a1.icon64URL, root_uri + "icon64.png"); + let uri = do_get_addon_root_uri(profileDir, "addon1@tests.mozilla.org"); + do_check_eq(a1.getResourceURI("install.rdf").spec, uri + "install.rdf"); + do_check_eq(a1.iconURL, uri + "icon.png"); + do_check_eq(a1.icon64URL, uri + "icon64.png"); a1.uninstall(); - do_execute_soon(function() { run_test_2(a1) }); + do_execute_soon(function(){run_test_2(a1)}); }); }); })); @@ -192,9 +197,8 @@ function check_test_1() { // Tests that an install from a url downloads. function run_test_2(aAddon) { - let { id, version } = aAddon; restartManager(); - do_check_not_in_crash_annotation(id, version); + do_check_not_in_crash_annotation(aAddon.id, aAddon.version); let url = "http://localhost:4444/addons/test_install2_1.xpi"; AddonManager.getInstallForURL(url, function(install) { @@ -216,7 +220,7 @@ function run_test_2(aAddon) { ], check_test_2); install.addListener({ - onDownloadProgress: function() { + onDownloadProgress: function(install) { do_execute_soon(function() { Components.utils.forceGC(); }); @@ -369,8 +373,8 @@ function check_test_5(install) { do_check_eq(installs[0].addon, olda2.pendingUpgrade); restartManager(); - AddonManager.getInstallsByTypes(null, function(installs2) { - do_check_eq(installs2.length, 0); + AddonManager.getInstallsByTypes(null, function(installs) { + do_check_eq(installs.length, 0); AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { do_check_neq(a2, null); @@ -635,8 +639,6 @@ function run_test_11() { "onNewInstall", "onNewInstall", "onNewInstall", - "onNewInstall", - "onNewInstall", "onNewInstall" ]); @@ -644,22 +646,11 @@ function run_test_11() { ensure_test_completed(); do_check_neq(install, null); do_check_neq(install.linkedInstalls, null); - do_check_eq(install.linkedInstalls.length, 5); + do_check_eq(install.linkedInstalls.length, 3); // Might be in any order so sort them based on ID let installs = [install].concat(install.linkedInstalls); installs.sort(function(a, b) { - if (a.state != b.state) { - if (a.state == AddonManager.STATE_DOWNLOAD_FAILED) - return 1; - else if (b.state == AddonManager.STATE_DOWNLOAD_FAILED) - return -1; - } - - // Don't care what order the failed installs show up in - if (a.state == AddonManager.STATE_DOWNLOAD_FAILED) - return 0; - if (a.addon.id < b.addon.id) return -1; if (a.addon.id > b.addon.id) @@ -707,12 +698,6 @@ function run_test_11() { do_check_true(hasFlag(installs[3].addon.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_INSTALL)); - do_check_eq(installs[4].state, AddonManager.STATE_DOWNLOAD_FAILED); - do_check_eq(installs[4].error, AddonManager.ERROR_CORRUPT_FILE); - - do_check_eq(installs[5].state, AddonManager.STATE_DOWNLOAD_FAILED); - do_check_eq(installs[5].error, AddonManager.ERROR_CORRUPT_FILE); - AddonManager.getAllInstalls(function(aInstalls) { do_check_eq(aInstalls.length, 4); @@ -821,8 +806,6 @@ function run_test_12() { "onNewInstall", "onNewInstall", "onNewInstall", - "onNewInstall", - "onNewInstall", "onDownloadEnded" ], "addon4@tests.mozilla.org": [ @@ -847,22 +830,11 @@ function run_test_12() { } function check_test_12() { - do_check_eq(gInstall.linkedInstalls.length, 5); + do_check_eq(gInstall.linkedInstalls.length, 3); // Might be in any order so sort them based on ID let installs = [gInstall].concat(gInstall.linkedInstalls); installs.sort(function(a, b) { - if (a.state != b.state) { - if (a.state == AddonManager.STATE_DOWNLOAD_FAILED) - return 1; - else if (b.state == AddonManager.STATE_DOWNLOAD_FAILED) - return -1; - } - - // Don't care what order the failed installs show up in - if (a.state == AddonManager.STATE_DOWNLOAD_FAILED) - return 0; - if (a.addon.id < b.addon.id) return -1; if (a.addon.id > b.addon.id) @@ -902,12 +874,6 @@ function check_test_12() { do_check_eq(installs[3].name, "Multi Test 4"); do_check_eq(installs[3].state, AddonManager.STATE_INSTALLED); - do_check_eq(installs[4].state, AddonManager.STATE_DOWNLOAD_FAILED); - do_check_eq(installs[4].error, AddonManager.ERROR_CORRUPT_FILE); - - do_check_eq(installs[5].state, AddonManager.STATE_DOWNLOAD_FAILED); - do_check_eq(installs[5].error, AddonManager.ERROR_CORRUPT_FILE); - restartManager(); AddonManager.getAddonsByIDs(["addon4@tests.mozilla.org", @@ -1129,26 +1095,26 @@ function run_test_16() { do_check_true(a2.userDisabled); do_check_false(a2.isActive); - let url_2 = "http://localhost:4444/addons/test_install2_2.xpi"; - AddonManager.getInstallForURL(url_2, function(aInstall_2) { - aInstall_2.addListener({ + let url = "http://localhost:4444/addons/test_install2_2.xpi"; + AddonManager.getInstallForURL(url, function(aInstall) { + aInstall.addListener({ onInstallEnded: function() { do_execute_soon(function test16_install2() { - do_check_true(aInstall_2.addon.userDisabled); + do_check_true(aInstall.addon.userDisabled); restartManager(); - AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2_2) { - do_check_true(a2_2.userDisabled); - do_check_false(a2_2.isActive); + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { + do_check_true(a2.userDisabled); + do_check_false(a2.isActive); - a2_2.uninstall(); + a2.uninstall(); do_execute_soon(run_test_17); }); }); } }); - aInstall_2.install(); + aInstall.install(); }, "application/x-xpinstall"); }); }); @@ -1166,7 +1132,7 @@ function run_test_17() { AddonManager.getInstallForURL(url, function(aInstall) { aInstall.addListener({ onInstallEnded: function() { - do_execute_soon(function() { + do_execute_soon(function test17_install1() { do_check_false(aInstall.addon.userDisabled); restartManager(); @@ -1175,29 +1141,29 @@ function run_test_17() { do_check_false(a2.userDisabled); do_check_true(a2.isActive); - let url_2 = "http://localhost:4444/addons/test_install2_2.xpi"; - AddonManager.getInstallForURL(url_2, function(aInstall_2) { - aInstall_2.addListener({ + let url = "http://localhost:4444/addons/test_install2_2.xpi"; + AddonManager.getInstallForURL(url, function(aInstall) { + aInstall.addListener({ onInstallStarted: function() { - do_check_false(aInstall_2.addon.userDisabled); - aInstall_2.addon.userDisabled = true; + do_check_false(aInstall.addon.userDisabled); + aInstall.addon.userDisabled = true; }, onInstallEnded: function() { - do_execute_soon(function() { + do_execute_soon(function test17_install1() { restartManager(); - AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2_2) { - do_check_true(a2_2.userDisabled); - do_check_false(a2_2.isActive); + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { + do_check_true(a2.userDisabled); + do_check_false(a2.isActive); - a2_2.uninstall(); + a2.uninstall(); do_execute_soon(run_test_18); }); }); } }); - aInstall_2.install(); + aInstall.install(); }, "application/x-xpinstall"); }); }); @@ -1227,29 +1193,29 @@ function run_test_18() { do_check_true(a2.userDisabled); do_check_false(a2.isActive); - let url_2 = "http://localhost:4444/addons/test_install2_2.xpi"; - AddonManager.getInstallForURL(url_2, function(aInstall_2) { - aInstall_2.addListener({ + let url = "http://localhost:4444/addons/test_install2_2.xpi"; + AddonManager.getInstallForURL(url, function(aInstall) { + aInstall.addListener({ onInstallStarted: function() { - do_check_true(aInstall_2.addon.userDisabled); - aInstall_2.addon.userDisabled = false; + do_check_true(aInstall.addon.userDisabled); + aInstall.addon.userDisabled = false; }, onInstallEnded: function() { do_execute_soon(function test18_install2() { restartManager(); - AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2_2) { - do_check_false(a2_2.userDisabled); - do_check_true(a2_2.isActive); + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { + do_check_false(a2.userDisabled); + do_check_true(a2.isActive); - a2_2.uninstall(); + a2.uninstall(); do_execute_soon(run_test_18_1); }); }); } }); - aInstall_2.install(); + aInstall.install(); }, "application/x-xpinstall"); }); }); @@ -1273,7 +1239,7 @@ function run_test_18_1() { let url = "http://localhost:4444/addons/test_install2_1.xpi"; AddonManager.getInstallForURL(url, function(aInstall) { aInstall.addListener({ - onInstallEnded: function(unused, aAddon) { + onInstallEnded: function(aInstall, aAddon) { do_execute_soon(function test18_install() { do_check_neq(aAddon.fullDescription, "Repository description"); @@ -1301,7 +1267,7 @@ function run_test_19() { let url = "http://localhost:4444/addons/test_install2_1.xpi"; AddonManager.getInstallForURL(url, function(aInstall) { aInstall.addListener({ - onInstallEnded: function(unused, aAddon) { + onInstallEnded: function(aInstall, aAddon) { do_execute_soon(function test19_install() { do_check_eq(aAddon.fullDescription, "Repository description"); @@ -1327,7 +1293,7 @@ function run_test_20() { let url = "http://localhost:4444/addons/test_install2_1.xpi"; AddonManager.getInstallForURL(url, function(aInstall) { aInstall.addListener({ - onInstallEnded: function(unused, aAddon) { + onInstallEnded: function(aInstall, aAddon) { do_execute_soon(function test20_install() { do_check_eq(aAddon.fullDescription, "Repository description"); @@ -1614,8 +1580,8 @@ function run_test_26() { let url = "http://localhost:4444/redirect?/addons/test_install1.xpi"; AddonManager.getInstallForURL(url, function(aInstall) { aInstall.addListener({ - onDownloadProgress: function(aDownloadProgressInstall) { - aDownloadProgressInstall.cancel(); + onDownloadProgress: function(aInstall) { + aInstall.cancel(); } }); @@ -1684,43 +1650,5 @@ function finish_test_27(aInstall) { ensure_test_completed(); - run_test_30(); -} - -// Tests that a multi-package XPI with no add-ons inside shows up as a -// corrupt file -function run_test_30() { - prepare_test({ }, [ - "onNewInstall" - ]); - - AddonManager.getInstallForFile(do_get_addon("test_install7"), function(install) { - ensure_test_completed(); - - do_check_neq(install, null); - do_check_eq(install.state, AddonManager.STATE_DOWNLOAD_FAILED); - do_check_eq(install.error, AddonManager.ERROR_CORRUPT_FILE); - do_check_eq(install.linkedInstalls, null); - - run_test_31(); - }); -} - -// Tests that a multi-package XPI with no valid add-ons inside shows up as a -// corrupt file -function run_test_31() { - prepare_test({ }, [ - "onNewInstall" - ]); - - AddonManager.getInstallForFile(do_get_addon("test_install8"), function(install) { - ensure_test_completed(); - - do_check_neq(install, null); - do_check_eq(install.state, AddonManager.STATE_DOWNLOAD_FAILED); - do_check_eq(install.error, AddonManager.ERROR_CORRUPT_FILE); - do_check_eq(install.linkedInstalls, null); - - end_test(); - }); + end_test(); } diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_isDebuggable.js b/toolkit/mozapps/extensions/test/xpcshell/test_isDebuggable.js index 87f2856b0..d4f8a482b 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_isDebuggable.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_isDebuggable.js @@ -17,7 +17,7 @@ var IDS = [ function run_test() { do_test_pending(); - + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "2"); startupManager(); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_json_updatecheck.js b/toolkit/mozapps/extensions/test/xpcshell/test_json_updatecheck.js deleted file mode 100644 index adf789afb..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_json_updatecheck.js +++ /dev/null @@ -1,372 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ -"use strict"; - -// This verifies that AddonUpdateChecker works correctly for JSON -// update manifests, particularly for behavior which does not -// cleanly overlap with RDF manifests. - -const TOOLKIT_ID = "toolkit@mozilla.org"; -const TOOLKIT_MINVERSION = "42.0a1"; - -createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "42.0a2", "42.0a2"); - -Components.utils.import("resource://gre/modules/addons/AddonUpdateChecker.jsm"); - -let testserver = createHttpServer(); -gPort = testserver.identity.primaryPort; - -let gUpdateManifests = {}; - -function mapManifest(aPath, aManifestData) { - gUpdateManifests[aPath] = aManifestData; - testserver.registerPathHandler(aPath, serveManifest); -} - -function serveManifest(request, response) { - let manifest = gUpdateManifests[request.path]; - - response.setHeader("Content-Type", manifest.contentType, false); - response.write(manifest.data); -} - -const extensionsDir = gProfD.clone(); -extensionsDir.append("extensions"); - - -function checkUpdates(aData) { - // Registers JSON update manifest for it with the testing server, - // checks for updates, and yields the list of updates on - // success. - - let extension = aData.manifestExtension || "json"; - - let path = `/updates/${aData.id}.${extension}`; - let updateUrl = `http://localhost:${gPort}${path}` - - let addonData = {}; - if ("updates" in aData) - addonData.updates = aData.updates; - - let manifestJSON = { - "addons": { - [aData.id]: addonData - } - }; - - mapManifest(path.replace(/\?.*/, ""), - { data: JSON.stringify(manifestJSON), - contentType: aData.contentType || "application/json" }); - - - return new Promise((resolve, reject) => { - AddonUpdateChecker.checkForUpdates(aData.id, aData.updateKey, updateUrl, { - onUpdateCheckComplete: resolve, - - onUpdateCheckError: function(status) { - reject(new Error("Update check failed with status " + status)); - } - }); - }); -} - - -add_task(function* test_default_values() { - // Checks that the appropriate defaults are used for omitted values. - - startupManager(); - - let updates = yield checkUpdates({ - id: "updatecheck-defaults@tests.mozilla.org", - version: "0.1", - updates: [{ - version: "0.2" - }] - }); - - equal(updates.length, 1); - let update = updates[0]; - - equal(update.targetApplications.length, 1); - let targetApp = update.targetApplications[0]; - - equal(targetApp.id, TOOLKIT_ID); - equal(targetApp.minVersion, TOOLKIT_MINVERSION); - equal(targetApp.maxVersion, "*"); - - equal(update.version, "0.2"); - equal(update.multiprocessCompatible, true, "multiprocess_compatible flag"); - equal(update.strictCompatibility, false, "inferred strictConpatibility flag"); - equal(update.updateURL, null, "updateURL"); - equal(update.updateHash, null, "updateHash"); - equal(update.updateInfoURL, null, "updateInfoURL"); - - // If there's no applications property, we default to using one - // containing "gecko". If there is an applications property, but - // it doesn't contain "gecko", the update is skipped. - updates = yield checkUpdates({ - id: "updatecheck-defaults@tests.mozilla.org", - version: "0.1", - updates: [{ - version: "0.2", - applications: { "foo": {} } - }] - }); - - equal(updates.length, 0); - - // Updates property is also optional. No updates, but also no error. - updates = yield checkUpdates({ - id: "updatecheck-defaults@tests.mozilla.org", - version: "0.1", - }); - - equal(updates.length, 0); -}); - - -add_task(function* test_explicit_values() { - // Checks that the appropriate explicit values are used when - // provided. - - let updates = yield checkUpdates({ - id: "updatecheck-explicit@tests.mozilla.org", - version: "0.1", - updates: [{ - version: "0.2", - update_link: "https://example.com/foo.xpi", - update_hash: "sha256:0", - update_info_url: "https://example.com/update_info.html", - multiprocess_compatible: false, - applications: { - gecko: { - strict_min_version: "42.0a2.xpcshell", - strict_max_version: "43.xpcshell" - } - } - }] - }); - - equal(updates.length, 1); - let update = updates[0]; - - equal(update.targetApplications.length, 1); - let targetApp = update.targetApplications[0]; - - equal(targetApp.id, TOOLKIT_ID); - equal(targetApp.minVersion, "42.0a2.xpcshell"); - equal(targetApp.maxVersion, "43.xpcshell"); - - equal(update.version, "0.2"); - equal(update.multiprocessCompatible, false, "multiprocess_compatible flag"); - equal(update.strictCompatibility, true, "inferred strictCompatibility flag"); - equal(update.updateURL, "https://example.com/foo.xpi", "updateURL"); - equal(update.updateHash, "sha256:0", "updateHash"); - equal(update.updateInfoURL, "https://example.com/update_info.html", "updateInfoURL"); -}); - - -add_task(function* test_secure_hashes() { - // Checks that only secure hash functions are accepted for - // non-secure update URLs. - - let hashFunctions = ["sha512", - "sha256", - "sha1", - "md5", - "md4", - "xxx"]; - - let updateItems = hashFunctions.map((hash, idx) => ({ - version: `0.${idx}`, - update_link: `http://localhost:${gPort}/updates/${idx}-${hash}.xpi`, - update_hash: `${hash}:08ac852190ecd81f40a514ea9299fe9143d9ab5e296b97e73fb2a314de49648a`, - })); - - let { messages, result: updates } = yield promiseConsoleOutput(() => { - return checkUpdates({ - id: "updatecheck-hashes@tests.mozilla.org", - version: "0.1", - updates: updateItems - }); - }); - - equal(updates.length, hashFunctions.length); - - updates = updates.filter(update => update.updateHash || update.updateURL); - equal(updates.length, 2, "expected number of update hashes were accepted"); - - ok(updates[0].updateHash.startsWith("sha512:"), "sha512 hash is present"); - ok(updates[0].updateURL); - - ok(updates[1].updateHash.startsWith("sha256:"), "sha256 hash is present"); - ok(updates[1].updateURL); - - messages = messages.filter(msg => /Update link.*not secure.*strong enough hash \(needs to be sha256 or sha512\)/.test(msg.message)); - equal(messages.length, hashFunctions.length - 2, "insecure hashes generated the expected warning"); -}); - - -add_task(function* test_strict_compat() { - // Checks that strict compatibility is enabled for strict max - // versions other than "*", but not for advisory max versions. - // Also, ensure that strict max versions take precedence over - // advisory versions. - - let { messages, result: updates } = yield promiseConsoleOutput(() => { - return checkUpdates({ - id: "updatecheck-strict@tests.mozilla.org", - version: "0.1", - updates: [ - { version: "0.2", - applications: { gecko: { strict_max_version: "*" } } }, - { version: "0.3", - applications: { gecko: { strict_max_version: "43" } } }, - { version: "0.4", - applications: { gecko: { advisory_max_version: "43" } } }, - { version: "0.5", - applications: { gecko: { advisory_max_version: "43", - strict_max_version: "44" } } }, - ] - }); - }); - - equal(updates.length, 4, "all update items accepted"); - - equal(updates[0].targetApplications[0].maxVersion, "*"); - equal(updates[0].strictCompatibility, false); - - equal(updates[1].targetApplications[0].maxVersion, "43"); - equal(updates[1].strictCompatibility, true); - - equal(updates[2].targetApplications[0].maxVersion, "43"); - equal(updates[2].strictCompatibility, false); - - equal(updates[3].targetApplications[0].maxVersion, "44"); - equal(updates[3].strictCompatibility, true); - - messages = messages.filter(msg => /Ignoring 'advisory_max_version'.*'strict_max_version' also present/.test(msg.message)); - equal(messages.length, 1, "mix of advisory_max_version and strict_max_version generated the expected warning"); -}); - - -add_task(function* test_update_url_security() { - // Checks that update links to privileged URLs are not accepted. - - let { messages, result: updates } = yield promiseConsoleOutput(() => { - return checkUpdates({ - id: "updatecheck-security@tests.mozilla.org", - version: "0.1", - updates: [ - { version: "0.2", - update_link: "chrome://browser/content/browser.xul", - update_hash: "sha256:08ac852190ecd81f40a514ea9299fe9143d9ab5e296b97e73fb2a314de49648a" }, - { version: "0.3", - update_link: "http://example.com/update.xpi", - update_hash: "sha256:18ac852190ecd81f40a514ea9299fe9143d9ab5e296b97e73fb2a314de49648a" }, - ] - }); - }); - - equal(updates.length, 2, "both updates were processed"); - equal(updates[0].updateURL, null, "privileged update URL was removed"); - equal(updates[1].updateURL, "http://example.com/update.xpi", "safe update URL was accepted"); - - messages = messages.filter(msg => /http:\/\/localhost.*\/updates\/.*may not load or link to chrome:/.test(msg.message)); - equal(messages.length, 1, "privileged upate URL generated the expected console message"); -}); - - -add_task(function* test_no_update_key() { - // Checks that updates fail when an update key has been specified. - - let { messages } = yield promiseConsoleOutput(function* () { - yield Assert.rejects( - checkUpdates({ - id: "updatecheck-updatekey@tests.mozilla.org", - version: "0.1", - updateKey: "ayzzx=", - updates: [ - { version: "0.2" }, - { version: "0.3" }, - ] - }), - null, "updated expected to fail"); - }); - - messages = messages.filter(msg => /Update keys are not supported for JSON update manifests/.test(msg.message)); - equal(messages.length, 1, "got expected update-key-unsupported error"); -}); - - -add_task(function* test_type_detection() { - // Checks that JSON update manifests are detected correctly - // regardless of extension or MIME type. - - let tests = [ - { contentType: "application/json", - extension: "json", - valid: true }, - { contentType: "application/json", - extension: "php", - valid: true }, - { contentType: "text/plain", - extension: "json", - valid: true }, - { contentType: "application/octet-stream", - extension: "json", - valid: true }, - { contentType: "text/plain", - extension: "json?foo=bar", - valid: true }, - { contentType: "text/plain", - extension: "php", - valid: true }, - { contentType: "text/plain", - extension: "rdf", - valid: true }, - { contentType: "application/json", - extension: "rdf", - valid: true }, - { contentType: "text/xml", - extension: "json", - valid: true }, - { contentType: "application/rdf+xml", - extension: "json", - valid: true }, - ]; - - for (let [i, test] of tests.entries()) { - let { messages } = yield promiseConsoleOutput(function *() { - let id = `updatecheck-typedetection-${i}@tests.mozilla.org`; - let updates; - try { - updates = yield checkUpdates({ - id: id, - version: "0.1", - contentType: test.contentType, - manifestExtension: test.extension, - updates: [{ version: "0.2" }] - }); - } catch (e) { - ok(!test.valid, "update manifest correctly detected as RDF"); - return; - } - - ok(test.valid, "update manifest correctly detected as JSON"); - equal(updates.length, 1, "correct number of updates"); - equal(updates[0].id, id, "update is for correct extension"); - }); - - if (test.valid) { - // Make sure we don't get any XML parsing errors from the - // XMLHttpRequest machinery. - ok(!messages.some(msg => /not well-formed/.test(msg.message)), - "expect XMLHttpRequest not to attempt XML parsing"); - } - - messages = messages.filter(msg => /Update manifest was not valid XML/.test(msg.message)); - equal(messages.length, !test.valid, "expected number of XML parsing errors"); - } -}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_locked.js b/toolkit/mozapps/extensions/test/xpcshell/test_locked.js index 86457eab1..d16c1019d 100755..100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_locked.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_locked.js @@ -361,12 +361,7 @@ add_task(function* run_test_1() { // Restarting will actually apply changes to extensions.ini which will // then be put into the in-memory database when we next fail to load the // real thing - try { - shutdownManager(); - } catch (e) { - // We're expecting an error here. - } - startupManager(false); + restartManager(); // Shouldn't have seen any startup changes check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, []); @@ -445,11 +440,7 @@ add_task(function* run_test_1() { // After allowing access to the original DB things should go back to as // they were previously - try { - shutdownManager(); - } catch (e) { - // We're expecting an error here. - } + shutdownManager(); do_print("Unlocking " + gExtensionsJSON.path); yield file.close(); gExtensionsJSON.permissions = filePermissions; @@ -530,12 +521,6 @@ add_task(function* run_test_1() { do_check_false(t2.appDisabled); do_check_eq(t2.pendingOperations, AddonManager.PENDING_NONE); do_check_true(isThemeInAddonsList(profileDir, t2.id)); - - try { - shutdownManager(); - } catch (e) { - // We're expecting an error here. - } }); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_locked2.js b/toolkit/mozapps/extensions/test/xpcshell/test_locked2.js index 4a62c585f..10b13c9f6 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_locked2.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_locked2.js @@ -71,7 +71,7 @@ var addon5 = { const profileDir = gProfD.clone(); profileDir.append("extensions"); -add_task(function*() { +add_task(function() { createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "2"); @@ -217,12 +217,7 @@ add_task(function*() { // After allowing access to the original DB things should still be // back how they were before the lock - let shutdownError; - try { - shutdownManager(); - } catch (e) { - shutdownError = e; - } + shutdownManager(); yield file.close(); gExtensionsJSON.permissions = filePermissions; startupManager(); @@ -231,7 +226,7 @@ add_task(function*() { // readable, so our changes were saved. On Windows, // these things happened when we had no access to the database so // they are seen as external changes when we get the database back - if (shutdownError) { + if (gXPISaveError) { do_print("Previous XPI save failed"); check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, ["addon6@tests.mozilla.org"]); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_locked_strictcompat.js b/toolkit/mozapps/extensions/test/xpcshell/test_locked_strictcompat.js index 9e17b4c8b..907c611dd 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_locked_strictcompat.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_locked_strictcompat.js @@ -362,12 +362,7 @@ add_task(function* run_test_1() { // Restarting will actually apply changes to extensions.ini which will // then be put into the in-memory database when we next fail to load the // real thing - try { - shutdownManager(); - } catch (e) { - // We're expecting an error here. - } - startupManager(false); + restartManager(); // Shouldn't have seen any startup changes check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, []); @@ -446,12 +441,7 @@ add_task(function* run_test_1() { // After allowing access to the original DB things should go back to as // back how they were before the lock - let shutdownError; - try { - shutdownManager(); - } catch (e) { - shutdownError = e; - } + shutdownManager(); do_print("Unlocking " + gExtensionsJSON.path); yield file.close(); gExtensionsJSON.permissions = filePermissions; @@ -491,7 +481,7 @@ add_task(function* run_test_1() { // remember that this extension was changed to disabled. On Windows we // couldn't replace the old DB so we read the older version of the DB // where the extension is enabled - if (shutdownError) { + if (gXPISaveError) { do_print("XPI save failed"); do_check_true(a3.isActive); do_check_false(a3.appDisabled); @@ -553,12 +543,6 @@ add_task(function* run_test_1() { do_check_false(t2.appDisabled); do_check_eq(t2.pendingOperations, AddonManager.PENDING_NONE); do_check_true(isThemeInAddonsList(profileDir, t2.id)); - - try { - shutdownManager(); - } catch (e) { - // An error is expected here. - } }); function run_test() { diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_manifest.js b/toolkit/mozapps/extensions/test/xpcshell/test_manifest.js index 85279ba5d..061a3a6b2 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_manifest.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_manifest.js @@ -243,7 +243,7 @@ function run_test() { maxVersion: "1" }], name: "Test Addon 18" - }, profileDir, undefined, "options.xul"); + }, profileDir, null, "options.xul"); writeInstallRDFForExtension({ id: "addon19@tests.mozilla.org", @@ -305,7 +305,7 @@ function run_test() { maxVersion: "1" }], name: "Test Addon 23" - }, profileDir, undefined, "options.xul"); + }, profileDir, null, "options.xul"); writeInstallRDFForExtension({ id: "addon24@tests.mozilla.org", @@ -316,7 +316,7 @@ function run_test() { maxVersion: "1" }], name: "Test Addon 24" - }, profileDir, undefined, "options.xul"); + }, profileDir, null, "options.xul"); writeInstallRDFForExtension({ id: "addon25@tests.mozilla.org", @@ -340,7 +340,7 @@ function run_test() { maxVersion: "1" }], name: "Test Addon 26" - }, profileDir, undefined, "options.xul"); + }, profileDir, null, "options.xul"); do_test_pending(); startupManager(); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_mapURIToAddonID.js b/toolkit/mozapps/extensions/test/xpcshell/test_mapURIToAddonID.js index 1dd05064e..a153256dc 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_mapURIToAddonID.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_mapURIToAddonID.js @@ -19,8 +19,6 @@ userExtDir.append("extensions2"); userExtDir.append(gAppInfo.ID); registerDirectory("XREUSysExt", userExtDir.parent); -BootstrapMonitor.init(); - function TestProvider(result) { this.result = result; } @@ -33,7 +31,7 @@ TestProvider.prototype = { if (aURI.spec === this.uri.spec) { return this.id; } - throw Components.Exception("Not mapped", this.result); + throw Components.Exception("Not mapped", result); } }; @@ -52,6 +50,18 @@ function check_mapping(uri, id) { do_check_eq(val.value, id); } +function resetPrefs() { + Services.prefs.setIntPref("bootstraptest.active_version", -1); +} + +function waitForPref(aPref, aCallback) { + function prefChanged() { + Services.prefs.removeObserver(aPref, prefChanged); + aCallback(); + } + Services.prefs.addObserver(aPref, prefChanged, false); +} + function getActiveVersion() { return Services.prefs.getIntPref("bootstraptest.active_version"); } @@ -59,6 +69,8 @@ function getActiveVersion() { function run_test() { do_test_pending(); + resetPrefs(); + run_test_early(); } @@ -138,7 +150,7 @@ function run_test_1() { let uri = addon.getResourceURI("."); check_mapping(uri, addon.id); - BootstrapMonitor.promiseAddonStartup("bootstrap1@tests.mozilla.org").then(function() { + waitForPref("bootstraptest.active_version", function() { run_test_2(uri); }); }); @@ -248,38 +260,8 @@ function run_test_7() { let uri = b1.getResourceURI("."); check_mapping(uri, b1.id); - do_execute_soon(run_test_8); - }); -} - -// Tests that temporary addon-on URIs are mappable after install and uninstall -function run_test_8() { - prepare_test({ - "bootstrap2@tests.mozilla.org": [ - ["onInstalling", false], - "onInstalled" - ] - }, [ - "onExternalInstall", - ], function(b2) { - let uri = b2.getResourceURI("."); - check_mapping(uri, b2.id); - - prepare_test({ - "bootstrap2@tests.mozilla.org": [ - ["onUninstalling", false], - "onUninstalled" - ] - }); - - b2.uninstall(); - ensure_test_completed(); - - check_mapping(uri, b2.id); - do_execute_soon(run_test_invalidarg); }); - AddonManager.installTemporaryAddon(do_get_addon("test_bootstrap2_1")); } // Tests that the AddonManager will bail when mapURIToAddonID is called with an @@ -299,12 +281,11 @@ function run_test_invalidarg() { AddonManager.mapURIToAddonID(test); throw new Error("Shouldn't be able to map the URI in question"); } + catch (ex if ex.result) { + do_check_eq(ex.result, Components.results.NS_ERROR_INVALID_ARG); + } catch (ex) { - if (ex.result) { - do_check_eq(ex.result, Components.results.NS_ERROR_INVALID_ARG); - } else { - do_throw(ex); - } + do_throw(ex); } } diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_metadata_update.js b/toolkit/mozapps/extensions/test/xpcshell/test_metadata_update.js index dbf5db485..a87b3f45b 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_metadata_update.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_metadata_update.js @@ -23,12 +23,12 @@ Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); // None of this works without the add-on repository cache Services.prefs.setBoolPref("extensions.getAddons.cache.enabled", true); -var Cc = Components.classes; -var Ci = Components.interfaces; -var Cu = Components.utils; -var Cr = Components.results; +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cu = Components.utils; +const Cr = Components.results; -Cu.import("resource://testing-common/MockRegistrar.jsm"); +Cu.import("resource://testing-common/httpd.js"); var testserver; const profileDir = gProfD.clone(); @@ -37,6 +37,7 @@ profileDir.append("extensions"); // This will be called to show the compatibility update dialog. var WindowWatcher = { expected: false, + arguments: null, openWindow: function(parent, url, name, features, args) { do_check_true(Services.startup.interrupted); @@ -54,7 +55,18 @@ var WindowWatcher = { } } -MockRegistrar.register("@mozilla.org/embedcomp/window-watcher;1", WindowWatcher); +var WindowWatcherFactory = { + createInstance: function createInstance(outer, iid) { + if (outer != null) + throw Components.results.NS_ERROR_NO_AGGREGATION; + return WindowWatcher.QueryInterface(iid); + } +}; + +var registrar = Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar); +registrar.registerFactory(Components.ID("{1dfeb90a-2193-45d5-9cb8-864928b2af55}"), + "Fake Window Watcher", + "@mozilla.org/embedcomp/window-watcher;1", WindowWatcherFactory); // Return Date.now() in seconds, rounded function now() { @@ -68,9 +80,10 @@ add_task(function* checkFirstMetadata() { Services.prefs.setBoolPref(PREF_EM_SHOW_MISMATCH_UI, true); // Create and configure the HTTP server. - testserver = createHttpServer(); + testserver = new HttpServer(); testserver.registerDirectory("/data/", do_get_file("data")); testserver.registerDirectory("/addons/", do_get_file("addons")); + testserver.start(-1); gPort = testserver.identity.primaryPort; const BASE_URL = "http://localhost:" + gPort; const GETADDONS_RESULTS = BASE_URL + "/data/test_AddonRepository_cache.xml"; @@ -157,3 +170,15 @@ add_task(function* upgrade_young_pref_lastupdate() { yield promiseRestartManager("2"); do_check_false(WindowWatcher.expected); }); + + + +add_task(function* cleanup() { + return new Promise((resolve, reject) => { + testserver.stop(resolve); + }); +}); + +function run_test() { + run_next_test(); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_migrate1.js b/toolkit/mozapps/extensions/test/xpcshell/test_migrate1.js index 8c13593b9..b3cae5283 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_migrate1.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_migrate1.js @@ -163,7 +163,6 @@ function run_test() { do_check_true(a1.isActive); do_check_true(isExtensionInAddonsList(profileDir, a1.id)); do_check_false(a1.hasBinaryComponents); - do_check_true(a1.seen); // addon2 was user disabled and app enabled in the old extensions.rdf do_check_neq(a2, null); @@ -172,7 +171,6 @@ function run_test() { do_check_false(a2.isActive); do_check_false(isExtensionInAddonsList(profileDir, a2.id)); do_check_false(a2.hasBinaryComponents); - do_check_true(a2.seen); // addon3 was pending user disable and app disabled in the old extensions.rdf do_check_neq(a3, null); @@ -181,7 +179,6 @@ function run_test() { do_check_false(a3.isActive); do_check_false(isExtensionInAddonsList(profileDir, a3.id)); do_check_false(a3.hasBinaryComponents); - do_check_true(a3.seen); // addon4 was pending user enable and app disabled in the old extensions.rdf do_check_neq(a4, null); @@ -190,7 +187,6 @@ function run_test() { do_check_false(a4.isActive); do_check_false(isExtensionInAddonsList(profileDir, a4.id)); do_check_false(a4.hasBinaryComponents); - do_check_true(a4.seen); // addon5 was disabled and compatible but a new version has been installed // since, it should still be disabled but should be incompatible @@ -200,13 +196,36 @@ function run_test() { do_check_false(a5.isActive); do_check_false(isExtensionInAddonsList(profileDir, a5.id)); do_check_false(a5.hasBinaryComponents); - do_check_true(a5.seen); - // addon6, addon7 and addon8 will have been lost as they were staged in the - // pre-Firefox 4.0 directory - do_check_eq(a6, null); - do_check_eq(a7, null); - do_check_eq(a8, null); + // addon6 should be installed and compatible and packed unless unpacking is + // forced + do_check_neq(a6, null); + do_check_false(a6.userDisabled); + do_check_false(a6.appDisabled); + do_check_true(a6.isActive); + do_check_true(isExtensionInAddonsList(profileDir, a6.id)); + if (Services.prefs.getBoolPref("extensions.alwaysUnpack")) + do_check_eq(a6.getResourceURI("install.rdf").scheme, "file"); + else + do_check_eq(a6.getResourceURI("install.rdf").scheme, "jar"); + do_check_false(a6.hasBinaryComponents); + + // addon7 should be installed and compatible and unpacked + do_check_neq(a7, null); + do_check_false(a7.userDisabled); + do_check_false(a7.appDisabled); + do_check_true(a7.isActive); + do_check_true(isExtensionInAddonsList(profileDir, a7.id)); + do_check_eq(a7.getResourceURI("install.rdf").scheme, "file"); + do_check_false(a7.hasBinaryComponents); + + // addon8 should be installed and compatible and have binary components + do_check_neq(a8, null); + do_check_false(a8.userDisabled); + do_check_false(a8.appDisabled); + do_check_true(a8.isActive); + do_check_true(isExtensionInAddonsList(profileDir, a8.id)); + do_check_true(a8.hasBinaryComponents); // Theme 1 was previously enabled do_check_neq(t1, null); @@ -215,16 +234,16 @@ function run_test() { do_check_true(t1.isActive); do_check_true(isThemeInAddonsList(profileDir, t1.id)); do_check_false(hasFlag(t1.permissions, AddonManager.PERM_CAN_ENABLE)); - do_check_true(t1.seen); // Theme 2 was previously disabled - do_check_neq(t2, null); + do_check_neq(t1, null); do_check_true(t2.userDisabled); do_check_false(t2.appDisabled); do_check_false(t2.isActive); do_check_false(isThemeInAddonsList(profileDir, t2.id)); do_check_true(hasFlag(t2.permissions, AddonManager.PERM_CAN_ENABLE)); - do_check_true(t2.seen); + + do_check_false(stagedXPIs.exists()); do_execute_soon(do_test_finished); }); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_migrate2.js b/toolkit/mozapps/extensions/test/xpcshell/test_migrate2.js index cc7336713..c213bace7 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_migrate2.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_migrate2.js @@ -203,7 +203,6 @@ function run_test() { do_check_true(a1.isActive); do_check_false(a1.strictCompatibility); do_check_false(a1.foreignInstall); - do_check_true(a1.seen); // addon2 was disabled in the database do_check_neq(a2, null); do_check_true(a2.userDisabled); @@ -211,7 +210,6 @@ function run_test() { do_check_false(a2.isActive); do_check_false(a2.strictCompatibility); do_check_false(a2.foreignInstall); - do_check_true(a2.seen); // addon3 was pending-disable in the database do_check_neq(a3, null); do_check_true(a3.userDisabled); @@ -219,7 +217,6 @@ function run_test() { do_check_false(a3.isActive); do_check_false(a3.strictCompatibility); do_check_false(a3.foreignInstall); - do_check_true(a3.seen); // addon4 was pending-enable in the database do_check_neq(a4, null); do_check_false(a4.userDisabled); @@ -227,7 +224,6 @@ function run_test() { do_check_true(a4.isActive); do_check_true(a4.strictCompatibility); do_check_false(a4.foreignInstall); - do_check_true(a4.seen); // addon5 was enabled in the database but needed a compatibility update do_check_neq(a5, null); do_check_false(a5.userDisabled); @@ -235,7 +231,6 @@ function run_test() { do_check_true(a5.isActive); do_check_false(a5.strictCompatibility); do_check_false(a5.foreignInstall); - do_check_true(a5.seen); // addon6 was disabled and compatible but a new version has been installed // since, it should still be disabled but should be incompatible do_check_neq(a6, null); @@ -244,7 +239,6 @@ function run_test() { do_check_false(a6.isActive); do_check_false(a6.strictCompatibility); do_check_false(a6.foreignInstall); - do_check_true(a6.seen); // addon7 is in the global install location so should be a foreignInstall do_check_neq(a7, null); do_check_false(a7.userDisabled); @@ -252,7 +246,6 @@ function run_test() { do_check_true(a7.isActive); do_check_false(a7.strictCompatibility); do_check_true(a7.foreignInstall); - do_check_true(a7.seen); // addon8 is in the user install location so should be a foreignInstall do_check_neq(a8, null); do_check_false(a8.userDisabled); @@ -260,7 +253,6 @@ function run_test() { do_check_true(a8.isActive); do_check_false(a8.strictCompatibility); do_check_true(a8.foreignInstall); - do_check_true(a8.seen); do_execute_soon(do_test_finished); }); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_migrate3.js b/toolkit/mozapps/extensions/test/xpcshell/test_migrate3.js index 71bd66603..f27d53c3f 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_migrate3.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_migrate3.js @@ -118,19 +118,19 @@ function run_test() { previewURL: "http://localhost/data/preview.png", iconURL: "http://localhost/data/icon.png" }])); - Services.prefs.setCharPref("lightweightThemes.selectedThemeID", "1"); + Services.prefs.setBoolPref("lightweightThemes.isThemeSelected", true); let stagedXPIs = profileDir.clone(); stagedXPIs.append("staged-xpis"); stagedXPIs.append("addon6@tests.mozilla.org"); - stagedXPIs.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0o755); + stagedXPIs.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0755); let addon6 = do_get_addon("test_migrate6"); addon6.copyTo(stagedXPIs, "tmp.xpi"); stagedXPIs = stagedXPIs.parent; stagedXPIs.append("addon7@tests.mozilla.org"); - stagedXPIs.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0o755); + stagedXPIs.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0755); let addon7 = do_get_addon("test_migrate7"); addon7.copyTo(stagedXPIs, "tmp.xpi"); @@ -166,7 +166,6 @@ function run_test() { do_check_false(a1.appDisabled); do_check_true(a1.isActive); do_check_true(isExtensionInAddonsList(profileDir, a1.id)); - do_check_true(a1.seen); // addon2 was user disabled and app enabled in the old extensions.rdf do_check_neq(a2, null); @@ -174,7 +173,6 @@ function run_test() { do_check_false(a2.appDisabled); do_check_false(a2.isActive); do_check_false(isExtensionInAddonsList(profileDir, a2.id)); - do_check_true(a2.seen); // addon3 was pending user disable and app disabled in the old extensions.rdf do_check_neq(a3, null); @@ -182,7 +180,6 @@ function run_test() { do_check_true(a3.appDisabled); do_check_false(a3.isActive); do_check_false(isExtensionInAddonsList(profileDir, a3.id)); - do_check_true(a3.seen); // addon4 was pending user enable and app disabled in the old extensions.rdf do_check_neq(a4, null); @@ -190,7 +187,6 @@ function run_test() { do_check_true(a4.appDisabled); do_check_false(a4.isActive); do_check_false(isExtensionInAddonsList(profileDir, a4.id)); - do_check_true(a4.seen); // addon5 was disabled and compatible but a new version has been installed // since, it should still be disabled but should be incompatible @@ -199,12 +195,26 @@ function run_test() { do_check_true(a5.appDisabled); do_check_false(a5.isActive); do_check_false(isExtensionInAddonsList(profileDir, a5.id)); - do_check_true(a5.seen); - // addon6 and addon7 will have been lost as they were staged in the - // pre-Firefox 4.0 directory - do_check_eq(a6, null); - do_check_eq(a7, null); + // addon6 should be installed and compatible and packed unless unpacking is + // forced + do_check_neq(a6, null); + do_check_false(a6.userDisabled); + do_check_false(a6.appDisabled); + do_check_true(a6.isActive); + do_check_true(isExtensionInAddonsList(profileDir, a6.id)); + if (Services.prefs.getBoolPref("extensions.alwaysUnpack")) + do_check_eq(a6.getResourceURI("install.rdf").scheme, "file"); + else + do_check_eq(a6.getResourceURI("install.rdf").scheme, "jar"); + + // addon7 should be installed and compatible and unpacked + do_check_neq(a7, null); + do_check_false(a7.userDisabled); + do_check_false(a7.appDisabled); + do_check_true(a7.isActive); + do_check_true(isExtensionInAddonsList(profileDir, a7.id)); + do_check_eq(a7.getResourceURI("install.rdf").scheme, "file"); // Theme 1 was previously disabled do_check_neq(t1, null); @@ -213,16 +223,16 @@ function run_test() { do_check_false(t1.isActive); do_check_true(isThemeInAddonsList(profileDir, t1.id)); do_check_true(hasFlag(t1.permissions, AddonManager.PERM_CAN_ENABLE)); - do_check_true(t1.seen); // Theme 2 was previously disabled - do_check_neq(t2, null); + do_check_neq(t1, null); do_check_true(t2.userDisabled); do_check_false(t2.appDisabled); do_check_false(t2.isActive); do_check_false(isThemeInAddonsList(profileDir, t2.id)); do_check_true(hasFlag(t2.permissions, AddonManager.PERM_CAN_ENABLE)); - do_check_true(t2.seen); + + do_check_false(stagedXPIs.exists()); do_execute_soon(do_test_finished); }); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_migrate4.js b/toolkit/mozapps/extensions/test/xpcshell/test_migrate4.js index fad015886..b2903ead7 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_migrate4.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_migrate4.js @@ -98,7 +98,7 @@ var defaultTheme = { const profileDir = gProfD.clone(); profileDir.append("extensions"); -var oldSyncGUIDs = {}; +let oldSyncGUIDs = {}; function prepare_profile() { createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); @@ -132,7 +132,7 @@ function prepare_profile() { a6.userDisabled = true; a9.userDisabled = false; - for (let addon of [a1, a2, a3, a4, a5, a6]) { + for each (let addon in [a1, a2, a3, a4, a5, a6]) { oldSyncGUIDs[addon.id] = addon.syncGUID; } @@ -141,18 +141,18 @@ function prepare_profile() { AddonManager.getInstallForURL("http://localhost:" + gPort + "/addons/test_migrate4_7.xpi", function(aInstall7) { completeAllInstalls([aInstall6, aInstall7], function() { restartManager(); - + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", "addon2@tests.mozilla.org", "addon3@tests.mozilla.org", "addon4@tests.mozilla.org", "addon5@tests.mozilla.org", "addon6@tests.mozilla.org"], - function([a1_2, a2_2, a3_2, a4_2, a5_2, a6_2]) { - a3_2.userDisabled = true; - a4_2.userDisabled = false; - - a5_2.findUpdates({ + function([a1, a2, a3, a4, a5, a6]) { + a3.userDisabled = true; + a4.userDisabled = false; + + a5.findUpdates({ onUpdateFinished: function() { do_execute_soon(perform_migration); } @@ -168,16 +168,11 @@ function prepare_profile() { function perform_migration() { shutdownManager(); - + // Turn on disabling for all scopes Services.prefs.setIntPref("extensions.autoDisableScopes", 15); - changeXPIDBVersion(1, data => { - // Delete the seen property from all add-ons to make sure it defaults to true - for (let addon of data.addons) { - delete addon.seen; - } - }); + changeXPIDBVersion(1); Services.prefs.setIntPref("extensions.databaseSchema", 1); gAppInfo.version = "2" @@ -210,7 +205,6 @@ function test_results() { do_check_true(a1.isActive); do_check_eq(a1.applyBackgroundUpdates, AddonManager.AUTOUPDATE_DEFAULT); do_check_true(a1.foreignInstall); - do_check_true(a1.seen); do_check_false(a1.hasBinaryComponents); do_check_false(a1.strictCompatibility); @@ -222,7 +216,6 @@ function test_results() { do_check_false(a2.isActive); do_check_eq(a2.applyBackgroundUpdates, AddonManager.AUTOUPDATE_DISABLE); do_check_true(a2.foreignInstall); - do_check_true(a2.seen); do_check_false(a2.hasBinaryComponents); do_check_false(a2.strictCompatibility); @@ -234,7 +227,6 @@ function test_results() { do_check_false(a3.isActive); do_check_eq(a3.applyBackgroundUpdates, AddonManager.AUTOUPDATE_ENABLE); do_check_true(a3.foreignInstall); - do_check_true(a3.seen); do_check_false(a3.hasBinaryComponents); do_check_false(a3.strictCompatibility); @@ -246,7 +238,6 @@ function test_results() { do_check_true(a4.isActive); do_check_eq(a4.applyBackgroundUpdates, AddonManager.AUTOUPDATE_DEFAULT); do_check_true(a4.foreignInstall); - do_check_true(a4.seen); do_check_false(a4.hasBinaryComponents); do_check_true(a4.strictCompatibility); @@ -257,7 +248,6 @@ function test_results() { do_check_true(a5.isActive); do_check_eq(a4.applyBackgroundUpdates, AddonManager.AUTOUPDATE_DEFAULT); do_check_true(a5.foreignInstall); - do_check_true(a5.seen); do_check_false(a5.hasBinaryComponents); do_check_false(a5.strictCompatibility); @@ -270,7 +260,6 @@ function test_results() { do_check_false(a6.isActive); do_check_eq(a6.applyBackgroundUpdates, AddonManager.AUTOUPDATE_DEFAULT); do_check_true(a6.foreignInstall); - do_check_true(a6.seen); do_check_eq(a6.sourceURI.spec, "http://localhost:" + gPort + "/addons/test_migrate4_6.xpi"); do_check_eq(a6.releaseNotesURI.spec, "http://example.com/updateInfo.xhtml"); do_check_false(a6.hasBinaryComponents); @@ -284,7 +273,6 @@ function test_results() { do_check_true(a7.isActive); do_check_eq(a7.applyBackgroundUpdates, AddonManager.AUTOUPDATE_DEFAULT); do_check_false(a7.foreignInstall); - do_check_true(a7.seen); do_check_eq(a7.sourceURI.spec, "http://localhost:" + gPort + "/addons/test_migrate4_7.xpi"); do_check_eq(a7.releaseNotesURI, null); do_check_false(a7.hasBinaryComponents); @@ -296,7 +284,6 @@ function test_results() { do_check_false(a8.appDisabled); do_check_true(a8.isActive); do_check_false(a8.foreignInstall); - do_check_true(a8.seen); do_check_true(a8.hasBinaryComponents); do_check_false(a8.strictCompatibility); @@ -306,7 +293,6 @@ function test_results() { do_check_false(a9.appDisabled); do_check_true(a9.isActive); do_check_false(a9.foreignInstall); - do_check_true(a9.seen); do_check_false(a9.hasBinaryComponents); do_check_true(a9.strictCompatibility); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_migrate5.js b/toolkit/mozapps/extensions/test/xpcshell/test_migrate5.js index 885cd5a7c..0109dcf92 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_migrate5.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_migrate5.js @@ -1,139 +1,139 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -// Checks that we fail to migrate but still start up ok when there is a SQLITE database -// with no useful data in it. - -const PREF_GENERAL_SKINS_SELECTEDSKIN = "general.skins.selectedSkin"; - -var addon1 = { - id: "addon1@tests.mozilla.org", - version: "1.0", - name: "Test 1", - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "1", - maxVersion: "1" - }] -}; - -var addon2 = { - id: "addon2@tests.mozilla.org", - version: "2.0", - name: "Test 5", - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "0", - maxVersion: "0" - }] -}; - -var defaultTheme = { - id: "default@tests.mozilla.org", - version: "2.0", - name: "Default theme", - internalName: "classic/1.0", - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "1", - maxVersion: "1" - }] -}; - -var theme1 = { - id: "theme1@tests.mozilla.org", - version: "2.0", - name: "Test theme", - internalName: "theme1/1.0", - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "1", - maxVersion: "1" - }] -}; - -const profileDir = gProfD.clone(); -profileDir.append("extensions"); - -function run_test() { - do_test_pending(); - createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); - - writeInstallRDFForExtension(addon1, profileDir); - writeInstallRDFForExtension(addon2, profileDir); - writeInstallRDFForExtension(defaultTheme, profileDir); - writeInstallRDFForExtension(theme1, profileDir); - - Services.prefs.setCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN, "theme1/1.0"); - - // Write out a broken database (no userDisabled field) - let dbfile = gProfD.clone(); - dbfile.append("extensions.sqlite"); - let db = AM_Cc["@mozilla.org/storage/service;1"]. - getService(AM_Ci.mozIStorageService). - openDatabase(dbfile); - db.createTable("addon", "internal_id INTEGER PRIMARY KEY AUTOINCREMENT, " + - "id TEXT, location TEXT, version TEXT, active INTEGER, " + - "installDate INTEGER"); - db.createTable("targetApplication", "addon_internal_id INTEGER, " + - "id TEXT, minVersion TEXT, maxVersion TEXT"); - let stmt = db.createStatement("INSERT INTO addon VALUES (NULL, :id, :location, " + - ":version, :active, :installDate)"); - - let internal_ids = {}; - - [["addon1@tests.mozilla.org", "app-profile", "1.0", "1", "0"], - ["addon2@tests.mozilla.org", "app-profile", "2.0", "0", "0"], - ["default@tests.mozilla.org", "app-profile", "2.0", "1", "0"], - ["theme1@tests.mozilla.org", "app-profile", "2.0", "0", "0"]].forEach(function(a) { - stmt.params.id = a[0]; - stmt.params.location = a[1]; - stmt.params.version = a[2]; - stmt.params.active = a[3]; - stmt.params.installDate = a[4]; - stmt.execute(); - internal_ids[a[0]] = db.lastInsertRowID; - }); - stmt.finalize(); - - db.schemaVersion = 100; - Services.prefs.setIntPref("extensions.databaseSchema", 100); - db.close(); - - startupManager(); - check_startup_changes("installed", []); - check_startup_changes("updated", []); - check_startup_changes("uninstalled", []); - check_startup_changes("disabled", []); - check_startup_changes("enabled", []); - - AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", - "addon2@tests.mozilla.org", - "default@tests.mozilla.org", - "theme1@tests.mozilla.org"], - function([a1, a2, d, t1]) { - do_check_neq(a1, null); - do_check_false(a1.userDisabled); - do_check_false(a1.appDisabled); - do_check_true(a1.isActive); - - do_check_neq(a2, null); - do_check_false(a2.userDisabled); - do_check_true(a2.appDisabled); - do_check_false(a2.isActive); - - // Should have enabled the selected theme - do_check_neq(t1, null); - do_check_false(t1.userDisabled); - do_check_false(t1.appDisabled); - do_check_true(t1.isActive); - - do_check_neq(d, null); - do_check_true(d.userDisabled); - do_check_false(d.appDisabled); - do_check_false(d.isActive); - - do_execute_soon(do_test_finished); - }); -} +/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Checks that we fail to migrate but still start up ok when there is a SQLITE database
+// with no useful data in it.
+
+const PREF_GENERAL_SKINS_SELECTEDSKIN = "general.skins.selectedSkin";
+
+var addon1 = {
+ id: "addon1@tests.mozilla.org",
+ version: "1.0",
+ name: "Test 1",
+ targetApplications: [{
+ id: "xpcshell@tests.mozilla.org",
+ minVersion: "1",
+ maxVersion: "1"
+ }]
+};
+
+var addon2 = {
+ id: "addon2@tests.mozilla.org",
+ version: "2.0",
+ name: "Test 5",
+ targetApplications: [{
+ id: "xpcshell@tests.mozilla.org",
+ minVersion: "0",
+ maxVersion: "0"
+ }]
+};
+
+var defaultTheme = {
+ id: "default@tests.mozilla.org",
+ version: "2.0",
+ name: "Default theme",
+ internalName: "classic/1.0",
+ targetApplications: [{
+ id: "xpcshell@tests.mozilla.org",
+ minVersion: "1",
+ maxVersion: "1"
+ }]
+};
+
+var theme1 = {
+ id: "theme1@tests.mozilla.org",
+ version: "2.0",
+ name: "Test theme",
+ internalName: "theme1/1.0",
+ targetApplications: [{
+ id: "xpcshell@tests.mozilla.org",
+ minVersion: "1",
+ maxVersion: "1"
+ }]
+};
+
+const profileDir = gProfD.clone();
+profileDir.append("extensions");
+
+function run_test() {
+ do_test_pending();
+ createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
+
+ writeInstallRDFForExtension(addon1, profileDir);
+ writeInstallRDFForExtension(addon2, profileDir);
+ writeInstallRDFForExtension(defaultTheme, profileDir);
+ writeInstallRDFForExtension(theme1, profileDir);
+
+ Services.prefs.setCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN, "theme1/1.0");
+
+ // Write out a broken database (no userDisabled field)
+ let dbfile = gProfD.clone();
+ dbfile.append("extensions.sqlite");
+ let db = AM_Cc["@mozilla.org/storage/service;1"].
+ getService(AM_Ci.mozIStorageService).
+ openDatabase(dbfile);
+ db.createTable("addon", "internal_id INTEGER PRIMARY KEY AUTOINCREMENT, " +
+ "id TEXT, location TEXT, version TEXT, active INTEGER, " +
+ "installDate INTEGER");
+ db.createTable("targetApplication", "addon_internal_id INTEGER, " +
+ "id TEXT, minVersion TEXT, maxVersion TEXT");
+ let stmt = db.createStatement("INSERT INTO addon VALUES (NULL, :id, :location, " +
+ ":version, :active, :installDate)");
+
+ let internal_ids = {};
+
+ [["addon1@tests.mozilla.org", "app-profile", "1.0", "1", "0"],
+ ["addon2@tests.mozilla.org", "app-profile", "2.0", "0", "0"],
+ ["default@tests.mozilla.org", "app-profile", "2.0", "1", "0"],
+ ["theme1@tests.mozilla.org", "app-profile", "2.0", "0", "0"]].forEach(function(a) {
+ stmt.params.id = a[0];
+ stmt.params.location = a[1];
+ stmt.params.version = a[2];
+ stmt.params.active = a[3];
+ stmt.params.installDate = a[4];
+ stmt.execute();
+ internal_ids[a[0]] = db.lastInsertRowID;
+ });
+ stmt.finalize();
+
+ db.schemaVersion = 100;
+ Services.prefs.setIntPref("extensions.databaseSchema", 100);
+ db.close();
+
+ startupManager();
+ check_startup_changes("installed", []);
+ check_startup_changes("updated", []);
+ check_startup_changes("uninstalled", []);
+ check_startup_changes("disabled", []);
+ check_startup_changes("enabled", []);
+
+ AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
+ "addon2@tests.mozilla.org",
+ "default@tests.mozilla.org",
+ "theme1@tests.mozilla.org"],
+ function([a1, a2, d, t1]) {
+ do_check_neq(a1, null);
+ do_check_false(a1.userDisabled);
+ do_check_false(a1.appDisabled);
+ do_check_true(a1.isActive);
+
+ do_check_neq(a2, null);
+ do_check_false(a2.userDisabled);
+ do_check_true(a2.appDisabled);
+ do_check_false(a2.isActive);
+
+ // Should have enabled the selected theme
+ do_check_neq(t1, null);
+ do_check_false(t1.userDisabled);
+ do_check_false(t1.appDisabled);
+ do_check_true(t1.isActive);
+
+ do_check_neq(d, null);
+ do_check_true(d.userDisabled);
+ do_check_false(d.appDisabled);
+ do_check_false(d.isActive);
+
+ do_execute_soon(do_test_finished);
+ });
+}
diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_migrateAddonRepository.js b/toolkit/mozapps/extensions/test/xpcshell/test_migrateAddonRepository.js index d9cfc8790..ad8bd5bca 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_migrateAddonRepository.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_migrateAddonRepository.js @@ -3,7 +3,7 @@ */ const EXPECTED_SCHEMA_VERSION = 4; -var dbfile; +let dbfile; function run_test() { do_test_pending(); @@ -59,21 +59,21 @@ function run_test() { "caption TEXT, " + "PRIMARY KEY (addon_internal_id, num)"); - let insertStmt = db.createStatement("INSERT INTO addon (id) VALUES (:id)"); - insertStmt.params.id = "test1@tests.mozilla.org"; - insertStmt.execute(); - insertStmt.finalize(); + let stmt = db.createStatement("INSERT INTO addon (id) VALUES (:id)"); + stmt.params.id = "test1@tests.mozilla.org"; + stmt.execute(); + stmt.finalize(); - insertStmt = db.createStatement("INSERT INTO screenshot VALUES " + + stmt = db.createStatement("INSERT INTO screenshot VALUES " + "(:addon_internal_id, :num, :url, :thumbnailURL, :caption)"); - insertStmt.params.addon_internal_id = 1; - insertStmt.params.num = 0; - insertStmt.params.url = "http://localhost/full1-1.png"; - insertStmt.params.thumbnailURL = "http://localhost/thumbnail1-1.png"; - insertStmt.params.caption = "Caption 1 - 1"; - insertStmt.execute(); - insertStmt.finalize(); + stmt.params.addon_internal_id = 1; + stmt.params.num = 0; + stmt.params.url = "http://localhost/full1-1.png"; + stmt.params.thumbnailURL = "http://localhost/thumbnail1-1.png"; + stmt.params.caption = "Caption 1 - 1"; + stmt.execute(); + stmt.finalize(); db.schemaVersion = 1; db.close(); @@ -108,15 +108,15 @@ function run_test() { let internalID = db.lastInsertRowID; db.executeSimpleSQL("INSERT INTO compatibility_override (addon_internal_id, num, type) VALUES('" + internalID + "', '1', 'incompatible')"); - let selectStmt = db.createStatement("SELECT COUNT(*) AS count FROM compatibility_override"); - selectStmt.executeStep(); - do_check_eq(selectStmt.row.count, 1); - selectStmt.reset(); + let stmt = db.createStatement("SELECT COUNT(*) AS count FROM compatibility_override"); + stmt.executeStep(); + do_check_eq(stmt.row.count, 1); + stmt.reset(); db.executeSimpleSQL("DELETE FROM addon"); - selectStmt.executeStep(); - do_check_eq(selectStmt.row.count, 0); - selectStmt.finalize(); + stmt.executeStep(); + do_check_eq(stmt.row.count, 0); + stmt.finalize(); db.close(); do_test_finished(); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_migrate_max_version.js b/toolkit/mozapps/extensions/test/xpcshell/test_migrate_max_version.js index 171ac411e..133c3a199 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_migrate_max_version.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_migrate_max_version.js @@ -80,7 +80,7 @@ add_test(function before_rebuild() { }); }); -// now shut down, remove the JSON database, +// now shut down, remove the JSON database, // start up again, and make sure the data didn't migrate this time add_test(function rebuild_again() { shutdownManager(); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_multiprocessCompatible.js b/toolkit/mozapps/extensions/test/xpcshell/test_multiprocessCompatible.js index 4cd103fa6..ab5a976cc 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_multiprocessCompatible.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_multiprocessCompatible.js @@ -53,8 +53,7 @@ function build_test(multiprocessCompatible, bootstrap, updateMultiprocessCompati let xpifile = createTempXPIFile(addonData); let install = yield new Promise(resolve => AddonManager.getInstallForFile(xpifile, resolve)); - do_check_eq(install.addon.multiprocessCompatible, !!multiprocessCompatible); - do_check_eq(install.addon.mpcOptedOut, multiprocessCompatible === false) + do_check_eq(install.addon.multiprocessCompatible, multiprocessCompatible); yield promiseCompleteAllInstalls([install]); if (!bootstrap) { @@ -65,18 +64,17 @@ function build_test(multiprocessCompatible, bootstrap, updateMultiprocessCompati let addon = yield promiseAddonByID(addonData.id); do_check_neq(addon, null); - do_check_eq(addon.multiprocessCompatible, !!multiprocessCompatible); - do_check_eq(addon.mpcOptedOut, multiprocessCompatible === false); + do_check_eq(addon.multiprocessCompatible, multiprocessCompatible); yield promiseFindAddonUpdates(addon); // Should have applied the compatibility change - do_check_eq(addon.multiprocessCompatible, !!expectedMPC); + do_check_eq(addon.multiprocessCompatible, expectedMPC); yield promiseRestartManager(); addon = yield promiseAddonByID(addonData.id); // Should have persisted the compatibility change - do_check_eq(addon.multiprocessCompatible, !!expectedMPC); + do_check_eq(addon.multiprocessCompatible, expectedMPC); if (!bootstrap) { do_check_true(isExtensionInAddonsList(profileDir, addonData.id)); do_check_eq(isItemMarkedMPIncompatible(addonData.id), !multiprocessCompatible); @@ -95,7 +93,7 @@ function build_test(multiprocessCompatible, bootstrap, updateMultiprocessCompati * The update saying the add-on should or should not support multiprocess (or not say anything at all) */ for (let bootstrap of [false, true]) { - for (let multiprocessCompatible of [undefined, false, true]) { + for (let multiprocessCompatible of [false, true]) { for (let updateMultiprocessCompatible of [undefined, false, true]) { add_task(build_test(multiprocessCompatible, bootstrap, updateMultiprocessCompatible)); } diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_no_addons.js b/toolkit/mozapps/extensions/test/xpcshell/test_no_addons.js index a2ea5301e..ae75fbb43 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_no_addons.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_no_addons.js @@ -8,7 +8,7 @@ Components.utils.import("resource://gre/modules/Promise.jsm"); // Load XPI Provider to get schema version ID -var XPIScope = Components.utils.import("resource://gre/modules/addons/XPIProvider.jsm"); +let XPIScope = Components.utils.import("resource://gre/modules/addons/XPIProvider.jsm"); const DB_SCHEMA = XPIScope.DB_SCHEMA; createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); @@ -33,7 +33,7 @@ function checkString(aPref, aValue) { do_check_eq(Services.prefs.getCharPref(aPref), aValue) } catch (e) { - // OK + //OK } } @@ -56,14 +56,14 @@ function check_empty_state() { // bootstrap add-ons preference is not found // add-on directory state preference is an empty array // no pending operations -add_task(function* first_run() { +add_task(function first_run() { startupManager(); check_empty_state(); yield true; }); // Now do something that causes a DB load, and re-check -function* trigger_db_load() { +function trigger_db_load() { let addonDefer = Promise.defer(); AddonManager.getAddonsByTypes(['extension'], addonDefer.resolve); let addonList = yield addonDefer.promise; @@ -72,11 +72,11 @@ function* trigger_db_load() { check_empty_state(); yield true; -} +}; add_task(trigger_db_load); // Now restart the manager and check again -add_task(function* restart_and_recheck() { +add_task(function restart_and_recheck() { restartManager(); check_empty_state(); yield true; diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_nodisable_hidden.js b/toolkit/mozapps/extensions/test/xpcshell/test_nodisable_hidden.js deleted file mode 100644 index 2d11e9c5b..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_nodisable_hidden.js +++ /dev/null @@ -1,107 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -// This test verifies that hidden add-ons cannot be user disabled. - -// for normal add-ons -const profileDir = FileUtils.getDir("ProfD", ["extensions"]); -// for system add-ons -const distroDir = FileUtils.getDir("ProfD", ["sysfeatures"], true); -registerDirectory("XREAppFeat", distroDir); - -const NORMAL_ID = "normal@tests.mozilla.org"; -const SYSTEM_ID = "system@tests.mozilla.org"; - -createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "42"); - -// normal add-ons can be user disabled. -add_task(function*() { - - writeInstallRDFToDir({ - id: NORMAL_ID, - version: "1.0", - bootstrap: true, - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "1", - maxVersion: "1" - }], - name: "Test disabling hidden add-ons, non-hidden add-on case.", - }, profileDir, NORMAL_ID); - - startupManager(); - - let addon = yield promiseAddonByID(NORMAL_ID); - do_check_neq(addon, null); - do_check_eq(addon.version, "1.0"); - do_check_eq(addon.name, "Test disabling hidden add-ons, non-hidden add-on case."); - do_check_true(addon.isCompatible); - do_check_false(addon.appDisabled); - do_check_false(addon.userDisabled); - do_check_true(addon.isActive); - do_check_eq(addon.type, "extension"); - - // normal add-ons can be disabled by the user. - addon.userDisabled = true; - - do_check_neq(addon, null); - do_check_eq(addon.version, "1.0"); - do_check_eq(addon.name, "Test disabling hidden add-ons, non-hidden add-on case."); - do_check_true(addon.isCompatible); - do_check_false(addon.appDisabled); - do_check_true(addon.userDisabled); - do_check_false(addon.isActive); - do_check_eq(addon.type, "extension"); - - addon.uninstall(); - - shutdownManager(); -}); - -// system add-ons can never be user disabled. -add_task(function*() { - - writeInstallRDFToDir({ - id: SYSTEM_ID, - version: "1.0", - bootstrap: true, - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "1", - maxVersion: "1" - }], - name: "Test disabling hidden add-ons, hidden system add-on case.", - }, distroDir, SYSTEM_ID); - - startupManager(); - - let addon = yield promiseAddonByID(SYSTEM_ID); - do_check_neq(addon, null); - do_check_eq(addon.version, "1.0"); - do_check_eq(addon.name, "Test disabling hidden add-ons, hidden system add-on case."); - do_check_true(addon.isCompatible); - do_check_false(addon.appDisabled); - do_check_false(addon.userDisabled); - do_check_true(addon.isActive); - do_check_eq(addon.type, "extension"); - - // system add-ons cannot be disabled by the user. - try { - addon.userDisabled = true; - do_throw("Expected addon.userDisabled on a hidden add-on to throw!"); - } catch (e) { - do_check_eq(e.message, `Cannot disable hidden add-on ${SYSTEM_ID}`); - } - - do_check_neq(addon, null); - do_check_eq(addon.version, "1.0"); - do_check_eq(addon.name, "Test disabling hidden add-ons, hidden system add-on case."); - do_check_true(addon.isCompatible); - do_check_false(addon.appDisabled); - do_check_false(addon.userDisabled); - do_check_true(addon.isActive); - do_check_eq(addon.type, "extension"); - - shutdownManager(); -}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_overrideblocklist.js b/toolkit/mozapps/extensions/test/xpcshell/test_overrideblocklist.js index c39e432bd..8a6bedea1 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_overrideblocklist.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_overrideblocklist.js @@ -16,19 +16,19 @@ const NEW_TSTAMP = 1396046918000; const gAppDir = FileUtils.getFile(KEY_APPDIR, []); -var oldAddon = { +let oldAddon = { id: "old@tests.mozilla.org", version: 1 } -var newAddon = { +let newAddon = { id: "new@tests.mozilla.org", version: 1 } -var ancientAddon = { +let ancientAddon = { id: "ancient@tests.mozilla.org", version: 1 } -var invalidAddon = { +let invalidAddon = { id: "invalid@tests.mozilla.org", version: 1 } diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_pass_symbol.js b/toolkit/mozapps/extensions/test/xpcshell/test_pass_symbol.js deleted file mode 100644 index 657601e45..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_pass_symbol.js +++ /dev/null @@ -1,43 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -const PASS_PREF = "symboltest.instanceid.pass"; -const FAIL_BOGUS_PREF = "symboltest.instanceid.fail_bogus"; -const FAIL_ID_PREF = "symboltest.instanceid.fail_bogus"; -const ADDON_ID = "test_symbol@tests.mozilla.org"; - -createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "42"); -startupManager(); - -BootstrapMonitor.init(); - -// symbol is passed when add-on is installed -add_task(function*() { - for (let pref of [PASS_PREF, FAIL_BOGUS_PREF, FAIL_ID_PREF]) - Services.prefs.clearUserPref(pref); - - yield promiseInstallAllFiles([do_get_addon("test_symbol")], true); - - let addon = yield promiseAddonByID(ADDON_ID); - - do_check_neq(addon, null); - do_check_eq(addon.version, "1.0"); - do_check_eq(addon.name, "Test Symbol"); - do_check_true(addon.isCompatible); - do_check_false(addon.appDisabled); - do_check_true(addon.isActive); - do_check_eq(addon.type, "extension"); - - // most of the test is in bootstrap.js in the addon because BootstrapMonitor - // currently requires the objects in `data` to be serializable, and we - // need a real reference to the symbol to test this. - do_execute_soon(function() { - // give the startup time to run - do_check_true(Services.prefs.getBoolPref(PASS_PREF)); - do_check_true(Services.prefs.getBoolPref(FAIL_BOGUS_PREF)); - do_check_true(Services.prefs.getBoolPref(FAIL_ID_PREF)); - }); - - yield promiseRestartManager(); -}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_permissions.js b/toolkit/mozapps/extensions/test/xpcshell/test_permissions.js index 48fef406f..11463768f 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_permissions.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_permissions.js @@ -1,86 +1,86 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -Components.utils.import("resource://gre/modules/NetUtil.jsm"); - -// Checks that permissions set in preferences are correctly imported but can -// be removed by the user. - -const XPI_MIMETYPE = "application/x-xpinstall"; - -function newPrincipal(uri) { - return Services.scriptSecurityManager.createCodebasePrincipal(NetUtil.newURI(uri), {}); -} - -function run_test() { - createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "2"); - - Services.prefs.setCharPref("xpinstall.whitelist.add", "https://test1.com,https://test2.com"); - Services.prefs.setCharPref("xpinstall.whitelist.add.36", "https://test3.com,https://www.test4.com"); - Services.prefs.setCharPref("xpinstall.whitelist.add.test5", "https://test5.com"); - - Services.perms.add(NetUtil.newURI("https://www.test9.com"), "install", - AM_Ci.nsIPermissionManager.ALLOW_ACTION); - - startupManager(); - - do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE, - newPrincipal("http://test1.com"))); - do_check_true(AddonManager.isInstallAllowed(XPI_MIMETYPE, - newPrincipal("https://test1.com"))); - do_check_true(AddonManager.isInstallAllowed(XPI_MIMETYPE, - newPrincipal("https://www.test2.com"))); - do_check_true(AddonManager.isInstallAllowed(XPI_MIMETYPE, - newPrincipal("https://test3.com"))); - do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE, - newPrincipal("https://test4.com"))); - do_check_true(AddonManager.isInstallAllowed(XPI_MIMETYPE, - newPrincipal("https://www.test4.com"))); - do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE, - newPrincipal("http://www.test5.com"))); - do_check_true(AddonManager.isInstallAllowed(XPI_MIMETYPE, - newPrincipal("https://www.test5.com"))); - - do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE, - newPrincipal("http://www.test6.com"))); - do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE, - newPrincipal("https://www.test6.com"))); - do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE, - newPrincipal("https://test7.com"))); - do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE, - newPrincipal("https://www.test8.com"))); - - // This should remain unaffected - do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE, - newPrincipal("http://www.test9.com"))); - do_check_true(AddonManager.isInstallAllowed(XPI_MIMETYPE, - newPrincipal("https://www.test9.com"))); - - Services.perms.removeAll(); - - do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE, - newPrincipal("https://test1.com"))); - do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE, - newPrincipal("https://www.test2.com"))); - do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE, - newPrincipal("https://test3.com"))); - do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE, - newPrincipal("https://www.test4.com"))); - do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE, - newPrincipal("https://www.test5.com"))); - - // Upgrade the application and verify that the permissions are still not there - restartManager("2"); - - do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE, - newPrincipal("https://test1.com"))); - do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE, - newPrincipal("https://www.test2.com"))); - do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE, - newPrincipal("https://test3.com"))); - do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE, - newPrincipal("https://www.test4.com"))); - do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE, - newPrincipal("https://www.test5.com"))); -} +/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+Components.utils.import("resource://gre/modules/NetUtil.jsm");
+
+// Checks that permissions set in preferences are correctly imported but can
+// be removed by the user.
+
+const XPI_MIMETYPE = "application/x-xpinstall";
+
+function newPrincipal(uri) {
+ return Services.scriptSecurityManager.getNoAppCodebasePrincipal(NetUtil.newURI(uri));
+}
+
+function run_test() {
+ createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "2");
+
+ Services.prefs.setCharPref("xpinstall.whitelist.add", "test1.com,test2.com");
+ Services.prefs.setCharPref("xpinstall.whitelist.add.36", "test3.com,www.test4.com");
+ Services.prefs.setCharPref("xpinstall.whitelist.add.test5", "test5.com");
+
+ Services.perms.add(NetUtil.newURI("https://www.test9.com"), "install",
+ AM_Ci.nsIPermissionManager.ALLOW_ACTION);
+
+ startupManager();
+
+ do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("http://test1.com")));
+ do_check_true(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://test1.com")));
+ do_check_true(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://www.test2.com")));
+ do_check_true(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://test3.com")));
+ do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://test4.com")));
+ do_check_true(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://www.test4.com")));
+ do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("http://www.test5.com")));
+ do_check_true(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://www.test5.com")));
+
+ do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("http://www.test6.com")));
+ do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://www.test6.com")));
+ do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://test7.com")));
+ do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://www.test8.com")));
+
+ // This should remain unaffected
+ do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("http://www.test9.com")));
+ do_check_true(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://www.test9.com")));
+
+ Services.perms.removeAll();
+
+ do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://test1.com")));
+ do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://www.test2.com")));
+ do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://test3.com")));
+ do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://www.test4.com")));
+ do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://www.test5.com")));
+
+ // Upgrade the application and verify that the permissions are still not there
+ restartManager("2");
+
+ do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://test1.com")));
+ do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://www.test2.com")));
+ do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://test3.com")));
+ do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://www.test4.com")));
+ do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://www.test5.com")));
+}
diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_permissions_prefs.js b/toolkit/mozapps/extensions/test/xpcshell/test_permissions_prefs.js index 576f04a65..ae1373214 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_permissions_prefs.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_permissions_prefs.js @@ -1,74 +1,74 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -// Tests that xpinstall.[whitelist|blacklist].add preferences are emptied when -// converted into permissions. - -const PREF_XPI_WHITELIST_PERMISSIONS = "xpinstall.whitelist.add"; -const PREF_XPI_BLACKLIST_PERMISSIONS = "xpinstall.blacklist.add"; - -function newPrincipal(uri) { - return Services.scriptSecurityManager.createCodebasePrincipal(NetUtil.newURI(uri), {}); -} - -function do_check_permission_prefs(preferences) { - // Check preferences were emptied - for (let pref of preferences) { - try { - do_check_eq(Services.prefs.getCharPref(pref), ""); - } - catch (e) { - // Successfully emptied - } - } -} - -function clear_imported_preferences_cache() { - let scope = Components.utils.import("resource://gre/modules/PermissionsUtils.jsm", {}); - scope.gImportedPrefBranches.clear(); -} - -function run_test() { - createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9"); - - // Create own preferences to test - Services.prefs.setCharPref("xpinstall.whitelist.add.EMPTY", ""); - Services.prefs.setCharPref("xpinstall.whitelist.add.TEST", "http://whitelist.example.com"); - Services.prefs.setCharPref("xpinstall.blacklist.add.EMPTY", ""); - Services.prefs.setCharPref("xpinstall.blacklist.add.TEST", "http://blacklist.example.com"); - - // Get list of preferences to check - var whitelistPreferences = Services.prefs.getChildList(PREF_XPI_WHITELIST_PERMISSIONS, {}); - var blacklistPreferences = Services.prefs.getChildList(PREF_XPI_BLACKLIST_PERMISSIONS, {}); - var preferences = whitelistPreferences.concat(blacklistPreferences); - - startupManager(); - - // Permissions are imported lazily - act as thought we're checking an install, - // to trigger on-deman importing of the permissions. - AddonManager.isInstallAllowed("application/x-xpinstall", newPrincipal("http://example.com/file.xpi")); - do_check_permission_prefs(preferences); - - - // Import can also be triggerred by an observer notification by any other area - // of code, such as a permissions management UI. - - // First, request to flush all permissions - clear_imported_preferences_cache(); - Services.prefs.setCharPref("xpinstall.whitelist.add.TEST2", "https://whitelist2.example.com"); - Services.obs.notifyObservers(null, "flush-pending-permissions", "install"); - do_check_permission_prefs(preferences); - - // Then, request to flush just install permissions - clear_imported_preferences_cache(); - Services.prefs.setCharPref("xpinstall.whitelist.add.TEST3", "https://whitelist3.example.com"); - Services.obs.notifyObservers(null, "flush-pending-permissions", ""); - do_check_permission_prefs(preferences); - - // And a request to flush some other permissions sholdn't flush install permissions - clear_imported_preferences_cache(); - Services.prefs.setCharPref("xpinstall.whitelist.add.TEST4", "https://whitelist4.example.com"); - Services.obs.notifyObservers(null, "flush-pending-permissions", "lolcats"); - do_check_eq(Services.prefs.getCharPref("xpinstall.whitelist.add.TEST4"), "https://whitelist4.example.com"); -} +/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Tests that xpinstall.[whitelist|blacklist].add preferences are emptied when
+// converted into permissions.
+
+const PREF_XPI_WHITELIST_PERMISSIONS = "xpinstall.whitelist.add";
+const PREF_XPI_BLACKLIST_PERMISSIONS = "xpinstall.blacklist.add";
+
+function newPrincipal(uri) {
+ return Services.scriptSecurityManager.getNoAppCodebasePrincipal(NetUtil.newURI(uri));
+}
+
+function do_check_permission_prefs(preferences) {
+ // Check preferences were emptied
+ for (let pref of preferences) {
+ try {
+ do_check_eq(Services.prefs.getCharPref(pref), "");
+ }
+ catch (e) {
+ // Successfully emptied
+ }
+ }
+}
+
+function clear_imported_preferences_cache() {
+ let scope = Components.utils.import("resource://gre/modules/PermissionsUtils.jsm", {});
+ scope.gImportedPrefBranches.clear();
+}
+
+function run_test() {
+ createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9");
+
+ // Create own preferences to test
+ Services.prefs.setCharPref("xpinstall.whitelist.add.EMPTY", "");
+ Services.prefs.setCharPref("xpinstall.whitelist.add.TEST", "whitelist.example.com");
+ Services.prefs.setCharPref("xpinstall.blacklist.add.EMPTY", "");
+ Services.prefs.setCharPref("xpinstall.blacklist.add.TEST", "blacklist.example.com");
+
+ // Get list of preferences to check
+ var whitelistPreferences = Services.prefs.getChildList(PREF_XPI_WHITELIST_PERMISSIONS, {});
+ var blacklistPreferences = Services.prefs.getChildList(PREF_XPI_BLACKLIST_PERMISSIONS, {});
+ var preferences = whitelistPreferences.concat(blacklistPreferences);
+
+ startupManager();
+
+ // Permissions are imported lazily - act as thought we're checking an install,
+ // to trigger on-deman importing of the permissions.
+ AddonManager.isInstallAllowed("application/x-xpinstall", newPrincipal("http://example.com/file.xpi"));
+ do_check_permission_prefs(preferences);
+
+
+ // Import can also be triggerred by an observer notification by any other area
+ // of code, such as a permissions management UI.
+
+ // First, request to flush all permissions
+ clear_imported_preferences_cache();
+ Services.prefs.setCharPref("xpinstall.whitelist.add.TEST2", "whitelist2.example.com");
+ Services.obs.notifyObservers(null, "flush-pending-permissions", "install");
+ do_check_permission_prefs(preferences);
+
+ // Then, request to flush just install permissions
+ clear_imported_preferences_cache();
+ Services.prefs.setCharPref("xpinstall.whitelist.add.TEST3", "whitelist3.example.com");
+ Services.obs.notifyObservers(null, "flush-pending-permissions", "");
+ do_check_permission_prefs(preferences);
+
+ // And a request to flush some other permissions sholdn't flush install permissions
+ clear_imported_preferences_cache();
+ Services.prefs.setCharPref("xpinstall.whitelist.add.TEST4", "whitelist4.example.com");
+ Services.obs.notifyObservers(null, "flush-pending-permissions", "lolcats");
+ do_check_eq(Services.prefs.getCharPref("xpinstall.whitelist.add.TEST4"), "whitelist4.example.com");
+}
diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_pluginBlocklistCtp.js b/toolkit/mozapps/extensions/test/xpcshell/test_pluginBlocklistCtp.js index 563b7434c..8d7e944e2 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_pluginBlocklistCtp.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_pluginBlocklistCtp.js @@ -161,7 +161,6 @@ function run_test() { createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9"); Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" + gPort + "/data/test_pluginBlocklistCtp.xml"); - Services.prefs.setBoolPref("plugin.load_flash_only", false); startupManager(); gPluginHost = Components.classes["@mozilla.org/plugin/host;1"].getService(Components.interfaces.nsIPluginHost); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_pluginInfoURL.js b/toolkit/mozapps/extensions/test/xpcshell/test_pluginInfoURL.js index e5acb28a4..e140f021a 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_pluginInfoURL.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_pluginInfoURL.js @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -var Ci = Components.interfaces; +const Ci = Components.interfaces; Components.utils.import("resource://gre/modules/Services.jsm"); /** @@ -30,9 +30,7 @@ MockPlugin.prototype = { const PLUGINS = [ new MockPlugin('test_with_infoURL', '5', Ci.nsIPluginTag.STATE_ENABLED), new MockPlugin('test_with_altInfoURL', '5', Ci.nsIPluginTag.STATE_ENABLED), - new MockPlugin('test_no_infoURL', '5', Ci.nsIPluginTag.STATE_ENABLED), - new MockPlugin('test_newVersion', '1', Ci.nsIPluginTag.STATE_ENABLED), - new MockPlugin('test_newVersion', '3', Ci.nsIPluginTag.STATE_ENABLED) + new MockPlugin('test_no_infoURL', '5', Ci.nsIPluginTag.STATE_ENABLED) ]; /** @@ -80,11 +78,3 @@ add_task(function* test_infoURL_missing() { Assert.strictEqual(Services.blocklist.getPluginInfoURL(PLUGINS[2]), null, 'Should be null when no infoURL tag is available.'); }); - -add_task(function* test_intoURL_newVersion() { - let testInfoURL = 'http://test.url2.com/'; - Assert.strictEqual(Services.blocklist.getPluginInfoURL(PLUGINS[3]), - testInfoURL, 'Old plugin should match'); - Assert.strictEqual(Services.blocklist.getPluginInfoURL(PLUGINS[4]), - null, 'New plugin should not match'); -}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_pluginchange.js b/toolkit/mozapps/extensions/test/xpcshell/test_pluginchange.js index 05e17b35e..d3e33dac3 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_pluginchange.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_pluginchange.js @@ -1,283 +1,292 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -const LIST_UPDATED_TOPIC = "plugins-list-updated"; - -// We need to use the same algorithm for generating IDs for plugins -var { getIDHashForString } = Components.utils.import("resource://gre/modules/addons/PluginProvider.jsm"); -var { MockRegistrar } = Components.utils.import("resource://testing-common/MockRegistrar.jsm"); - -function PluginTag(name, description) { - this.name = name; - this.description = description; -} - -PluginTag.prototype = { - name: null, - description: null, - version: "1.0", - filename: null, - fullpath: null, - disabled: false, - blocklisted: false, - clicktoplay: false, - - mimeTypes: [], - - getMimeTypes: function(count) { - count.value = this.mimeTypes.length; - return this.mimeTypes; - } -}; - -const PLUGINS = [ - // A standalone plugin - new PluginTag("Java", "A mock Java plugin"), - - // A plugin made up of two plugin files - new PluginTag("Flash", "A mock Flash plugin"), - new PluginTag("Flash", "A mock Flash plugin") -]; - -const gPluginHost = { - // nsIPluginHost - getPluginTags: function(count) { - count.value = PLUGINS.length; - return PLUGINS; - }, - - QueryInterface: XPCOMUtils.generateQI([AM_Ci.nsIPluginHost]) -}; - -MockRegistrar.register("@mozilla.org/plugin/host;1", gPluginHost); - -// This verifies that when the list of plugins changes the add-ons manager -// correctly updates -function run_test() { - do_test_pending(); - createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); - - Services.prefs.setBoolPref("media.gmp-provider.enabled", false); - - startupManager(); - AddonManager.addAddonListener(AddonListener); - AddonManager.addInstallListener(InstallListener); - - run_test_1(); -} - -function end_test() { - do_execute_soon(do_test_finished); -} - -function sortAddons(addons) { - addons.sort(function(a, b) { - return a.name.localeCompare(b.name); - }); -} - -// Basic check that the mock object works -function run_test_1() { - AddonManager.getAddonsByTypes(["plugin"], function(addons) { - sortAddons(addons); - - do_check_eq(addons.length, 2); - - do_check_eq(addons[0].name, "Flash"); - do_check_false(addons[0].userDisabled); - do_check_eq(addons[1].name, "Java"); - do_check_false(addons[1].userDisabled); - - run_test_2(); - }); -} - -// No change to the list should not trigger any events or changes in the API -function run_test_2() { - // Reorder the list a bit - let tag = PLUGINS[0]; - PLUGINS[0] = PLUGINS[2]; - PLUGINS[2] = PLUGINS[1]; - PLUGINS[1] = tag; - - Services.obs.notifyObservers(null, LIST_UPDATED_TOPIC, null); - - AddonManager.getAddonsByTypes(["plugin"], function(addons) { - sortAddons(addons); - - do_check_eq(addons.length, 2); - - do_check_eq(addons[0].name, "Flash"); - do_check_false(addons[0].userDisabled); - do_check_eq(addons[1].name, "Java"); - do_check_false(addons[1].userDisabled); - - run_test_3(); - }); -} - -// Tests that a newly detected plugin shows up in the API and sends out events -function run_test_3() { - let tag = new PluginTag("Quicktime", "A mock Quicktime plugin"); - PLUGINS.push(tag); - let id = getIDHashForString(tag.name + tag.description); - - let test_params = {}; - test_params[id] = [ - ["onInstalling", false], - "onInstalled" - ]; - - prepare_test(test_params, [ - "onExternalInstall" - ]); - - Services.obs.notifyObservers(null, LIST_UPDATED_TOPIC, null); - - ensure_test_completed(); - - AddonManager.getAddonsByTypes(["plugin"], function(addons) { - sortAddons(addons); - - do_check_eq(addons.length, 3); - - do_check_eq(addons[0].name, "Flash"); - do_check_false(addons[0].userDisabled); - do_check_eq(addons[1].name, "Java"); - do_check_false(addons[1].userDisabled); - do_check_eq(addons[2].name, "Quicktime"); - do_check_false(addons[2].userDisabled); - - run_test_4(); - }); -} - -// Tests that a removed plugin disappears from in the API and sends out events -function run_test_4() { - let tag = PLUGINS.splice(1, 1)[0]; - let id = getIDHashForString(tag.name + tag.description); - - let test_params = {}; - test_params[id] = [ - ["onUninstalling", false], - "onUninstalled" - ]; - - prepare_test(test_params); - - Services.obs.notifyObservers(null, LIST_UPDATED_TOPIC, null); - - ensure_test_completed(); - - AddonManager.getAddonsByTypes(["plugin"], function(addons) { - sortAddons(addons); - - do_check_eq(addons.length, 2); - - do_check_eq(addons[0].name, "Flash"); - do_check_false(addons[0].userDisabled); - do_check_eq(addons[1].name, "Quicktime"); - do_check_false(addons[1].userDisabled); - - run_test_5(); - }); -} - -// Removing part of the flash plugin should have no effect -function run_test_5() { - PLUGINS.splice(0, 1); - - Services.obs.notifyObservers(null, LIST_UPDATED_TOPIC, null); - - ensure_test_completed(); - - AddonManager.getAddonsByTypes(["plugin"], function(addons) { - sortAddons(addons); - - do_check_eq(addons.length, 2); - - do_check_eq(addons[0].name, "Flash"); - do_check_false(addons[0].userDisabled); - do_check_eq(addons[1].name, "Quicktime"); - do_check_false(addons[1].userDisabled); - - run_test_6(); - }); -} - -// Replacing flash should be detected -function run_test_6() { - let oldTag = PLUGINS.splice(0, 1)[0]; - let newTag = new PluginTag("Flash 2", "A new crash-free Flash!"); - newTag.disabled = true; - PLUGINS.push(newTag); - - let test_params = {}; - test_params[getIDHashForString(oldTag.name + oldTag.description)] = [ - ["onUninstalling", false], - "onUninstalled" - ]; - test_params[getIDHashForString(newTag.name + newTag.description)] = [ - ["onInstalling", false], - "onInstalled" - ]; - - prepare_test(test_params, [ - "onExternalInstall" - ]); - - Services.obs.notifyObservers(null, LIST_UPDATED_TOPIC, null); - - ensure_test_completed(); - - AddonManager.getAddonsByTypes(["plugin"], function(addons) { - sortAddons(addons); - - do_check_eq(addons.length, 2); - - do_check_eq(addons[0].name, "Flash 2"); - do_check_true(addons[0].userDisabled); - do_check_eq(addons[1].name, "Quicktime"); - do_check_false(addons[1].userDisabled); - - run_test_7(); - }); -} - -// If new tags are detected and the disabled state changes then we should send -// out appropriate notifications -function run_test_7() { - PLUGINS[0] = new PluginTag("Quicktime", "A mock Quicktime plugin"); - PLUGINS[0].disabled = true; - PLUGINS[1] = new PluginTag("Flash 2", "A new crash-free Flash!"); - - let test_params = {}; - test_params[getIDHashForString(PLUGINS[0].name + PLUGINS[0].description)] = [ - ["onDisabling", false], - "onDisabled" - ]; - test_params[getIDHashForString(PLUGINS[1].name + PLUGINS[1].description)] = [ - ["onEnabling", false], - "onEnabled" - ]; - - prepare_test(test_params); - - Services.obs.notifyObservers(null, LIST_UPDATED_TOPIC, null); - - ensure_test_completed(); - - AddonManager.getAddonsByTypes(["plugin"], function(addons) { - sortAddons(addons); - - do_check_eq(addons.length, 2); - - do_check_eq(addons[0].name, "Flash 2"); - do_check_false(addons[0].userDisabled); - do_check_eq(addons[1].name, "Quicktime"); - do_check_true(addons[1].userDisabled); - - end_test(); - }); -} +/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+const LIST_UPDATED_TOPIC = "plugins-list-updated";
+
+// We need to use the same algorithm for generating IDs for plugins
+var { getIDHashForString } = Components.utils.import("resource://gre/modules/addons/PluginProvider.jsm");
+
+function PluginTag(name, description) {
+ this.name = name;
+ this.description = description;
+}
+
+PluginTag.prototype = {
+ name: null,
+ description: null,
+ version: "1.0",
+ filename: null,
+ fullpath: null,
+ disabled: false,
+ blocklisted: false,
+ clicktoplay: false,
+
+ mimeTypes: [],
+
+ getMimeTypes: function(count) {
+ count.value = this.mimeTypes.length;
+ return this.mimeTypes;
+ }
+};
+
+PLUGINS = [
+ // A standalone plugin
+ new PluginTag("Java", "A mock Java plugin"),
+
+ // A plugin made up of two plugin files
+ new PluginTag("Flash", "A mock Flash plugin"),
+ new PluginTag("Flash", "A mock Flash plugin")
+];
+
+gPluginHost = {
+ // nsIPluginHost
+ getPluginTags: function(count) {
+ count.value = PLUGINS.length;
+ return PLUGINS;
+ },
+
+ QueryInterface: XPCOMUtils.generateQI([AM_Ci.nsIPluginHost])
+};
+
+var PluginHostFactory = {
+ createInstance: function (outer, iid) {
+ if (outer != null)
+ throw Components.results.NS_ERROR_NO_AGGREGATION;
+ return gPluginHost.QueryInterface(iid);
+ }
+};
+
+var registrar = Components.manager.QueryInterface(AM_Ci.nsIComponentRegistrar);
+registrar.registerFactory(Components.ID("{aa6f9fef-cbe2-4d55-a2fa-dcf5482068b9}"), "PluginHost",
+ "@mozilla.org/plugin/host;1", PluginHostFactory);
+
+// This verifies that when the list of plugins changes the add-ons manager
+// correctly updates
+function run_test() {
+ do_test_pending();
+ createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
+
+ Services.prefs.setBoolPref("media.gmp-provider.enabled", false);
+
+ startupManager();
+ AddonManager.addAddonListener(AddonListener);
+ AddonManager.addInstallListener(InstallListener);
+
+ run_test_1();
+}
+
+function end_test() {
+ do_execute_soon(do_test_finished);
+}
+
+function sortAddons(addons) {
+ addons.sort(function(a, b) {
+ return a.name.localeCompare(b.name);
+ });
+}
+
+// Basic check that the mock object works
+function run_test_1() {
+ AddonManager.getAddonsByTypes(["plugin"], function(addons) {
+ sortAddons(addons);
+
+ do_check_eq(addons.length, 2);
+
+ do_check_eq(addons[0].name, "Flash");
+ do_check_false(addons[0].userDisabled);
+ do_check_eq(addons[1].name, "Java");
+ do_check_false(addons[1].userDisabled);
+
+ run_test_2();
+ });
+}
+
+// No change to the list should not trigger any events or changes in the API
+function run_test_2() {
+ // Reorder the list a bit
+ let tag = PLUGINS[0];
+ PLUGINS[0] = PLUGINS[2];
+ PLUGINS[2] = PLUGINS[1];
+ PLUGINS[1] = tag;
+
+ Services.obs.notifyObservers(null, LIST_UPDATED_TOPIC, null);
+
+ AddonManager.getAddonsByTypes(["plugin"], function(addons) {
+ sortAddons(addons);
+
+ do_check_eq(addons.length, 2);
+
+ do_check_eq(addons[0].name, "Flash");
+ do_check_false(addons[0].userDisabled);
+ do_check_eq(addons[1].name, "Java");
+ do_check_false(addons[1].userDisabled);
+
+ run_test_3();
+ });
+}
+
+// Tests that a newly detected plugin shows up in the API and sends out events
+function run_test_3() {
+ let tag = new PluginTag("Quicktime", "A mock Quicktime plugin");
+ PLUGINS.push(tag);
+ let id = getIDHashForString(tag.name + tag.description);
+
+ let test_params = {};
+ test_params[id] = [
+ ["onInstalling", false],
+ "onInstalled"
+ ];
+
+ prepare_test(test_params, [
+ "onExternalInstall"
+ ]);
+
+ Services.obs.notifyObservers(null, LIST_UPDATED_TOPIC, null);
+
+ ensure_test_completed();
+
+ AddonManager.getAddonsByTypes(["plugin"], function(addons) {
+ sortAddons(addons);
+
+ do_check_eq(addons.length, 3);
+
+ do_check_eq(addons[0].name, "Flash");
+ do_check_false(addons[0].userDisabled);
+ do_check_eq(addons[1].name, "Java");
+ do_check_false(addons[1].userDisabled);
+ do_check_eq(addons[2].name, "Quicktime");
+ do_check_false(addons[2].userDisabled);
+
+ run_test_4();
+ });
+}
+
+// Tests that a removed plugin disappears from in the API and sends out events
+function run_test_4() {
+ let tag = PLUGINS.splice(1, 1)[0];
+ let id = getIDHashForString(tag.name + tag.description);
+
+ let test_params = {};
+ test_params[id] = [
+ ["onUninstalling", false],
+ "onUninstalled"
+ ];
+
+ prepare_test(test_params);
+
+ Services.obs.notifyObservers(null, LIST_UPDATED_TOPIC, null);
+
+ ensure_test_completed();
+
+ AddonManager.getAddonsByTypes(["plugin"], function(addons) {
+ sortAddons(addons);
+
+ do_check_eq(addons.length, 2);
+
+ do_check_eq(addons[0].name, "Flash");
+ do_check_false(addons[0].userDisabled);
+ do_check_eq(addons[1].name, "Quicktime");
+ do_check_false(addons[1].userDisabled);
+
+ run_test_5();
+ });
+}
+
+// Removing part of the flash plugin should have no effect
+function run_test_5() {
+ PLUGINS.splice(0, 1);
+
+ Services.obs.notifyObservers(null, LIST_UPDATED_TOPIC, null);
+
+ ensure_test_completed();
+
+ AddonManager.getAddonsByTypes(["plugin"], function(addons) {
+ sortAddons(addons);
+
+ do_check_eq(addons.length, 2);
+
+ do_check_eq(addons[0].name, "Flash");
+ do_check_false(addons[0].userDisabled);
+ do_check_eq(addons[1].name, "Quicktime");
+ do_check_false(addons[1].userDisabled);
+
+ run_test_6();
+ });
+}
+
+// Replacing flash should be detected
+function run_test_6() {
+ let oldTag = PLUGINS.splice(0, 1)[0];
+ let newTag = new PluginTag("Flash 2", "A new crash-free Flash!");
+ newTag.disabled = true;
+ PLUGINS.push(newTag);
+
+ let test_params = {};
+ test_params[getIDHashForString(oldTag.name + oldTag.description)] = [
+ ["onUninstalling", false],
+ "onUninstalled"
+ ];
+ test_params[getIDHashForString(newTag.name + newTag.description)] = [
+ ["onInstalling", false],
+ "onInstalled"
+ ];
+
+ prepare_test(test_params, [
+ "onExternalInstall"
+ ]);
+
+ Services.obs.notifyObservers(null, LIST_UPDATED_TOPIC, null);
+
+ ensure_test_completed();
+
+ AddonManager.getAddonsByTypes(["plugin"], function(addons) {
+ sortAddons(addons);
+
+ do_check_eq(addons.length, 2);
+
+ do_check_eq(addons[0].name, "Flash 2");
+ do_check_true(addons[0].userDisabled);
+ do_check_eq(addons[1].name, "Quicktime");
+ do_check_false(addons[1].userDisabled);
+
+ run_test_7();
+ });
+}
+
+// If new tags are detected and the disabled state changes then we should send
+// out appropriate notifications
+function run_test_7() {
+ PLUGINS[0] = new PluginTag("Quicktime", "A mock Quicktime plugin");
+ PLUGINS[0].disabled = true;
+ PLUGINS[1] = new PluginTag("Flash 2", "A new crash-free Flash!");
+
+ let test_params = {};
+ test_params[getIDHashForString(PLUGINS[0].name + PLUGINS[0].description)] = [
+ ["onDisabling", false],
+ "onDisabled"
+ ];
+ test_params[getIDHashForString(PLUGINS[1].name + PLUGINS[1].description)] = [
+ ["onEnabling", false],
+ "onEnabled"
+ ];
+
+ prepare_test(test_params);
+
+ Services.obs.notifyObservers(null, LIST_UPDATED_TOPIC, null);
+
+ ensure_test_completed();
+
+ AddonManager.getAddonsByTypes(["plugin"], function(addons) {
+ sortAddons(addons);
+
+ do_check_eq(addons.length, 2);
+
+ do_check_eq(addons[0].name, "Flash 2");
+ do_check_false(addons[0].userDisabled);
+ do_check_eq(addons[1].name, "Quicktime");
+ do_check_true(addons[1].userDisabled);
+
+ end_test();
+ });
+}
diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_plugins.js b/toolkit/mozapps/extensions/test/xpcshell/test_plugins.js index 3f0ac7ebe..5541bc946 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_plugins.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_plugins.js @@ -2,8 +2,6 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -var TEST_PLUGIN_DESCRIPTION = "Flash plug-in for testing purposes."; - // This verifies that plugins exist and can be enabled and disabled. var gID = null; @@ -11,8 +9,7 @@ function setTestPluginState(state) { let tags = AM_Cc["@mozilla.org/plugin/host;1"].getService(AM_Ci.nsIPluginHost) .getPluginTags(); for (let tag of tags) { - do_print("Checking tag: " + tag.description); - if (tag.description == TEST_PLUGIN_DESCRIPTION) { + if (tag.name == "Test Plug-in") { tag.enabledState = state; return; } @@ -24,7 +21,6 @@ function run_test() { do_test_pending(); createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); Services.prefs.setBoolPref("plugins.click_to_play", true); - Services.prefs.setBoolPref("plugin.load_flash_only", false); setTestPluginState(AM_Ci.nsIPluginTag.STATE_CLICKTOPLAY); @@ -42,21 +38,21 @@ function get_test_plugin() { let dir = pluginEnum.getNext().QueryInterface(AM_Ci.nsILocalFile); let plugin = dir.clone(); // OSX plugin - plugin.append("npswftest.plugin"); + plugin.append("Test.plugin"); if (plugin.exists()) { plugin.normalize(); return plugin; } plugin = dir.clone(); // *nix plugin - plugin.append("libnpswftest.so"); + plugin.append("libnptest.so"); if (plugin.exists()) { plugin.normalize(); return plugin; } // Windows plugin plugin = dir.clone(); - plugin.append("npswftest.dll"); + plugin.append("nptest.dll"); if (plugin.exists()) { plugin.normalize(); return plugin; @@ -102,7 +98,7 @@ function run_test_1() { do_check_true(addons.length > 0); addons.forEach(function(p) { - if (p.description == TEST_PLUGIN_DESCRIPTION) + if (p.name == "Test Plug-in") gID = p.id; }); @@ -110,8 +106,12 @@ function run_test_1() { AddonManager.getAddonByID(gID, function(p) { do_check_neq(p, null); - do_check_eq(p.name, "Shockwave Flash"); - do_check_eq(p.description, TEST_PLUGIN_DESCRIPTION); + do_check_eq(p.name, "Test Plug-in"); + do_check_eq(p.description, + "Plug-in for testing purposes.\u2122 " + + "(\u0939\u093f\u0928\u094d\u0926\u0940 " + + "\u4e2d\u6587 " + + "\u0627\u0644\u0639\u0631\u0628\u064a\u0629)"); do_check_eq(p.creator, null); do_check_eq(p.version, "1.0.0.0"); do_check_eq(p.type, "plugin"); @@ -156,14 +156,14 @@ function run_test_2(p) { do_check_false(p.appDisabled); do_check_false(p.isActive); - AddonManager.getAddonByID(gID, function(p2) { - do_check_neq(p2, null); - do_check_true(p2.userDisabled); - do_check_false(p2.appDisabled); - do_check_false(p2.isActive); - do_check_eq(p2.name, "Shockwave Flash"); + AddonManager.getAddonByID(gID, function(p) { + do_check_neq(p, null); + do_check_true(p.userDisabled); + do_check_false(p.appDisabled); + do_check_false(p.isActive); + do_check_eq(p.name, "Test Plug-in"); - run_test_3(p2); + run_test_3(p); }); } @@ -184,12 +184,12 @@ function run_test_3(p) { do_check_false(p.appDisabled); do_check_true(p.isActive); - AddonManager.getAddonByID(gID, function(p2) { - do_check_neq(p2, null); - do_check_false(p2.userDisabled); - do_check_false(p2.appDisabled); - do_check_true(p2.isActive); - do_check_eq(p2.name, "Shockwave Flash"); + AddonManager.getAddonByID(gID, function(p) { + do_check_neq(p, null); + do_check_false(p.userDisabled); + do_check_false(p.appDisabled); + do_check_true(p.isActive); + do_check_eq(p.name, "Test Plug-in"); do_execute_soon(run_test_4); }); @@ -201,7 +201,7 @@ function run_test_4() { AddonManager.getAddonByID(gID, function(p) { do_check_neq(p, null); - do_check_eq(p.name, "Shockwave Flash"); + do_check_eq(p.name, "Test Plug-in"); Services.prefs.clearUserPref("plugins.click_to_play"); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_pref_properties.js b/toolkit/mozapps/extensions/test/xpcshell/test_pref_properties.js index c6a10e7c1..9abffaab0 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_pref_properties.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_pref_properties.js @@ -199,21 +199,6 @@ function run_test() { gManagerEventsListener.shutdown(); - // AddonManager.hotfixID - let hotfixID = "hotfix@tests.mozilla.org"; - Services.prefs.setCharPref("extensions.hotfix.id", hotfixID); - do_check_eq(AddonManager.hotfixID, hotfixID); - // Change the pref and make sure the property is updated - hotfixID = "hotfix2@tests.mozilla.org"; - Services.prefs.setCharPref("extensions.hotfix.id", hotfixID); - do_check_eq(AddonManager.hotfixID, hotfixID); - // Test an invalid pref value - hotfixID = 99; - Services.prefs.deleteBranch("extensions.hotfix.id"); - Services.prefs.setIntPref("extensions.hotfix.id", hotfixID); - do_check_eq(AddonManager.hotfixID, null); - Services.prefs.clearUserPref("extensions.hotfix.id"); - // After removing the listener, ensure we get no further events. gManagerEventsListener.expect([]); AddonManager.updateEnabled = false; diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_provider_markSafe.js b/toolkit/mozapps/extensions/test/xpcshell/test_provider_markSafe.js index 228eb7d34..55d503f2c 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_provider_markSafe.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_provider_markSafe.js @@ -1,6 +1,6 @@ createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); -var startupOrder = []; +let startupOrder = []; function mockAddonProvider(name) { let mockProvider = { @@ -19,13 +19,11 @@ function mockAddonProvider(name) { return false; }, - get name() { - return name; - }, + get name() name, }; return mockProvider; -} +}; function run_test() { run_next_test(); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_provider_shutdown.js b/toolkit/mozapps/extensions/test/xpcshell/test_provider_shutdown.js index d210eb81d..f6de26241 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_provider_shutdown.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_provider_shutdown.js @@ -18,9 +18,7 @@ function mockAddonProvider(aName) { shutdownPromise: null, shutdownResolve: null, - get name() { - return aName; - }, + get name() aName, shutdown() { this.shutdownResolve(); @@ -35,7 +33,7 @@ function mockAddonProvider(aName) { mockProvider.shutdownResolve = resolve; }); return mockProvider; -} +}; function run_test() { run_next_test(); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_provider_unsafe_access_shutdown.js b/toolkit/mozapps/extensions/test/xpcshell/test_provider_unsafe_access_shutdown.js index f90e38292..df717f5a5 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_provider_unsafe_access_shutdown.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_provider_unsafe_access_shutdown.js @@ -1,6 +1,6 @@ createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); -var shutdownOrder = []; +let shutdownOrder = []; function mockAddonProvider(name) { let mockProvider = { @@ -15,22 +15,19 @@ function mockAddonProvider(name) { shutdownOrder.push(this.name); if (this.shutdownCallback) return this.shutdownCallback(); - return undefined; }, getAddonByID(id, callback) { if (this.hasShutdown) { - this.unsafeAccess = true; + unsafeAccess = true; } callback(null); }, - get name() { - return name; - }, + get name() name, }; return mockProvider; -} +}; function run_test() { run_next_test(); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_provider_unsafe_access_startup.js b/toolkit/mozapps/extensions/test/xpcshell/test_provider_unsafe_access_startup.js index 1193ddfe4..867dc9673 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_provider_unsafe_access_startup.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_provider_unsafe_access_startup.js @@ -1,6 +1,6 @@ createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); -var startupOrder = []; +let startupOrder = []; function mockAddonProvider(name) { let mockProvider = { @@ -17,18 +17,16 @@ function mockAddonProvider(name) { }, getAddonByID(id, callback) { if (!this.hasStarted) { - this.unsafeAccess = true; + unsafeAccess = true; } callback(null); }, - get name() { - return name; - }, + get name() name, }; return mockProvider; -} +}; function run_test() { run_next_test(); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_proxies.js b/toolkit/mozapps/extensions/test/xpcshell/test_proxies.js deleted file mode 100644 index 7b28c78f2..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_proxies.js +++ /dev/null @@ -1,240 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -// Tests the semantics of extension proxy files and symlinks - -Components.utils.import("resource://gre/modules/AppConstants.jsm"); -Components.utils.import("resource://gre/modules/osfile.jsm"); - -var ADDONS = [ - { - id: "proxy1@tests.mozilla.org", - dirId: "proxy1@tests.mozilla.com", - type: "proxy" - }, - { - id: "proxy2@tests.mozilla.org", - type: "proxy" - }, - { - id: "symlink1@tests.mozilla.org", - dirId: "symlink1@tests.mozilla.com", - type: "symlink" - }, - { - id: "symlink2@tests.mozilla.org", - type: "symlink" - } -]; - -var METADATA = { - version: "2.0", - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "2", - maxVersion: "2" - }] -} - -const ios = AM_Cc["@mozilla.org/network/io-service;1"].getService(AM_Ci.nsIIOService); - -const LocalFile = Components.Constructor("@mozilla.org/file/local;1", - "nsILocalFile", "initWithPath"); -const Process = Components.Constructor("@mozilla.org/process/util;1", - "nsIProcess", "init"); - -const gHaveSymlinks = AppConstants.platform != "win"; - - -function createSymlink(aSource, aDest) { - if (aSource instanceof AM_Ci.nsIFile) - aSource = aSource.path; - if (aDest instanceof AM_Ci.nsIFile) - aDest = aDest.path; - - return OS.File.unixSymLink(aSource, aDest); -} - -function writeFile(aData, aFile) { - if (!aFile.parent.exists()) - aFile.parent.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0o755); - - var fos = AM_Cc["@mozilla.org/network/file-output-stream;1"]. - createInstance(AM_Ci.nsIFileOutputStream); - fos.init(aFile, - FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE | FileUtils.MODE_TRUNCATE, - FileUtils.PERMS_FILE, 0); - fos.write(aData, aData.length); - fos.close(); -} - -function checkAddonsExist() { - for (let addon of ADDONS) { - let file = addon.directory.clone(); - file.append("install.rdf"); - do_check_true(file.exists(), Components.stack.caller); - } -} - - -const profileDir = gProfD.clone(); -profileDir.append("extensions"); - - -function run_test() { - createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "2"); - - add_task(run_proxy_tests); - - if (gHaveSymlinks) - add_task(run_symlink_tests); - - run_next_test(); -} - -function* run_proxy_tests() { - if (!gHaveSymlinks) { - ADDONS = ADDONS.filter(a => a.type != "symlink"); - } - - for (let addon of ADDONS) { - addon.directory = gTmpD.clone(); - addon.directory.append(addon.id); - - addon.proxyFile = profileDir.clone(); - addon.proxyFile.append(addon.dirId || addon.id); - - METADATA.id = addon.id; - METADATA.name = addon.id; - writeInstallRDFToDir(METADATA, gTmpD); - - if (addon.type == "proxy") { - writeFile(addon.directory.path, addon.proxyFile) - } - else if (addon.type == "symlink") { - yield createSymlink(addon.directory, addon.proxyFile) - } - } - - startupManager(); - - // Check that all add-ons original sources still exist after invalid - // add-ons have been removed at startup. - checkAddonsExist(); - - return new Promise(resolve => { - AddonManager.getAddonsByIDs(ADDONS.map(addon => addon.id), resolve); - }).then(addons => { - try { - for (let [i, addon] of addons.entries()) { - // Ensure that valid proxied add-ons were installed properly on - // platforms that support the installation method. - print(ADDONS[i].id, - ADDONS[i].dirId, - ADDONS[i].dirId != null, - ADDONS[i].type == "symlink"); - do_check_eq(addon == null, - ADDONS[i].dirId != null); - - if (addon != null) { - let fixURL = url => { - if (AppConstants.platform == "macosx") - return url.replace(RegExp(`^file:///private/`), "file:///"); - return url; - }; - - // Check that proxied add-ons do not have upgrade permissions. - do_check_eq(addon.permissions & AddonManager.PERM_CAN_UPGRADE, 0); - - // Check that getResourceURI points to the right place. - do_check_eq(ios.newFileURI(ADDONS[i].directory).spec, - fixURL(addon.getResourceURI().spec), - `Base resource URL resolves as expected`); - - let file = ADDONS[i].directory.clone(); - file.append("install.rdf"); - - do_check_eq(ios.newFileURI(file).spec, - fixURL(addon.getResourceURI("install.rdf").spec), - `Resource URLs resolve as expected`); - - addon.uninstall(); - } - } - - // Check that original sources still exist after explicit uninstall. - restartManager(); - checkAddonsExist(); - - shutdownManager(); - - // Check that all of the proxy files have been removed and remove - // the original targets. - for (let addon of ADDONS) { - equal(addon.proxyFile.exists(), addon.dirId != null, - `Proxy file ${addon.proxyFile.path} should exist?`); - addon.directory.remove(true); - try { - addon.proxyFile.remove(false); - } catch (e) {} - } - } - catch (e) { - do_throw(e); - } - }); -} - -function* run_symlink_tests() { - // Check that symlinks are not followed out of a directory tree - // when deleting an add-on. - - METADATA.id = "unpacked@test.mozilla.org"; - METADATA.name = METADATA.id; - METADATA.unpack = "true"; - - let tempDirectory = gTmpD.clone(); - tempDirectory.append(METADATA.id); - - let tempFile = tempDirectory.clone(); - tempFile.append("test.txt"); - tempFile.create(AM_Ci.nsIFile.NORMAL_FILE_TYPE, 0o644); - - let addonDirectory = profileDir.clone(); - addonDirectory.append(METADATA.id); - - writeInstallRDFToDir(METADATA, profileDir); - - let symlink = addonDirectory.clone(); - symlink.append(tempDirectory.leafName); - yield createSymlink(tempDirectory, symlink); - - // Make sure that the symlink was created properly. - let file = symlink.clone(); - file.append(tempFile.leafName); - file.normalize(); - do_check_eq(file.path.replace(/^\/private\//, "/"), tempFile.path); - - startupManager(); - - return new Promise(resolve => { - AddonManager.getAddonByID(METADATA.id, resolve); - }).then(addon => { - do_check_neq(addon, null); - - addon.uninstall(); - - restartManager(); - shutdownManager(); - - // Check that the install directory is gone. - do_check_false(addonDirectory.exists()); - - // Check that the temp file is not gone. - do_check_true(tempFile.exists()); - - tempDirectory.remove(true); - }); -} - diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_proxy.js b/toolkit/mozapps/extensions/test/xpcshell/test_proxy.js deleted file mode 100644 index c35870c9b..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_proxy.js +++ /dev/null @@ -1,106 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -const ID = "proxy1@tests.mozilla.org"; - -createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "42"); -startupManager(); - -BootstrapMonitor.init(); - -// Ensure that a proxy file to an add-on with a valid manifest works. -add_task(function*() { - let tempdir = gTmpD.clone(); - writeInstallRDFToDir({ - id: ID, - version: "1.0", - bootstrap: true, - unpack: true, - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "1", - maxVersion: "1" - }], - name: "Test Bootstrap 1 (proxy)", - }, tempdir, ID, "bootstrap.js"); - - let unpackedAddon = tempdir.clone(); - unpackedAddon.append(ID); - do_get_file("data/test_proxy/bootstrap.js") - .copyTo(unpackedAddon, "bootstrap.js"); - - // create proxy file in profile/extensions dir - let extensionsDir = gProfD.clone(); - extensionsDir.append("extensions"); - let proxyFile = writeProxyFileToDir(extensionsDir, unpackedAddon, ID); - - yield promiseRestartManager(); - - BootstrapMonitor.checkAddonInstalled(ID, "1.0"); - BootstrapMonitor.checkAddonStarted(ID, "1.0"); - - let addon = yield promiseAddonByID(ID); - - do_check_neq(addon, null); - do_check_eq(addon.version, "1.0"); - do_check_eq(addon.name, "Test Bootstrap 1 (proxy)"); - do_check_true(addon.isCompatible); - do_check_false(addon.appDisabled); - do_check_true(addon.isActive); - do_check_eq(addon.type, "extension"); - do_check_eq(addon.signedState, mozinfo.addon_signing ? AddonManager.SIGNEDSTATE_SIGNED : AddonManager.SIGNEDSTATE_NOT_REQUIRED); - - do_check_true(proxyFile.exists()); - - addon.uninstall(); - unpackedAddon.remove(true); - - yield promiseRestartManager(); -}); - - -// Ensure that a proxy file to an add-on is not removed even -// if the manifest file is invalid. See bug 1195353. -add_task(function*() { - let tempdir = gTmpD.clone(); - - // use a mismatched ID to make this install.rdf invalid - writeInstallRDFToDir({ - id: "bad-proxy1@tests.mozilla.org", - version: "1.0", - bootstrap: true, - unpack: true, - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "1", - maxVersion: "1" - }], - name: "Test Bootstrap 1 (proxy)", - }, tempdir, ID, "bootstrap.js"); - - let unpackedAddon = tempdir.clone(); - unpackedAddon.append(ID); - do_get_file("data/test_proxy/bootstrap.js") - .copyTo(unpackedAddon, "bootstrap.js"); - - // create proxy file in profile/extensions dir - let extensionsDir = gProfD.clone(); - extensionsDir.append("extensions"); - let proxyFile = writeProxyFileToDir(extensionsDir, unpackedAddon, ID); - - yield promiseRestartManager(); - - BootstrapMonitor.checkAddonNotInstalled(ID, "1.0"); - BootstrapMonitor.checkAddonNotStarted(ID, "1.0"); - - let addon = yield promiseAddonByID(ID); - do_check_eq(addon, null); - - do_check_true(proxyFile.exists()); - - unpackedAddon.remove(true); - proxyFile.remove(true); - - yield promiseRestartManager(); -}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_registry.js b/toolkit/mozapps/extensions/test/xpcshell/test_registry.js index eab7af6b6..010250457 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_registry.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_registry.js @@ -35,18 +35,11 @@ var addon2 = { const addon1Dir = writeInstallRDFForExtension(addon1, gProfD, "addon1"); const addon2Dir = writeInstallRDFForExtension(addon2, gProfD, "addon2"); -let registry; - function run_test() { // This test only works where there is a registry. if (!("nsIWindowsRegKey" in AM_Ci)) return; - registry = new MockRegistry(); - do_register_cleanup(() => { - registry.shutdown(); - }); - do_test_pending(); run_test_1(); @@ -54,12 +47,12 @@ function run_test() { // Tests whether basic registry install works function run_test_1() { - registry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE, - "SOFTWARE\\Mozilla\\XPCShell\\Extensions", - "addon1@tests.mozilla.org", addon1Dir.path); - registry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, - "SOFTWARE\\Mozilla\\XPCShell\\Extensions", - "addon2@tests.mozilla.org", addon2Dir.path); + MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE, + "SOFTWARE\\Mozilla\\XPCShell\\Extensions", + "addon1@tests.mozilla.org", addon1Dir.path); + MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, + "SOFTWARE\\Mozilla\\XPCShell\\Extensions", + "addon2@tests.mozilla.org", addon2Dir.path); startupManager(); @@ -81,12 +74,12 @@ function run_test_1() { // Tests whether uninstalling from the registry works function run_test_2() { - registry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE, - "SOFTWARE\\Mozilla\\XPCShell\\Extensions", - "addon1@tests.mozilla.org", null); - registry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, - "SOFTWARE\\Mozilla\\XPCShell\\Extensions", - "addon2@tests.mozilla.org", null); + MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE, + "SOFTWARE\\Mozilla\\XPCShell\\Extensions", + "addon1@tests.mozilla.org", null); + MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, + "SOFTWARE\\Mozilla\\XPCShell\\Extensions", + "addon2@tests.mozilla.org", null); restartManager(); @@ -101,12 +94,12 @@ function run_test_2() { // Checks that the ID in the registry must match that in the install manifest function run_test_3() { - registry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE, - "SOFTWARE\\Mozilla\\XPCShell\\Extensions", - "addon1@tests.mozilla.org", addon2Dir.path); - registry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, - "SOFTWARE\\Mozilla\\XPCShell\\Extensions", - "addon2@tests.mozilla.org", addon1Dir.path); + MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE, + "SOFTWARE\\Mozilla\\XPCShell\\Extensions", + "addon1@tests.mozilla.org", addon2Dir.path); + MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, + "SOFTWARE\\Mozilla\\XPCShell\\Extensions", + "addon2@tests.mozilla.org", addon1Dir.path); restartManager(); @@ -124,26 +117,26 @@ function run_test_4() { // Restarting with bad items in the registry should not force an EM restart restartManager(); - registry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE, - "SOFTWARE\\Mozilla\\XPCShell\\Extensions", - "addon1@tests.mozilla.org", null); - registry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, - "SOFTWARE\\Mozilla\\XPCShell\\Extensions", - "addon2@tests.mozilla.org", null); + MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE, + "SOFTWARE\\Mozilla\\XPCShell\\Extensions", + "addon1@tests.mozilla.org", null); + MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, + "SOFTWARE\\Mozilla\\XPCShell\\Extensions", + "addon2@tests.mozilla.org", null); restartManager(); - registry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE, - "SOFTWARE\\Mozilla\\XPCShell\\Extensions", - "addon1@tests.mozilla.org", addon1Dir.path); + MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE, + "SOFTWARE\\Mozilla\\XPCShell\\Extensions", + "addon1@tests.mozilla.org", addon1Dir.path); restartManager(); - registry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE, - "SOFTWARE\\Mozilla\\XPCShell\\Extensions", - "addon1@tests.mozilla.org", null); - registry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, - "SOFTWARE\\Mozilla\\XPCShell\\Extensions", - "addon2@tests.mozilla.org", addon1Dir.path); + MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE, + "SOFTWARE\\Mozilla\\XPCShell\\Extensions", + "addon1@tests.mozilla.org", null); + MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, + "SOFTWARE\\Mozilla\\XPCShell\\Extensions", + "addon2@tests.mozilla.org", addon1Dir.path); writeInstallRDFForExtension(addon2, gProfD, "addon1"); restartManager(); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_reload.js b/toolkit/mozapps/extensions/test/xpcshell/test_reload.js deleted file mode 100644 index 5873d1980..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_reload.js +++ /dev/null @@ -1,235 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "42"); - -const sampleAddon = { - id: "webextension1@tests.mozilla.org", - name: "webextension_1", -} - -const manifestSample = { - id: "bootstrap1@tests.mozilla.org", - version: "1.0", - bootstrap: true, - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "1", - maxVersion: "1" - }], -}; - -const { Management } = Components.utils.import("resource://gre/modules/Extension.jsm", {}); - -function promiseAddonStartup() { - return new Promise(resolve => { - let listener = (extension) => { - Management.off("startup", listener); - resolve(extension); - }; - - Management.on("startup", listener); - }); -} - -function* installAddon(fixtureName, addonID) { - yield promiseInstallAllFiles([do_get_addon(fixtureName)]); - return promiseAddonByID(addonID); -} - -function* tearDownAddon(addon) { - addon.uninstall(); - yield promiseShutdownManager(); -} - -add_task(function* test_reloading_a_temp_addon() { - yield promiseRestartManager(); - yield AddonManager.installTemporaryAddon(do_get_addon(sampleAddon.name)); - const addon = yield promiseAddonByID(sampleAddon.id) - - var receivedOnUninstalled = false; - var receivedOnUninstalling = false; - var receivedOnInstalled = false; - var receivedOnInstalling = false; - - const onReload = new Promise(resolve => { - const listener = { - onUninstalling: (addonObj) => { - if (addonObj.id === sampleAddon.id) { - receivedOnUninstalling = true; - } - }, - onUninstalled: (addonObj) => { - if (addonObj.id === sampleAddon.id) { - receivedOnUninstalled = true; - } - }, - onInstalling: (addonObj) => { - receivedOnInstalling = true; - equal(addonObj.id, sampleAddon.id); - }, - onInstalled: (addonObj) => { - receivedOnInstalled = true; - equal(addonObj.id, sampleAddon.id); - // This should be the last event called. - AddonManager.removeAddonListener(listener); - resolve(); - }, - } - AddonManager.addAddonListener(listener); - }); - - yield addon.reload(); - yield onReload; - - // Make sure reload() doesn't trigger uninstall events. - equal(receivedOnUninstalled, false, "reload should not trigger onUninstalled"); - equal(receivedOnUninstalling, false, "reload should not trigger onUninstalling"); - - // Make sure reload() triggers install events, like an upgrade. - equal(receivedOnInstalling, true, "reload should trigger onInstalling"); - equal(receivedOnInstalled, true, "reload should trigger onInstalled"); - - yield tearDownAddon(addon); -}); - -add_task(function* test_can_reload_permanent_addon() { - yield promiseRestartManager(); - const addon = yield installAddon(sampleAddon.name, sampleAddon.id); - - let disabledCalled = false; - let enabledCalled = false; - AddonManager.addAddonListener({ - onDisabled: (aAddon) => { - do_check_false(enabledCalled); - disabledCalled = true - }, - onEnabled: (aAddon) => { - do_check_true(disabledCalled); - enabledCalled = true - } - }) - - yield addon.reload(); - - do_check_true(disabledCalled); - do_check_true(enabledCalled); - - notEqual(addon, null); - equal(addon.appDisabled, false); - equal(addon.userDisabled, false); - - yield tearDownAddon(addon); -}); - -add_task(function* test_reload_to_invalid_version_fails() { - yield promiseRestartManager(); - let tempdir = gTmpD.clone(); - - // The initial version of the add-on will be compatible, and will therefore load - const addonId = "invalid_version_cannot_be_reloaded@tests.mozilla.org"; - let manifest = { - name: "invalid_version_cannot_be_reloaded", - description: "test invalid_version_cannot_be_reloaded", - manifest_version: 2, - version: "1.0", - applications: { - gecko: { - id: addonId, - } - }, - }; - - let addonDir = yield promiseWriteWebManifestForExtension(manifest, tempdir, "invalid_version"); - yield AddonManager.installTemporaryAddon(addonDir); - yield promiseAddonStartup(); - - let addon = yield promiseAddonByID(addonId); - notEqual(addon, null); - equal(addon.id, addonId); - equal(addon.version, "1.0"); - equal(addon.appDisabled, false); - equal(addon.userDisabled, false); - addonDir.remove(true); - - // update the manifest to make the add-on version incompatible, so the reload will reject - manifest.applications.gecko.strict_min_version = "1"; - manifest.applications.gecko.strict_max_version = "1"; - manifest.version = "2.0"; - - addonDir = yield promiseWriteWebManifestForExtension(manifest, tempdir, "invalid_version", false); - let expectedMsg = new RegExp("Add-on invalid_version_cannot_be_reloaded@tests.mozilla.org is not compatible with application version. " + - "add-on minVersion: 1. add-on maxVersion: 1."); - - yield Assert.rejects(addon.reload(), - expectedMsg, - "Reload rejects when application version does not fall between minVersion and maxVersion"); - - let reloadedAddon = yield promiseAddonByID(addonId); - notEqual(reloadedAddon, null); - equal(reloadedAddon.id, addonId); - equal(reloadedAddon.version, "1.0"); - equal(reloadedAddon.appDisabled, false); - equal(reloadedAddon.userDisabled, false); - - yield tearDownAddon(reloadedAddon); - addonDir.remove(true); -}); - -add_task(function* test_manifest_changes_are_refreshed() { - yield promiseRestartManager(); - let tempdir = gTmpD.clone(); - - const unpackedAddon = writeInstallRDFToDir( - Object.assign({}, manifestSample, { - name: "Test Bootstrap 1", - }), tempdir, manifestSample.id, "bootstrap.js"); - - yield AddonManager.installTemporaryAddon(unpackedAddon); - const addon = yield promiseAddonByID(manifestSample.id); - notEqual(addon, null); - equal(addon.name, "Test Bootstrap 1"); - - writeInstallRDFToDir(Object.assign({}, manifestSample, { - name: "Test Bootstrap 1 (reloaded)", - }), tempdir, manifestSample.id); - - yield addon.reload(); - - const reloadedAddon = yield promiseAddonByID(manifestSample.id); - notEqual(reloadedAddon, null); - equal(reloadedAddon.name, "Test Bootstrap 1 (reloaded)"); - - yield tearDownAddon(reloadedAddon); - unpackedAddon.remove(true); -}); - -add_task(function* test_reload_fails_on_installation_errors() { - yield promiseRestartManager(); - let tempdir = gTmpD.clone(); - - const unpackedAddon = writeInstallRDFToDir( - Object.assign({}, manifestSample, { - name: "Test Bootstrap 1", - }), tempdir, manifestSample.id, "bootstrap.js"); - - yield AddonManager.installTemporaryAddon(unpackedAddon); - const addon = yield promiseAddonByID(manifestSample.id); - notEqual(addon, null); - - // Trigger an installation error with an empty manifest. - writeInstallRDFToDir({}, tempdir, manifestSample.id); - - yield Assert.rejects(addon.reload(), /No ID in install manifest/); - - // The old add-on should be active. I.E. the broken reload will not - // disturb it. - const oldAddon = yield promiseAddonByID(manifestSample.id); - notEqual(oldAddon, null); - equal(oldAddon.isActive, true); - equal(oldAddon.name, "Test Bootstrap 1"); - - yield tearDownAddon(addon); - unpackedAddon.remove(true); -}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_schema_change.js b/toolkit/mozapps/extensions/test/xpcshell/test_schema_change.js deleted file mode 100644 index 3d386f663..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_schema_change.js +++ /dev/null @@ -1,317 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -BootstrapMonitor.init(); - -const PREF_DB_SCHEMA = "extensions.databaseSchema"; - -const profileDir = gProfD.clone(); -profileDir.append("extensions"); - -createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "49"); -startupManager(); - -/** - * Schema change with no application update reloads metadata. - */ -add_task(function* schema_change() { - const ID = "schema-change@tests.mozilla.org"; - - let xpiFile = createTempXPIFile({ - id: ID, - name: "Test Add-on", - version: "1.0", - bootstrap: true, - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "1", - maxVersion: "1.9.2" - }] - }); - - yield promiseInstallAllFiles([xpiFile]); - - let addon = yield promiseAddonByID(ID); - - notEqual(addon, null, "Got an addon object as expected"); - equal(addon.version, "1.0", "Got the expected version"); - - yield shutdownManager(); - - xpiFile = createTempXPIFile({ - id: ID, - name: "Test Add-on 2", - version: "2.0", - bootstrap: true, - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "1", - maxVersion: "1.9.2" - }] - }); - - Services.prefs.setIntPref(PREF_DB_SCHEMA, 0); - - let file = profileDir.clone(); - file.append(`${ID}.xpi`); - - // Make sure the timestamp is unchanged, so it is not re-scanned for that reason. - let timestamp = file.lastModifiedTime; - xpiFile.moveTo(profileDir, `${ID}.xpi`); - - file.lastModifiedTime = timestamp; - - yield startupManager(); - - addon = yield promiseAddonByID(ID); - notEqual(addon, null, "Got an addon object as expected"); - equal(addon.version, "2.0", "Got the expected version"); - - let waitUninstall = promiseAddonEvent("onUninstalled"); - addon.uninstall(); - yield waitUninstall; -}); - -/** - * Application update with no schema change does not reload metadata. - */ -add_task(function* schema_change() { - const ID = "schema-change@tests.mozilla.org"; - - let xpiFile = createTempXPIFile({ - id: ID, - name: "Test Add-on", - version: "1.0", - bootstrap: true, - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "1", - maxVersion: "2" - }] - }); - - yield promiseInstallAllFiles([xpiFile]); - - let addon = yield promiseAddonByID(ID); - - notEqual(addon, null, "Got an addon object as expected"); - equal(addon.version, "1.0", "Got the expected version"); - - yield shutdownManager(); - - xpiFile = createTempXPIFile({ - id: ID, - name: "Test Add-on 2", - version: "2.0", - bootstrap: true, - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "1", - maxVersion: "2" - }] - }); - - gAppInfo.version = "2"; - let file = profileDir.clone(); - file.append(`${ID}.xpi`); - - // Make sure the timestamp is unchanged, so it is not re-scanned for that reason. - let timestamp = file.lastModifiedTime; - xpiFile.moveTo(profileDir, `${ID}.xpi`); - - file.lastModifiedTime = timestamp; - - yield startupManager(); - - addon = yield promiseAddonByID(ID); - notEqual(addon, null, "Got an addon object as expected"); - equal(addon.version, "1.0", "Got the expected version"); - - let waitUninstall = promiseAddonEvent("onUninstalled"); - addon.uninstall(); - yield waitUninstall; -}); - -/** - * App update and a schema change causes a reload of the manifest. - */ -add_task(function* schema_change_app_update() { - const ID = "schema-change@tests.mozilla.org"; - - let xpiFile = createTempXPIFile({ - id: ID, - name: "Test Add-on", - version: "1.0", - bootstrap: true, - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "1", - maxVersion: "3" - }] - }); - - yield promiseInstallAllFiles([xpiFile]); - - let addon = yield promiseAddonByID(ID); - - notEqual(addon, null, "Got an addon object as expected"); - equal(addon.version, "1.0", "Got the expected version"); - - yield shutdownManager(); - - xpiFile = createTempXPIFile({ - id: ID, - name: "Test Add-on 2", - version: "2.0", - bootstrap: true, - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "1", - maxVersion: "3" - }] - }); - - gAppInfo.version = "3"; - Services.prefs.setIntPref(PREF_DB_SCHEMA, 0); - - let file = profileDir.clone(); - file.append(`${ID}.xpi`); - - // Make sure the timestamp is unchanged, so it is not re-scanned for that reason. - let timestamp = file.lastModifiedTime; - xpiFile.moveTo(profileDir, `${ID}.xpi`); - - file.lastModifiedTime = timestamp; - - yield startupManager(); - - addon = yield promiseAddonByID(ID); - notEqual(addon, null, "Got an addon object as expected"); - equal(addon.appDisabled, false); - equal(addon.version, "2.0", "Got the expected version"); - - let waitUninstall = promiseAddonEvent("onUninstalled"); - addon.uninstall(); - yield waitUninstall; -}); - -/** - * No schema change, no manifest reload. - */ -add_task(function* schema_change() { - const ID = "schema-change@tests.mozilla.org"; - - let xpiFile = createTempXPIFile({ - id: ID, - name: "Test Add-on", - version: "1.0", - bootstrap: true, - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "1", - maxVersion: "1.9.2" - }] - }); - - yield promiseInstallAllFiles([xpiFile]); - - let addon = yield promiseAddonByID(ID); - - notEqual(addon, null, "Got an addon object as expected"); - equal(addon.version, "1.0", "Got the expected version"); - - yield shutdownManager(); - - xpiFile = createTempXPIFile({ - id: ID, - name: "Test Add-on 2", - version: "2.0", - bootstrap: true, - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "1", - maxVersion: "1.9.2" - }] - }); - - let file = profileDir.clone(); - file.append(`${ID}.xpi`); - - // Make sure the timestamp is unchanged, so it is not re-scanned for that reason. - let timestamp = file.lastModifiedTime; - xpiFile.moveTo(profileDir, `${ID}.xpi`); - - file.lastModifiedTime = timestamp; - - yield startupManager(); - - addon = yield promiseAddonByID(ID); - notEqual(addon, null, "Got an addon object as expected"); - equal(addon.version, "1.0", "Got the expected version"); - - let waitUninstall = promiseAddonEvent("onUninstalled"); - addon.uninstall(); - yield waitUninstall; -}); - -/** - * Modified timestamp on the XPI causes a reload of the manifest. - */ -add_task(function* schema_change() { - const ID = "schema-change@tests.mozilla.org"; - - let xpiFile = createTempXPIFile({ - id: ID, - name: "Test Add-on", - version: "1.0", - bootstrap: true, - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "1", - maxVersion: "1.9.2" - }] - }); - - yield promiseInstallAllFiles([xpiFile]); - - let addon = yield promiseAddonByID(ID); - - notEqual(addon, null, "Got an addon object as expected"); - equal(addon.version, "1.0", "Got the expected version"); - - yield shutdownManager(); - - xpiFile = createTempXPIFile({ - id: ID, - name: "Test Add-on 2", - version: "2.0", - bootstrap: true, - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "1", - maxVersion: "1.9.2" - }] - }); - - xpiFile.moveTo(profileDir, `${ID}.xpi`); - - let file = profileDir.clone(); - file.append(`${ID}.xpi`); - - // Set timestamp in the future so manifest is re-scanned. - let timestamp = new Date(Date.now() + 60000); - xpiFile.moveTo(profileDir, `${ID}.xpi`); - - file.lastModifiedTime = timestamp; - - yield startupManager(); - - addon = yield promiseAddonByID(ID); - notEqual(addon, null, "Got an addon object as expected"); - equal(addon.version, "2.0", "Got the expected version"); - - let waitUninstall = promiseAddonEvent("onUninstalled"); - addon.uninstall(); - yield waitUninstall; -}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_seen.js b/toolkit/mozapps/extensions/test/xpcshell/test_seen.js deleted file mode 100644 index e499e7339..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_seen.js +++ /dev/null @@ -1,211 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -const ID = "bootstrap1@tests.mozilla.org"; - -let profileDir = gProfD.clone(); -profileDir.append("extensions"); - -createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); -startupManager(); - -// By default disable add-ons from the profile -Services.prefs.setIntPref("extensions.autoDisableScopes", AddonManager.SCOPE_PROFILE); - -// Installing an add-on through the API should mark it as seen -add_task(function*() { - let install = yield new Promise(resolve => AddonManager.getInstallForFile(do_get_addon("test_bootstrap1_1"), resolve)); - yield promiseCompleteAllInstalls([install]); - do_check_eq(install.state, AddonManager.STATE_INSTALLED); - do_check_false(hasFlag(install.addon.pendingOperations, AddonManager.PENDING_INSTALL)); - - let addon = install.addon; - do_check_eq(addon.version, "1.0"); - do_check_false(addon.foreignInstall); - do_check_true(addon.seen); - - yield promiseRestartManager(); - - addon = yield promiseAddonByID(ID); - do_check_false(addon.foreignInstall); - do_check_true(addon.seen); - - // Installing an update should retain that - install = yield new Promise(resolve => AddonManager.getInstallForFile(do_get_addon("test_bootstrap1_2"), resolve)); - yield promiseCompleteAllInstalls([install]); - do_check_eq(install.state, AddonManager.STATE_INSTALLED); - do_check_false(hasFlag(install.addon.pendingOperations, AddonManager.PENDING_INSTALL)); - - addon = install.addon; - do_check_eq(addon.version, "2.0"); - do_check_false(addon.foreignInstall); - do_check_true(addon.seen); - - yield promiseRestartManager(); - - addon = yield promiseAddonByID(ID); - do_check_false(addon.foreignInstall); - do_check_true(addon.seen); - - addon.uninstall(); - yield promiseShutdownManager(); -}); - -// Sideloading an add-on should mark it as unseen -add_task(function*() { - let path = manuallyInstall(do_get_addon("test_bootstrap1_1"), profileDir, ID); - // Make sure the startup code will detect sideloaded updates - setExtensionModifiedTime(path, Date.now() - 10000); - - startupManager(); - - let addon = yield promiseAddonByID(ID); - do_check_eq(addon.version, "1.0"); - do_check_true(addon.foreignInstall); - do_check_false(addon.seen); - - yield promiseRestartManager(); - - addon = yield promiseAddonByID(ID); - do_check_true(addon.foreignInstall); - do_check_false(addon.seen); - - yield promiseShutdownManager(); - - // Sideloading an update shouldn't change the state - manuallyUninstall(profileDir, ID); - manuallyInstall(do_get_addon("test_bootstrap1_2"), profileDir, ID); - setExtensionModifiedTime(path, Date.now()); - - startupManager(); - - addon = yield promiseAddonByID(ID); - do_check_eq(addon.version, "2.0"); - do_check_true(addon.foreignInstall); - do_check_false(addon.seen); - - addon.uninstall(); - yield promiseShutdownManager(); -}); - -// Sideloading an add-on should mark it as unseen -add_task(function*() { - let path = manuallyInstall(do_get_addon("test_bootstrap1_1"), profileDir, ID); - // Make sure the startup code will detect sideloaded updates - setExtensionModifiedTime(path, Date.now() - 10000); - - startupManager(); - - let addon = yield promiseAddonByID(ID); - do_check_eq(addon.version, "1.0"); - do_check_true(addon.foreignInstall); - do_check_false(addon.seen); - - yield promiseRestartManager(); - - addon = yield promiseAddonByID(ID); - do_check_true(addon.foreignInstall); - do_check_false(addon.seen); - - // Updating through the API shouldn't change the state - let install = yield new Promise(resolve => AddonManager.getInstallForFile(do_get_addon("test_bootstrap1_2"), resolve)); - yield promiseCompleteAllInstalls([install]); - do_check_eq(install.state, AddonManager.STATE_INSTALLED); - do_check_false(hasFlag(install.addon.pendingOperations, AddonManager.PENDING_INSTALL)); - - addon = install.addon; - do_check_true(addon.foreignInstall); - do_check_false(addon.seen); - - yield promiseRestartManager(); - - addon = yield promiseAddonByID(ID); - do_check_eq(addon.version, "2.0"); - do_check_true(addon.foreignInstall); - do_check_false(addon.seen); - - addon.uninstall(); - yield promiseShutdownManager(); -}); - -// Sideloading an add-on should mark it as unseen -add_task(function*() { - let path = manuallyInstall(do_get_addon("test_bootstrap1_1"), profileDir, ID); - // Make sure the startup code will detect sideloaded updates - setExtensionModifiedTime(path, Date.now() - 10000); - - startupManager(); - - let addon = yield promiseAddonByID(ID); - do_check_eq(addon.version, "1.0"); - do_check_true(addon.foreignInstall); - do_check_false(addon.seen); - addon.markAsSeen(); - do_check_true(addon.seen); - - yield promiseRestartManager(); - - addon = yield promiseAddonByID(ID); - do_check_true(addon.foreignInstall); - do_check_true(addon.seen); - - yield promiseShutdownManager(); - - // Sideloading an update shouldn't change the state - manuallyUninstall(profileDir, ID); - manuallyInstall(do_get_addon("test_bootstrap1_2"), profileDir, ID); - setExtensionModifiedTime(path, Date.now()); - - startupManager(); - - addon = yield promiseAddonByID(ID); - do_check_eq(addon.version, "2.0"); - do_check_true(addon.foreignInstall); - do_check_true(addon.seen); - - addon.uninstall(); - yield promiseShutdownManager(); -}); - -// Sideloading an add-on should mark it as unseen -add_task(function*() { - let path = manuallyInstall(do_get_addon("test_bootstrap1_1"), profileDir, ID); - // Make sure the startup code will detect sideloaded updates - setExtensionModifiedTime(path, Date.now() - 10000); - - startupManager(); - - let addon = yield promiseAddonByID(ID); - do_check_eq(addon.version, "1.0"); - do_check_true(addon.foreignInstall); - do_check_false(addon.seen); - addon.markAsSeen(); - do_check_true(addon.seen); - - yield promiseRestartManager(); - - addon = yield promiseAddonByID(ID); - do_check_true(addon.foreignInstall); - do_check_true(addon.seen); - - // Updating through the API shouldn't change the state - let install = yield new Promise(resolve => AddonManager.getInstallForFile(do_get_addon("test_bootstrap1_2"), resolve)); - yield promiseCompleteAllInstalls([install]); - do_check_eq(install.state, AddonManager.STATE_INSTALLED); - do_check_false(hasFlag(install.addon.pendingOperations, AddonManager.PENDING_INSTALL)); - - addon = install.addon; - do_check_true(addon.foreignInstall); - do_check_true(addon.seen); - - yield promiseRestartManager(); - - addon = yield promiseAddonByID(ID); - do_check_eq(addon.version, "2.0"); - do_check_true(addon.foreignInstall); - do_check_true(addon.seen); - - addon.uninstall(); - yield promiseShutdownManager(); -}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_seen_newprofile.js b/toolkit/mozapps/extensions/test/xpcshell/test_seen_newprofile.js deleted file mode 100644 index 43ee18594..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_seen_newprofile.js +++ /dev/null @@ -1,41 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -const ID = "bootstrap1@tests.mozilla.org"; - -Services.prefs.setIntPref("extensions.enabledScopes", - AddonManager.SCOPE_PROFILE + AddonManager.SCOPE_SYSTEM); - -createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); - -BootstrapMonitor.init(); - -const globalDir = gProfD.clone(); -globalDir.append("extensions2"); -globalDir.append(gAppInfo.ID); -registerDirectory("XRESysSExtPD", globalDir.parent); -const profileDir = gProfD.clone(); -profileDir.append("extensions"); - -// By default disable add-ons from the system -Services.prefs.setIntPref("extensions.autoDisableScopes", AddonManager.SCOPE_SYSTEM); - -// When new add-ons already exist in a system location when starting with a new -// profile they should be marked as already seen. -add_task(function*() { - manuallyInstall(do_get_addon("test_bootstrap1_1"), globalDir, ID); - - startupManager(); - - let addon = yield promiseAddonByID(ID); - do_check_true(addon.foreignInstall); - do_check_true(addon.seen); - do_check_true(addon.userDisabled); - do_check_false(addon.isActive); - - BootstrapMonitor.checkAddonInstalled(ID); - BootstrapMonitor.checkAddonNotStarted(ID); - - yield promiseShutdownManager(); -}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_shutdown.js b/toolkit/mozapps/extensions/test/xpcshell/test_shutdown.js index 725887bc1..a865824f0 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_shutdown.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_shutdown.js @@ -4,15 +4,12 @@ // Verify that API functions fail if the Add-ons Manager isn't initialised. -const IGNORE = ["getPreferredIconURL", "escapeAddonURI", - "shouldAutoUpdate", "getStartupChanges", +const IGNORE = ["escapeAddonURI", "shouldAutoUpdate", "getStartupChanges", "addTypeListener", "removeTypeListener", "addAddonListener", "removeAddonListener", "addInstallListener", "removeInstallListener", "addManagerListener", "removeManagerListener", - "mapURIToAddonID", "shutdown", "init", - "stateToString", "errorToString", "getUpgradeListener", - "addUpgradeListener", "removeUpgradeListener"]; + "mapURIToAddonID", "shutdown"]; const IGNORE_PRIVATE = ["AddonAuthor", "AddonCompatibilityOverride", "AddonScreenshot", "AddonType", "startup", "shutdown", @@ -21,8 +18,7 @@ const IGNORE_PRIVATE = ["AddonAuthor", "AddonCompatibilityOverride", "recordTimestamp", "recordSimpleMeasure", "recordException", "getSimpleMeasures", "simpleTimer", "setTelemetryDetails", "getTelemetryDetails", - "callNoUpdateListeners", "backgroundUpdateTimerHandler", - "hasUpgradeListener", "getUpgradeListener"]; + "callNoUpdateListeners", "backgroundUpdateTimerHandler"]; function test_functions() { for (let prop in AddonManager) { @@ -31,25 +27,9 @@ function test_functions() { if (typeof AddonManager[prop] != "function") continue; - let args = []; - - // Getter functions need a callback and in some cases not having one will - // throw before checking if the add-ons manager is initialized so pass in - // an empty one. - if (prop.startsWith("get")) { - // For now all getter functions with more than one argument take the - // callback in the second argument. - if (AddonManager[prop].length > 1) { - args.push(undefined, () => {}); - } - else { - args.push(() => {}); - } - } - try { do_print("AddonManager." + prop); - AddonManager[prop](...args); + AddonManager[prop](); do_throw(prop + " did not throw an exception"); } catch (e) { diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_signed_inject.js b/toolkit/mozapps/extensions/test/xpcshell/test_signed_inject.js deleted file mode 100644 index 3b96f40ba..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_signed_inject.js +++ /dev/null @@ -1,382 +0,0 @@ -// Enable signature checks for these tests -gUseRealCertChecks = true; -// Disable update security -Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false); - -const DATA = "data/signing_checks/"; -const ADDONS = { - bootstrap: { - unsigned: "unsigned_bootstrap_2.xpi", - badid: "signed_bootstrap_badid_2.xpi", - signed: "signed_bootstrap_2.xpi", - preliminary: "preliminary_bootstrap_2.xpi", - }, - nonbootstrap: { - unsigned: "unsigned_nonbootstrap_2.xpi", - badid: "signed_nonbootstrap_badid_2.xpi", - signed: "signed_nonbootstrap_2.xpi", - } -}; -const ID = "test@tests.mozilla.org"; - -const profileDir = gProfD.clone(); -profileDir.append("extensions"); - -// Deletes a file from the test add-on in the profile -function breakAddon(file) { - if (TEST_UNPACKED) { - file.append("test.txt"); - file.remove(true); - } - else { - var zipW = AM_Cc["@mozilla.org/zipwriter;1"]. - createInstance(AM_Ci.nsIZipWriter); - zipW.open(file, FileUtils.MODE_RDWR | FileUtils.MODE_APPEND); - zipW.removeEntry("test.txt", false); - zipW.close(); - } -} - -function resetPrefs() { - Services.prefs.setIntPref("bootstraptest.active_version", -1); - Services.prefs.setIntPref("bootstraptest.installed_version", -1); - Services.prefs.setIntPref("bootstraptest.startup_reason", -1); - Services.prefs.setIntPref("bootstraptest.shutdown_reason", -1); - Services.prefs.setIntPref("bootstraptest.install_reason", -1); - Services.prefs.setIntPref("bootstraptest.uninstall_reason", -1); - Services.prefs.setIntPref("bootstraptest.startup_oldversion", -1); - Services.prefs.setIntPref("bootstraptest.shutdown_newversion", -1); - Services.prefs.setIntPref("bootstraptest.install_oldversion", -1); - Services.prefs.setIntPref("bootstraptest.uninstall_newversion", -1); -} - -function clearCache(file) { - if (TEST_UNPACKED) - return; - - Services.obs.notifyObservers(file, "flush-cache-entry", null); -} - -function getActiveVersion() { - return Services.prefs.getIntPref("bootstraptest.active_version"); -} - -function run_test() { - createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "4", "4"); - - // Start and stop the manager to initialise everything in the profile before - // actual testing - startupManager(); - shutdownManager(); - resetPrefs(); - - run_next_test(); -} - -// Injecting into profile (bootstrap) -add_task(function*() { - let file = manuallyInstall(do_get_file(DATA + ADDONS.bootstrap.unsigned), profileDir, ID); - - startupManager(); - - // Currently we leave the sideloaded add-on there but just don't run it - let addon = yield promiseAddonByID(ID); - do_check_neq(addon, null); - do_check_true(addon.appDisabled); - do_check_false(addon.isActive); - do_check_eq(addon.signedState, AddonManager.SIGNEDSTATE_MISSING); - do_check_eq(getActiveVersion(), -1); - - addon.uninstall(); - yield promiseShutdownManager(); - resetPrefs(); - - do_check_false(file.exists()); - clearCache(file); -}); - -add_task(function*() { - let file = manuallyInstall(do_get_file(DATA + ADDONS.bootstrap.signed), profileDir, ID); - breakAddon(file); - - startupManager(); - - // Currently we leave the sideloaded add-on there but just don't run it - let addon = yield promiseAddonByID(ID); - do_check_neq(addon, null); - do_check_true(addon.appDisabled); - do_check_false(addon.isActive); - do_check_eq(addon.signedState, AddonManager.SIGNEDSTATE_BROKEN); - do_check_eq(getActiveVersion(), -1); - - addon.uninstall(); - yield promiseShutdownManager(); - resetPrefs(); - - do_check_false(file.exists()); - clearCache(file); -}); - -add_task(function*() { - let file = manuallyInstall(do_get_file(DATA + ADDONS.bootstrap.badid), profileDir, ID); - - startupManager(); - - // Currently we leave the sideloaded add-on there but just don't run it - let addon = yield promiseAddonByID(ID); - do_check_neq(addon, null); - do_check_true(addon.appDisabled); - do_check_false(addon.isActive); - do_check_eq(addon.signedState, AddonManager.SIGNEDSTATE_BROKEN); - do_check_eq(getActiveVersion(), -1); - - addon.uninstall(); - yield promiseShutdownManager(); - resetPrefs(); - - do_check_false(file.exists()); - clearCache(file); -}); - -// Installs a signed add-on then modifies it in place breaking its signing -add_task(function*() { - let file = manuallyInstall(do_get_file(DATA + ADDONS.bootstrap.signed), profileDir, ID); - - // Make it appear to come from the past so when we modify it later it is - // detected during startup. Obviously malware can bypass this method of - // detection but the periodic scan will catch that - yield promiseSetExtensionModifiedTime(file.path, Date.now() - 600000); - - startupManager(); - let addon = yield promiseAddonByID(ID); - do_check_neq(addon, null); - do_check_false(addon.appDisabled); - do_check_true(addon.isActive); - do_check_eq(addon.signedState, AddonManager.SIGNEDSTATE_SIGNED); - do_check_eq(getActiveVersion(), 2); - - yield promiseShutdownManager(); - do_check_eq(getActiveVersion(), 0); - - clearCache(file); - breakAddon(file); - resetPrefs(); - - startupManager(); - - addon = yield promiseAddonByID(ID); - do_check_neq(addon, null); - do_check_true(addon.appDisabled); - do_check_false(addon.isActive); - do_check_eq(addon.signedState, AddonManager.SIGNEDSTATE_BROKEN); - do_check_eq(getActiveVersion(), -1); - - let ids = AddonManager.getStartupChanges(AddonManager.STARTUP_CHANGE_DISABLED); - do_check_eq(ids.length, 1); - do_check_eq(ids[0], ID); - - addon.uninstall(); - yield promiseShutdownManager(); - resetPrefs(); - - do_check_false(file.exists()); - clearCache(file); -}); - -// Injecting into profile (non-bootstrap) -add_task(function*() { - let file = manuallyInstall(do_get_file(DATA + ADDONS.nonbootstrap.unsigned), profileDir, ID); - - startupManager(); - - // Currently we leave the sideloaded add-on there but just don't run it - let addon = yield promiseAddonByID(ID); - do_check_neq(addon, null); - do_check_true(addon.appDisabled); - do_check_false(addon.isActive); - do_check_eq(addon.signedState, AddonManager.SIGNEDSTATE_MISSING); - do_check_false(isExtensionInAddonsList(profileDir, ID)); - - addon.uninstall(); - yield promiseRestartManager(); - yield promiseShutdownManager(); - - do_check_false(file.exists()); - clearCache(file); -}); - -add_task(function*() { - let file = manuallyInstall(do_get_file(DATA + ADDONS.nonbootstrap.signed), profileDir, ID); - breakAddon(file); - - startupManager(); - - // Currently we leave the sideloaded add-on there but just don't run it - let addon = yield promiseAddonByID(ID); - do_check_neq(addon, null); - do_check_true(addon.appDisabled); - do_check_false(addon.isActive); - do_check_eq(addon.signedState, AddonManager.SIGNEDSTATE_BROKEN); - do_check_false(isExtensionInAddonsList(profileDir, ID)); - - addon.uninstall(); - yield promiseRestartManager(); - yield promiseShutdownManager(); - - do_check_false(file.exists()); - clearCache(file); -}); - -add_task(function*() { - let file = manuallyInstall(do_get_file(DATA + ADDONS.nonbootstrap.badid), profileDir, ID); - - startupManager(); - - // Currently we leave the sideloaded add-on there but just don't run it - let addon = yield promiseAddonByID(ID); - do_check_neq(addon, null); - do_check_true(addon.appDisabled); - do_check_false(addon.isActive); - do_check_eq(addon.signedState, AddonManager.SIGNEDSTATE_BROKEN); - do_check_false(isExtensionInAddonsList(profileDir, ID)); - - addon.uninstall(); - yield promiseRestartManager(); - yield promiseShutdownManager(); - - do_check_false(file.exists()); - clearCache(file); -}); - -// Installs a signed add-on then modifies it in place breaking its signing -add_task(function*() { - let file = manuallyInstall(do_get_file(DATA + ADDONS.nonbootstrap.signed), profileDir, ID); - - // Make it appear to come from the past so when we modify it later it is - // detected during startup. Obviously malware can bypass this method of - // detection but the periodic scan will catch that - yield promiseSetExtensionModifiedTime(file.path, Date.now() - 60000); - - startupManager(); - let addon = yield promiseAddonByID(ID); - do_check_neq(addon, null); - do_check_false(addon.appDisabled); - do_check_true(addon.isActive); - do_check_eq(addon.signedState, AddonManager.SIGNEDSTATE_SIGNED); - do_check_true(isExtensionInAddonsList(profileDir, ID)); - - yield promiseShutdownManager(); - - clearCache(file); - breakAddon(file); - - startupManager(); - - addon = yield promiseAddonByID(ID); - do_check_neq(addon, null); - do_check_true(addon.appDisabled); - do_check_false(addon.isActive); - do_check_eq(addon.signedState, AddonManager.SIGNEDSTATE_BROKEN); - do_check_false(isExtensionInAddonsList(profileDir, ID)); - - let ids = AddonManager.getStartupChanges(AddonManager.STARTUP_CHANGE_DISABLED); - do_check_eq(ids.length, 1); - do_check_eq(ids[0], ID); - - addon.uninstall(); - yield promiseRestartManager(); - yield promiseShutdownManager(); - - do_check_false(file.exists()); - clearCache(file); -}); - -// Stage install then modify before startup (non-bootstrap) -add_task(function*() { - startupManager(); - yield promiseInstallAllFiles([do_get_file(DATA + ADDONS.nonbootstrap.signed)]); - yield promiseShutdownManager(); - - let staged = profileDir.clone(); - staged.append("staged"); - staged.append(do_get_expected_addon_name(ID)); - do_check_true(staged.exists()); - - breakAddon(staged); - startupManager(); - - // Should have refused to install the broken staged version - let addon = yield promiseAddonByID(ID); - do_check_eq(addon, null); - - clearCache(staged); - - yield promiseShutdownManager(); -}); - -// Manufacture staged install (bootstrap) -add_task(function*() { - let stage = profileDir.clone(); - stage.append("staged"); - - let file = manuallyInstall(do_get_file(DATA + ADDONS.bootstrap.signed), stage, ID); - breakAddon(file); - - startupManager(); - - // Should have refused to install the broken staged version - let addon = yield promiseAddonByID(ID); - do_check_eq(addon, null); - do_check_eq(getActiveVersion(), -1); - - do_check_false(file.exists()); - clearCache(file); - - yield promiseShutdownManager(); - resetPrefs(); -}); - -// Preliminarily-signed sideloaded add-ons should work -add_task(function*() { - let file = manuallyInstall(do_get_file(DATA + ADDONS.bootstrap.preliminary), profileDir, ID); - - startupManager(); - - let addon = yield promiseAddonByID(ID); - do_check_neq(addon, null); - do_check_false(addon.appDisabled); - do_check_true(addon.isActive); - do_check_eq(addon.signedState, AddonManager.SIGNEDSTATE_PRELIMINARY); - do_check_eq(getActiveVersion(), 2); - - addon.uninstall(); - yield promiseShutdownManager(); - resetPrefs(); - - do_check_false(file.exists()); - clearCache(file); -}); - -// Preliminarily-signed sideloaded add-ons should work via staged install -add_task(function*() { - let stage = profileDir.clone(); - stage.append("staged"); - - let file = manuallyInstall(do_get_file(DATA + ADDONS.bootstrap.preliminary), stage, ID); - - startupManager(); - - let addon = yield promiseAddonByID(ID); - do_check_neq(addon, null); - do_check_false(addon.appDisabled); - do_check_true(addon.isActive); - do_check_eq(addon.signedState, AddonManager.SIGNEDSTATE_PRELIMINARY); - do_check_eq(getActiveVersion(), 2); - - addon.uninstall(); - yield promiseShutdownManager(); - resetPrefs(); - - do_check_false(file.exists()); - clearCache(file); -}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_signed_install.js b/toolkit/mozapps/extensions/test/xpcshell/test_signed_install.js deleted file mode 100644 index 19b07ac16..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_signed_install.js +++ /dev/null @@ -1,265 +0,0 @@ -// Enable signature checks for these tests -gUseRealCertChecks = true; -// Disable update security -Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false); - -const DATA = "data/signing_checks/"; -const ADDONS = { - bootstrap: { - unsigned: "unsigned_bootstrap_2.xpi", - badid: "signed_bootstrap_badid_2.xpi", - preliminary: "preliminary_bootstrap_2.xpi", - signed: "signed_bootstrap_2.xpi", - }, -}; -const WORKING = "signed_bootstrap_1.xpi"; -const ID = "test@tests.mozilla.org"; - -var gServer = createHttpServer(4444); - -// Creates an add-on with a broken signature by changing an existing file -function createBrokenAddonModify(file) { - let brokenFile = gTmpD.clone(); - brokenFile.append("broken.xpi"); - file.copyTo(brokenFile.parent, brokenFile.leafName); - - var stream = AM_Cc["@mozilla.org/io/string-input-stream;1"]. - createInstance(AM_Ci.nsIStringInputStream); - stream.setData("FOOBAR", -1); - var zipW = AM_Cc["@mozilla.org/zipwriter;1"]. - createInstance(AM_Ci.nsIZipWriter); - zipW.open(brokenFile, FileUtils.MODE_RDWR | FileUtils.MODE_APPEND); - zipW.removeEntry("test.txt", false); - zipW.addEntryStream("test.txt", 0, AM_Ci.nsIZipWriter.COMPRESSION_NONE, - stream, false); - zipW.close(); - - return brokenFile; -} - -// Creates an add-on with a broken signature by adding a new file -function createBrokenAddonAdd(file) { - let brokenFile = gTmpD.clone(); - brokenFile.append("broken.xpi"); - file.copyTo(brokenFile.parent, brokenFile.leafName); - - var stream = AM_Cc["@mozilla.org/io/string-input-stream;1"]. - createInstance(AM_Ci.nsIStringInputStream); - stream.setData("FOOBAR", -1); - var zipW = AM_Cc["@mozilla.org/zipwriter;1"]. - createInstance(AM_Ci.nsIZipWriter); - zipW.open(brokenFile, FileUtils.MODE_RDWR | FileUtils.MODE_APPEND); - zipW.addEntryStream("test2.txt", 0, AM_Ci.nsIZipWriter.COMPRESSION_NONE, - stream, false); - zipW.close(); - - return brokenFile; -} - -// Creates an add-on with a broken signature by removing an existing file -function createBrokenAddonRemove(file) { - let brokenFile = gTmpD.clone(); - brokenFile.append("broken.xpi"); - file.copyTo(brokenFile.parent, brokenFile.leafName); - - var stream = AM_Cc["@mozilla.org/io/string-input-stream;1"]. - createInstance(AM_Ci.nsIStringInputStream); - stream.setData("FOOBAR", -1); - var zipW = AM_Cc["@mozilla.org/zipwriter;1"]. - createInstance(AM_Ci.nsIZipWriter); - zipW.open(brokenFile, FileUtils.MODE_RDWR | FileUtils.MODE_APPEND); - zipW.removeEntry("test.txt", false); - zipW.close(); - - return brokenFile; -} - -function createInstall(url) { - return new Promise(resolve => { - AddonManager.getInstallForURL(url, resolve, "application/x-xpinstall"); - }); -} - -function serveUpdateRDF(leafName) { - gServer.registerPathHandler("/update.rdf", function(request, response) { - let updateData = {}; - updateData[ID] = [{ - version: "2.0", - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "4", - maxVersion: "6", - updateLink: "http://localhost:4444/" + leafName - }] - }]; - - response.setStatusLine(request.httpVersion, 200, "OK"); - response.write(createUpdateRDF(updateData)); - }); -} - - -function* test_install_broken(file, expectedError) { - gServer.registerFile("/" + file.leafName, file); - - let install = yield createInstall("http://localhost:4444/" + file.leafName); - yield promiseCompleteAllInstalls([install]); - - do_check_eq(install.state, AddonManager.STATE_DOWNLOAD_FAILED); - do_check_eq(install.error, expectedError); - do_check_eq(install.addon, null); - - gServer.registerFile("/" + file.leafName, null); -} - -function* test_install_working(file, expectedSignedState) { - gServer.registerFile("/" + file.leafName, file); - - let install = yield createInstall("http://localhost:4444/" + file.leafName); - yield promiseCompleteAllInstalls([install]); - - do_check_eq(install.state, AddonManager.STATE_INSTALLED); - do_check_neq(install.addon, null); - do_check_eq(install.addon.signedState, expectedSignedState); - - gServer.registerFile("/" + file.leafName, null); - - install.addon.uninstall(); -} - -function* test_update_broken(file, expectedError) { - // First install the older version - yield promiseInstallAllFiles([do_get_file(DATA + WORKING)]); - - gServer.registerFile("/" + file.leafName, file); - serveUpdateRDF(file.leafName); - - let addon = yield promiseAddonByID(ID); - let update = yield promiseFindAddonUpdates(addon); - let install = update.updateAvailable; - yield promiseCompleteAllInstalls([install]); - - do_check_eq(install.state, AddonManager.STATE_DOWNLOAD_FAILED); - do_check_eq(install.error, expectedError); - do_check_eq(install.addon, null); - - gServer.registerFile("/" + file.leafName, null); - gServer.registerPathHandler("/update.rdf", null); - - addon.uninstall(); -} - -function* test_update_working(file, expectedSignedState) { - // First install the older version - yield promiseInstallAllFiles([do_get_file(DATA + WORKING)]); - - gServer.registerFile("/" + file.leafName, file); - serveUpdateRDF(file.leafName); - - let addon = yield promiseAddonByID(ID); - let update = yield promiseFindAddonUpdates(addon); - let install = update.updateAvailable; - yield promiseCompleteAllInstalls([install]); - - do_check_eq(install.state, AddonManager.STATE_INSTALLED); - do_check_neq(install.addon, null); - do_check_eq(install.addon.signedState, expectedSignedState); - - gServer.registerFile("/" + file.leafName, null); - gServer.registerPathHandler("/update.rdf", null); - - install.addon.uninstall(); -} - -function run_test() { - createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "4", "4"); - startupManager(); - - run_next_test(); -} - -// Try to install a broken add-on -add_task(function*() { - let file = createBrokenAddonModify(do_get_file(DATA + ADDONS.bootstrap.signed)); - yield test_install_broken(file, AddonManager.ERROR_CORRUPT_FILE); - file.remove(true); -}); - -add_task(function*() { - let file = createBrokenAddonAdd(do_get_file(DATA + ADDONS.bootstrap.signed)); - yield test_install_broken(file, AddonManager.ERROR_CORRUPT_FILE); - file.remove(true); -}); - -add_task(function*() { - let file = createBrokenAddonRemove(do_get_file(DATA + ADDONS.bootstrap.signed)); - yield test_install_broken(file, AddonManager.ERROR_CORRUPT_FILE); - file.remove(true); -}); - -// Try to install an add-on with an incorrect ID -add_task(function*() { - let file = do_get_file(DATA + ADDONS.bootstrap.badid); - yield test_install_broken(file, AddonManager.ERROR_CORRUPT_FILE); -}); - -// Try to install an unsigned add-on -add_task(function*() { - let file = do_get_file(DATA + ADDONS.bootstrap.unsigned); - yield test_install_broken(file, AddonManager.ERROR_SIGNEDSTATE_REQUIRED); -}); - -// Try to install a preliminarily reviewed add-on -add_task(function*() { - let file = do_get_file(DATA + ADDONS.bootstrap.preliminary); - yield test_install_working(file, AddonManager.SIGNEDSTATE_PRELIMINARY); -}); - -// Try to install a signed add-on -add_task(function*() { - let file = do_get_file(DATA + ADDONS.bootstrap.signed); - yield test_install_working(file, AddonManager.SIGNEDSTATE_SIGNED); -}); - -// Try to update to a broken add-on -add_task(function*() { - let file = createBrokenAddonModify(do_get_file(DATA + ADDONS.bootstrap.signed)); - yield test_update_broken(file, AddonManager.ERROR_CORRUPT_FILE); - file.remove(true); -}); - -add_task(function*() { - let file = createBrokenAddonAdd(do_get_file(DATA + ADDONS.bootstrap.signed)); - yield test_update_broken(file, AddonManager.ERROR_CORRUPT_FILE); - file.remove(true); -}); - -add_task(function*() { - let file = createBrokenAddonRemove(do_get_file(DATA + ADDONS.bootstrap.signed)); - yield test_update_broken(file, AddonManager.ERROR_CORRUPT_FILE); - file.remove(true); -}); - -// Try to update to an add-on with an incorrect ID -add_task(function*() { - let file = do_get_file(DATA + ADDONS.bootstrap.badid); - yield test_update_broken(file, AddonManager.ERROR_CORRUPT_FILE); -}); - -// Try to update to an unsigned add-on -add_task(function*() { - let file = do_get_file(DATA + ADDONS.bootstrap.unsigned); - yield test_update_broken(file, AddonManager.ERROR_SIGNEDSTATE_REQUIRED); -}); - -// Try to update to a preliminarily reviewed add-on -add_task(function*() { - let file = do_get_file(DATA + ADDONS.bootstrap.preliminary); - yield test_update_working(file, AddonManager.SIGNEDSTATE_PRELIMINARY); -}); - -// Try to update to a signed add-on -add_task(function*() { - let file = do_get_file(DATA + ADDONS.bootstrap.signed); - yield test_update_working(file, AddonManager.SIGNEDSTATE_SIGNED); -}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_signed_long.js b/toolkit/mozapps/extensions/test/xpcshell/test_signed_long.js deleted file mode 100644 index b74d7804a..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_signed_long.js +++ /dev/null @@ -1,49 +0,0 @@ -// Disable update security -Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false); - -gUseRealCertChecks = true; - -const DATA = "data/signing_checks/"; - -const ID_63 = "123456789012345678901234567890123456789012345@tests.mozilla.org" -const ID_64 = "1234567890123456789012345678901234567890123456@tests.mozilla.org" -const ID_65 = "12345678901234567890123456789012345678901234568@tests.mozilla.org" - -function run_test() { - createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1"); - startupManager(); - - run_next_test(); -} - -// Installs the cases that should be working -add_task(function* test_working() { - yield promiseInstallAllFiles([do_get_file(DATA + "long_63_plain.xpi"), - do_get_file(DATA + "long_64_plain.xpi"), - do_get_file(DATA + "long_65_hash.xpi")]); - - let addons = yield promiseAddonsByIDs([ID_63, ID_64, ID_65]); - - for (let addon of addons) { - do_check_neq(addon, null); - do_check_true(addon.signedState > AddonManager.SIGNEDSTATE_MISSING); - - addon.uninstall(); - } -}); - -// Checks the cases that should be broken -add_task(function* test_broken() { - function promiseInstallForFile(file) { - return new Promise(resolve => AddonManager.getInstallForFile(file, resolve)); - } - - let promises = [promiseInstallForFile(do_get_file(DATA + "long_63_hash.xpi")), - promiseInstallForFile(do_get_file(DATA + "long_64_hash.xpi"))]; - let installs = yield Promise.all(promises); - - for (let install of installs) { - do_check_eq(install.state, AddonManager.STATE_DOWNLOAD_FAILED); - do_check_eq(install.error, AddonManager.ERROR_CORRUPT_FILE); - } -}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_signed_migrate.js b/toolkit/mozapps/extensions/test/xpcshell/test_signed_migrate.js deleted file mode 100644 index 97e2ff79f..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_signed_migrate.js +++ /dev/null @@ -1,194 +0,0 @@ -// Enable signature checks for these tests -gUseRealCertChecks = true; -// Disable update security -Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false); -// Allow attempting to show the compatibility UI which should not happen -Services.prefs.setBoolPref("extensions.showMismatchUI", true); - -const DATA = "data/signing_checks/"; -const ADDONS = { - bootstrap: { - unsigned: "unsigned_bootstrap_2.xpi", - badid: "signed_bootstrap_badid_2.xpi", - signed: "signed_bootstrap_2.xpi", - }, - nonbootstrap: { - unsigned: "unsigned_nonbootstrap_2.xpi", - badid: "signed_nonbootstrap_badid_2.xpi", - signed: "signed_nonbootstrap_2.xpi", - } -}; -const ID = "test@tests.mozilla.org"; - -const profileDir = gProfD.clone(); -profileDir.append("extensions"); - -// Override the window watcher -var WindowWatcher = { - sawAddon: false, - - openWindow: function(parent, url, name, features, args) { - let ids = args.QueryInterface(AM_Ci.nsIVariant); - this.sawAddon = ids.indexOf(ID) >= 0; - }, - - QueryInterface: function(iid) { - if (iid.equals(AM_Ci.nsIWindowWatcher) - || iid.equals(AM_Ci.nsISupports)) - return this; - - throw Components.results.NS_ERROR_NO_INTERFACE; - } -} - -MockRegistrar.register("@mozilla.org/embedcomp/window-watcher;1", WindowWatcher); - -function resetPrefs() { - Services.prefs.setIntPref("bootstraptest.active_version", -1); - Services.prefs.setIntPref("bootstraptest.installed_version", -1); - Services.prefs.setIntPref("bootstraptest.startup_reason", -1); - Services.prefs.setIntPref("bootstraptest.shutdown_reason", -1); - Services.prefs.setIntPref("bootstraptest.install_reason", -1); - Services.prefs.setIntPref("bootstraptest.uninstall_reason", -1); - Services.prefs.setIntPref("bootstraptest.startup_oldversion", -1); - Services.prefs.setIntPref("bootstraptest.shutdown_newversion", -1); - Services.prefs.setIntPref("bootstraptest.install_oldversion", -1); - Services.prefs.setIntPref("bootstraptest.uninstall_newversion", -1); -} - -function getActiveVersion() { - return Services.prefs.getIntPref("bootstraptest.active_version"); -} - -function run_test() { - createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "4", "4"); - - // Start and stop the manager to initialise everything in the profile before - // actual testing - startupManager(); - shutdownManager(); - resetPrefs(); - - run_next_test(); -} - -// Removes the signedState field from add-ons in the json database to make it -// look like the database was written with an older version of the application -function stripDB() { - let jData = loadJSON(gExtensionsJSON); - jData.schemaVersion--; - - for (let addon of jData.addons) - delete addon.signedState; - - saveJSON(jData, gExtensionsJSON); -} - -function* test_breaking_migrate(addons, test, expectedSignedState) { - // Startup as the old version - gAppInfo.version = "4"; - startupManager(true); - - // Install the signed add-on - yield promiseInstallAllFiles([do_get_file(DATA + addons.signed)]); - // Restart to let non-restartless add-ons install fully - yield promiseRestartManager(); - yield promiseShutdownManager(); - resetPrefs(); - stripDB(); - - // Now replace it with the version to test. Doing this so quickly shouldn't - // trigger the file modification code to detect the change by itself. - manuallyUninstall(profileDir, ID); - manuallyInstall(do_get_file(DATA + addons[test]), profileDir, ID); - - // Update the application - gAppInfo.version = "5"; - startupManager(true); - - let addon = yield promiseAddonByID(ID); - do_check_neq(addon, null); - do_check_true(addon.appDisabled); - do_check_false(addon.isActive); - do_check_eq(addon.signedState, expectedSignedState); - - // Add-on shouldn't be active - if (addons == ADDONS.bootstrap) - do_check_eq(getActiveVersion(), -1); - else - do_check_false(isExtensionInAddonsList(profileDir, ID)); - - // Should have flagged the change during startup - let changes = AddonManager.getStartupChanges(AddonManager.STARTUP_CHANGE_DISABLED); - do_check_eq(changes.length, 1); - do_check_eq(changes[0], ID); - - // Shouldn't have checked for updates for the add-on - do_check_false(WindowWatcher.sawAddon); - WindowWatcher.sawAddon = false; - - addon.uninstall(); - // Restart to let non-restartless add-ons uninstall fully - yield promiseRestartManager(); - yield shutdownManager(); - resetPrefs(); -} - -function* test_working_migrate(addons, test, expectedSignedState) { - // Startup as the old version - gAppInfo.version = "4"; - startupManager(true); - - // Install the signed add-on - yield promiseInstallAllFiles([do_get_file(DATA + addons.signed)]); - // Restart to let non-restartless add-ons install fully - yield promiseRestartManager(); - yield promiseShutdownManager(); - resetPrefs(); - stripDB(); - - // Now replace it with the version to test. Doing this so quickly shouldn't - // trigger the file modification code to detect the change by itself. - manuallyUninstall(profileDir, ID); - manuallyInstall(do_get_file(DATA + addons[test]), profileDir, ID); - - // Update the application - gAppInfo.version = "5"; - startupManager(true); - - let addon = yield promiseAddonByID(ID); - do_check_neq(addon, null); - do_check_false(addon.appDisabled); - do_check_true(addon.isActive); - do_check_eq(addon.signedState, expectedSignedState); - - if (addons == ADDONS.bootstrap) - do_check_eq(getActiveVersion(), 2); - else - do_check_true(isExtensionInAddonsList(profileDir, ID)); - - // Shouldn't have checked for updates for the add-on - do_check_false(WindowWatcher.sawAddon); - WindowWatcher.sawAddon = false; - - addon.uninstall(); - // Restart to let non-restartless add-ons uninstall fully - yield promiseRestartManager(); - yield shutdownManager(); - resetPrefs(); -} - -add_task(function*() { - yield test_breaking_migrate(ADDONS.bootstrap, "unsigned", AddonManager.SIGNEDSTATE_MISSING); - yield test_breaking_migrate(ADDONS.nonbootstrap, "unsigned", AddonManager.SIGNEDSTATE_MISSING); -}); - -add_task(function*() { - yield test_breaking_migrate(ADDONS.bootstrap, "badid", AddonManager.SIGNEDSTATE_BROKEN); - yield test_breaking_migrate(ADDONS.nonbootstrap, "badid", AddonManager.SIGNEDSTATE_BROKEN); -}); - -add_task(function*() { - yield test_working_migrate(ADDONS.bootstrap, "signed", AddonManager.SIGNEDSTATE_SIGNED); - yield test_working_migrate(ADDONS.nonbootstrap, "signed", AddonManager.SIGNEDSTATE_SIGNED); -}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_signed_multi.js b/toolkit/mozapps/extensions/test/xpcshell/test_signed_multi.js deleted file mode 100644 index 01de29088..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_signed_multi.js +++ /dev/null @@ -1,55 +0,0 @@ -// Enable signature checks for these tests -gUseRealCertChecks = true; -// Disable update security -Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false); - -const DATA = "data/signing_checks/"; - -// Each multi-package XPI contains one valid theme and one other add-on that -// has the following error state: -const ADDONS = { - "multi_signed.xpi": 0, - "multi_badid.xpi": AddonManager.ERROR_CORRUPT_FILE, - "multi_broken.xpi": AddonManager.ERROR_CORRUPT_FILE, - "multi_unsigned.xpi": AddonManager.ERROR_SIGNEDSTATE_REQUIRED, -}; - -function createInstall(filename) { - return new Promise(resolve => { - AddonManager.getInstallForFile(do_get_file(DATA + filename), resolve, "application/x-xpinstall"); - }); -} - -function run_test() { - createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "4", "4"); - startupManager(); - - run_next_test(); -} - -function* test_addon(filename) { - do_print("Testing " + filename); - - let install = yield createInstall(filename); - do_check_eq(install.state, AddonManager.STATE_DOWNLOADED); - do_check_eq(install.error, 0); - - do_check_neq(install.linkedInstalls, null); - do_check_eq(install.linkedInstalls.length, 1); - - let linked = install.linkedInstalls[0]; - do_print(linked.state); - do_check_eq(linked.error, ADDONS[filename]); - if (linked.error == 0) { - do_check_eq(linked.state, AddonManager.STATE_DOWNLOADED); - linked.cancel(); - } - else { - do_check_eq(linked.state, AddonManager.STATE_DOWNLOAD_FAILED); - } - - install.cancel(); -} - -for (let filename of Object.keys(ADDONS)) - add_task(test_addon.bind(null, filename)); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_signed_updatepref.js b/toolkit/mozapps/extensions/test/xpcshell/test_signed_updatepref.js deleted file mode 100644 index eb1bb78b3..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_signed_updatepref.js +++ /dev/null @@ -1,136 +0,0 @@ -// Disable update security -Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false); -gUseRealCertChecks = true; - -const DATA = "data/signing_checks/"; -const ID = "test@tests.mozilla.org"; - -Components.utils.import("resource://testing-common/httpd.js"); -var gServer = new HttpServer(); -gServer.start(); - -gServer.registerPathHandler("/update.rdf", function(request, response) { - let updateData = {}; - updateData[ID] = [{ - version: "2.0", - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "4", - maxVersion: "6" - }] - }]; - - response.setStatusLine(request.httpVersion, 200, "OK"); - response.write(createUpdateRDF(updateData)); -}); - -const SERVER = "127.0.0.1:" + gServer.identity.primaryPort; -Services.prefs.setCharPref("extensions.update.background.url", "http://" + SERVER + "/update.rdf"); - -function verifySignatures() { - return new Promise(resolve => { - let observer = (subject, topic, data) => { - Services.obs.removeObserver(observer, "xpi-signature-changed"); - resolve(JSON.parse(data)); - } - Services.obs.addObserver(observer, "xpi-signature-changed", false); - - do_print("Verifying signatures"); - let XPIscope = Components.utils.import("resource://gre/modules/addons/XPIProvider.jsm"); - XPIscope.XPIProvider.verifySignatures(); - }); -} - -function run_test() { - createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "4", "4"); - - // Start and stop the manager to initialise everything in the profile before - // actual testing - startupManager(); - shutdownManager(); - - run_next_test(); -} - -// Updating the pref without changing the app version won't disable add-ons -// immediately but will after a signing check -add_task(function*() { - Services.prefs.setBoolPref(PREF_XPI_SIGNATURES_REQUIRED, false); - startupManager(); - - // Install the signed add-on - yield promiseInstallAllFiles([do_get_file(DATA + "unsigned_bootstrap_2.xpi")]); - - let addon = yield promiseAddonByID(ID); - do_check_neq(addon, null); - do_check_false(addon.appDisabled); - do_check_true(addon.isActive); - do_check_eq(addon.signedState, AddonManager.SIGNEDSTATE_MISSING); - - yield promiseShutdownManager(); - - Services.prefs.setBoolPref(PREF_XPI_SIGNATURES_REQUIRED, true); - - startupManager(); - - addon = yield promiseAddonByID(ID); - do_check_neq(addon, null); - do_check_false(addon.appDisabled); - do_check_true(addon.isActive); - do_check_eq(addon.signedState, AddonManager.SIGNEDSTATE_MISSING); - - // Update checks shouldn't affect the add-on - yield AddonManagerInternal.backgroundUpdateCheck(); - addon = yield promiseAddonByID(ID); - do_check_neq(addon, null); - do_check_false(addon.appDisabled); - do_check_true(addon.isActive); - do_check_eq(addon.signedState, AddonManager.SIGNEDSTATE_MISSING); - - let changes = yield verifySignatures(); - - do_check_eq(changes.disabled.length, 1); - do_check_eq(changes.disabled[0], ID); - - addon = yield promiseAddonByID(ID); - do_check_neq(addon, null); - do_check_true(addon.appDisabled); - do_check_false(addon.isActive); - do_check_eq(addon.signedState, AddonManager.SIGNEDSTATE_MISSING); - - addon.uninstall(); - - yield promiseShutdownManager(); -}); - -// Updating the pref with changing the app version will disable add-ons -// immediately -add_task(function*() { - Services.prefs.setBoolPref(PREF_XPI_SIGNATURES_REQUIRED, false); - startupManager(); - - // Install the signed add-on - yield promiseInstallAllFiles([do_get_file(DATA + "unsigned_bootstrap_2.xpi")]); - - let addon = yield promiseAddonByID(ID); - do_check_neq(addon, null); - do_check_false(addon.appDisabled); - do_check_true(addon.isActive); - do_check_eq(addon.signedState, AddonManager.SIGNEDSTATE_MISSING); - - yield promiseShutdownManager(); - - Services.prefs.setBoolPref(PREF_XPI_SIGNATURES_REQUIRED, true); - gAppInfo.version = 5.0 - startupManager(true); - - addon = yield promiseAddonByID(ID); - do_check_neq(addon, null); - do_check_true(addon.appDisabled); - do_check_false(addon.isActive); - do_check_eq(addon.signedState, AddonManager.SIGNEDSTATE_MISSING); - - addon.uninstall(); - - yield promiseShutdownManager(); -}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_signed_verify.js b/toolkit/mozapps/extensions/test/xpcshell/test_signed_verify.js deleted file mode 100644 index 0b5b30d89..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_signed_verify.js +++ /dev/null @@ -1,234 +0,0 @@ -// Enable signature checks for these tests -gUseRealCertChecks = true; -// Disable update security -Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false); - -const DATA = "data/signing_checks/"; -const GOOD = [ - ["signed_bootstrap_2.xpi", AddonManager.SIGNEDSTATE_SIGNED], - ["signed_nonbootstrap_2.xpi", AddonManager.SIGNEDSTATE_SIGNED] -]; -const BAD = [ - ["unsigned_bootstrap_2.xpi", AddonManager.SIGNEDSTATE_MISSING], - ["signed_bootstrap_badid_2.xpi", AddonManager.SIGNEDSTATE_BROKEN], - ["unsigned_nonbootstrap_2.xpi", AddonManager.SIGNEDSTATE_MISSING], - ["signed_nonbootstrap_badid_2.xpi", AddonManager.SIGNEDSTATE_BROKEN], -]; -const ID = "test@tests.mozilla.org"; - -const profileDir = gProfD.clone(); -profileDir.append("extensions"); - -function verifySignatures() { - return new Promise(resolve => { - let observer = (subject, topic, data) => { - Services.obs.removeObserver(observer, "xpi-signature-changed"); - resolve(JSON.parse(data)); - } - Services.obs.addObserver(observer, "xpi-signature-changed", false); - - do_print("Verifying signatures"); - let XPIscope = Components.utils.import("resource://gre/modules/addons/XPIProvider.jsm"); - XPIscope.XPIProvider.verifySignatures(); - }); -} - -function run_test() { - createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "4", "4"); - - run_next_test(); -} - -function verify_no_change([startFile, startState], [endFile, endState]) { - add_task(function*() { - do_print("A switch from " + startFile + " to " + endFile + " should cause no change."); - - // Install the first add-on - manuallyInstall(do_get_file(DATA + startFile), profileDir, ID); - startupManager(); - - let addon = yield promiseAddonByID(ID); - do_check_neq(addon, null); - let wasAppDisabled = addon.appDisabled; - do_check_neq(addon.appDisabled, addon.isActive); - do_check_eq(addon.pendingOperations, AddonManager.PENDING_NONE); - do_check_eq(addon.signedState, startState); - - // Swap in the files from the next add-on - manuallyUninstall(profileDir, ID); - manuallyInstall(do_get_file(DATA + endFile), profileDir, ID); - - let events = { - [ID]: [] - }; - - if (startState != endState) - events[ID].unshift(["onPropertyChanged", ["signedState"]]); - - prepare_test(events); - - // Trigger the check - let changes = yield verifySignatures(); - do_check_eq(changes.enabled.length, 0); - do_check_eq(changes.disabled.length, 0); - - do_check_eq(addon.appDisabled, wasAppDisabled); - do_check_neq(addon.appDisabled, addon.isActive); - do_check_eq(addon.pendingOperations, AddonManager.PENDING_NONE); - do_check_eq(addon.signedState, endState); - - // Remove the add-on and restart to let it go away - manuallyUninstall(profileDir, ID); - yield promiseRestartManager(); - yield promiseShutdownManager(); - }); -} - -function verify_enables([startFile, startState], [endFile, endState]) { - add_task(function*() { - do_print("A switch from " + startFile + " to " + endFile + " should enable the add-on."); - - // Install the first add-on - manuallyInstall(do_get_file(DATA + startFile), profileDir, ID); - startupManager(); - - let addon = yield promiseAddonByID(ID); - do_check_neq(addon, null); - do_check_false(addon.isActive); - do_check_eq(addon.pendingOperations, AddonManager.PENDING_NONE); - do_check_eq(addon.signedState, startState); - - // Swap in the files from the next add-on - manuallyUninstall(profileDir, ID); - manuallyInstall(do_get_file(DATA + endFile), profileDir, ID); - - let needsRestart = hasFlag(addon.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_ENABLE); - do_print(needsRestart); - - let events = {}; - if (!needsRestart) { - events[ID] = [ - ["onPropertyChanged", ["appDisabled"]], - ["onEnabling", false], - "onEnabled" - ]; - } - else { - events[ID] = [ - ["onPropertyChanged", ["appDisabled"]], - "onEnabling" - ]; - } - - if (startState != endState) - events[ID].unshift(["onPropertyChanged", ["signedState"]]); - - prepare_test(events); - - // Trigger the check - let changes = yield verifySignatures(); - do_check_eq(changes.enabled.length, 1); - do_check_eq(changes.enabled[0], ID); - do_check_eq(changes.disabled.length, 0); - - do_check_false(addon.appDisabled); - if (needsRestart) - do_check_neq(addon.pendingOperations, AddonManager.PENDING_NONE); - else - do_check_true(addon.isActive); - do_check_eq(addon.signedState, endState); - - ensure_test_completed(); - - // Remove the add-on and restart to let it go away - manuallyUninstall(profileDir, ID); - yield promiseRestartManager(); - yield promiseShutdownManager(); - }); -} - -function verify_disables([startFile, startState], [endFile, endState]) { - add_task(function*() { - do_print("A switch from " + startFile + " to " + endFile + " should disable the add-on."); - - // Install the first add-on - manuallyInstall(do_get_file(DATA + startFile), profileDir, ID); - startupManager(); - - let addon = yield promiseAddonByID(ID); - do_check_neq(addon, null); - do_check_true(addon.isActive); - do_check_eq(addon.pendingOperations, AddonManager.PENDING_NONE); - do_check_eq(addon.signedState, startState); - - let needsRestart = hasFlag(addon.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_DISABLE); - - // Swap in the files from the next add-on - manuallyUninstall(profileDir, ID); - manuallyInstall(do_get_file(DATA + endFile), profileDir, ID); - - let events = {}; - if (!needsRestart) { - events[ID] = [ - ["onPropertyChanged", ["appDisabled"]], - ["onDisabling", false], - "onDisabled" - ]; - } - else { - events[ID] = [ - ["onPropertyChanged", ["appDisabled"]], - "onDisabling" - ]; - } - - if (startState != endState) - events[ID].unshift(["onPropertyChanged", ["signedState"]]); - - prepare_test(events); - - // Trigger the check - let changes = yield verifySignatures(); - do_check_eq(changes.enabled.length, 0); - do_check_eq(changes.disabled.length, 1); - do_check_eq(changes.disabled[0], ID); - - do_check_true(addon.appDisabled); - if (needsRestart) - do_check_neq(addon.pendingOperations, AddonManager.PENDING_NONE); - else - do_check_false(addon.isActive); - do_check_eq(addon.signedState, endState); - - ensure_test_completed(); - - // Remove the add-on and restart to let it go away - manuallyUninstall(profileDir, ID); - yield promiseRestartManager(); - yield promiseShutdownManager(); - }); -} - -for (let start of GOOD) { - for (let end of BAD) { - verify_disables(start, end); - } -} - -for (let start of BAD) { - for (let end of GOOD) { - verify_enables(start, end); - } -} - -for (let start of GOOD) { - for (let end of GOOD.filter(f => f != start)) { - verify_no_change(start, end); - } -} - -for (let start of BAD) { - for (let end of BAD.filter(f => f != start)) { - verify_no_change(start, end); - } -} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_softblocked.js b/toolkit/mozapps/extensions/test/xpcshell/test_softblocked.js deleted file mode 100644 index 260b536e1..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_softblocked.js +++ /dev/null @@ -1,109 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -const { utils: Cu, interfaces: Ci, classes: Cc, results: Cr } = Components; - -const URI_EXTENSION_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul"; - -Cu.import("resource://gre/modules/NetUtil.jsm"); -Cu.import("resource://testing-common/MockRegistrar.jsm"); - -// Allow insecure updates -Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false) - -const testserver = createHttpServer(); -gPort = testserver.identity.primaryPort; -testserver.registerDirectory("/data/", do_get_file("data")); - -// Don't need the full interface, attempts to call other methods will just -// throw which is just fine -var WindowWatcher = { - openWindow: function(parent, url, name, features, openArgs) { - // Should be called to list the newly blocklisted items - do_check_eq(url, URI_EXTENSION_BLOCKLIST_DIALOG); - - // Simulate auto-disabling any softblocks - var list = openArgs.wrappedJSObject.list; - list.forEach(function(aItem) { - if (!aItem.blocked) - aItem.disable = true; - }); - - // run the code after the blocklist is closed - Services.obs.notifyObservers(null, "addon-blocklist-closed", null); - }, - - QueryInterface: function(iid) { - if (iid.equals(Ci.nsIWindowWatcher) - || iid.equals(Ci.nsISupports)) - return this; - - throw Cr.NS_ERROR_NO_INTERFACE; - } -}; - -MockRegistrar.register("@mozilla.org/embedcomp/window-watcher;1", WindowWatcher); - -const profileDir = gProfD.clone(); -profileDir.append("extensions"); - -function load_blocklist(aFile) { - return new Promise((resolve, reject) => { - Services.obs.addObserver(function() { - Services.obs.removeObserver(arguments.callee, "blocklist-updated"); - - resolve(); - }, "blocklist-updated", false); - - Services.prefs.setCharPref("extensions.blocklist.url", `http://localhost:${gPort}/data/${aFile}`); - var blocklist = Cc["@mozilla.org/extensions/blocklist;1"]. - getService(Ci.nsITimerCallback); - blocklist.notify(null); - }); -} - -function run_test() { - createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1"); - run_next_test(); -} - -// Tests that an appDisabled add-on that becomes softBlocked remains disabled -// when becoming appEnabled -add_task(function* () { - writeInstallRDFForExtension({ - id: "softblock1@tests.mozilla.org", - version: "1.0", - name: "Softblocked add-on", - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "2", - maxVersion: "3" - }] - }, profileDir); - - startupManager(); - - let s1 = yield promiseAddonByID("softblock1@tests.mozilla.org"); - - // Make sure to mark it as previously enabled. - s1.userDisabled = false; - - do_check_false(s1.softDisabled); - do_check_true(s1.appDisabled); - do_check_false(s1.isActive); - - yield load_blocklist("test_softblocked1.xml"); - - do_check_true(s1.softDisabled); - do_check_true(s1.appDisabled); - do_check_false(s1.isActive); - - yield promiseRestartManager("2"); - - s1 = yield promiseAddonByID("softblock1@tests.mozilla.org"); - - do_check_true(s1.softDisabled); - do_check_false(s1.appDisabled); - do_check_false(s1.isActive); -}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_sourceURI.js b/toolkit/mozapps/extensions/test/xpcshell/test_sourceURI.js index db5e4f7cc..e78bb5074 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_sourceURI.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_sourceURI.js @@ -54,10 +54,10 @@ function run_test() { backgroundUpdate(function() { restartManager(); - AddonManager.getAddonByID("addon@tests.mozilla.org", function(a2) { - do_check_neq(a2, null); - do_check_neq(a2.sourceURI, null); - do_check_eq(a2.sourceURI.spec, "http://www.example.com/testaddon.xpi"); + AddonManager.getAddonByID("addon@tests.mozilla.org", function(a) { + do_check_neq(a, null); + do_check_neq(a.sourceURI, null); + do_check_eq(a.sourceURI.spec, "http://www.example.com/testaddon.xpi"); do_test_finished(); }); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_startup.js b/toolkit/mozapps/extensions/test/xpcshell/test_startup.js index fdd00c1ad..181f8ee62 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_startup.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_startup.js @@ -212,8 +212,6 @@ function run_test_1() { do_check_eq(a1.scope, AddonManager.SCOPE_PROFILE); do_check_eq(a1.sourceURI, null); do_check_true(a1.foreignInstall); - do_check_false(a1.userDisabled); - do_check_true(a1.seen); do_check_neq(a2, null); do_check_eq(a2.id, "addon2@tests.mozilla.org"); @@ -228,8 +226,6 @@ function run_test_1() { do_check_eq(a2.scope, AddonManager.SCOPE_PROFILE); do_check_eq(a2.sourceURI, null); do_check_true(a2.foreignInstall); - do_check_false(a1.userDisabled); - do_check_true(a1.seen); do_check_neq(a3, null); do_check_eq(a3.id, "addon3@tests.mozilla.org"); @@ -244,8 +240,6 @@ function run_test_1() { do_check_eq(a3.scope, AddonManager.SCOPE_PROFILE); do_check_eq(a3.sourceURI, null); do_check_true(a3.foreignInstall); - do_check_false(a1.userDisabled); - do_check_true(a1.seen); do_check_eq(a4, null); do_check_false(isExtensionInAddonsList(profileDir, "addon4@tests.mozilla.org")); @@ -830,17 +824,14 @@ function run_test_12() { callback_soon(function([a1, a2, a3, a4, a5]) { do_check_neq(a1, null); do_check_false(a1.userDisabled); - do_check_true(a1.seen); do_check_true(a1.isActive); do_check_neq(a2, null); do_check_true(a2.userDisabled); - do_check_false(a2.seen); do_check_false(a2.isActive); do_check_neq(a3, null); do_check_false(a3.userDisabled); - do_check_true(a3.seen); do_check_true(a3.isActive); var dest = profileDir.clone(); @@ -868,31 +859,28 @@ function run_test_12() { "addon3@tests.mozilla.org", "addon4@tests.mozilla.org", "addon5@tests.mozilla.org"], - function([a1_2, a2_2, a3_2, a4_2, a5_2]) { - do_check_neq(a1_2, null); - do_check_false(a1_2.userDisabled); - do_check_true(a1_2.seen); - do_check_true(a1_2.isActive); - - do_check_neq(a2_2, null); - do_check_false(a2_2.userDisabled); - do_check_true(a2_2.seen); - do_check_true(a2_2.isActive); - - do_check_neq(a3_2, null); - do_check_true(a3_2.userDisabled); - do_check_false(a3_2.seen); - do_check_false(a3_2.isActive); - - var dest2 = profileDir.clone(); - dest2.append(do_get_expected_addon_name("addon1@tests.mozilla.org")); - dest2.remove(true); - dest2 = userDir.clone(); - dest2.append(do_get_expected_addon_name("addon2@tests.mozilla.org")); - dest2.remove(true); - dest2 = globalDir.clone(); - dest2.append(do_get_expected_addon_name("addon3@tests.mozilla.org")); - dest2.remove(true); + function([a1, a2, a3, a4, a5]) { + do_check_neq(a1, null); + do_check_false(a1.userDisabled); + do_check_true(a1.isActive); + + do_check_neq(a2, null); + do_check_false(a2.userDisabled); + do_check_true(a2.isActive); + + do_check_neq(a3, null); + do_check_true(a3.userDisabled); + do_check_false(a3.isActive); + + var dest = profileDir.clone(); + dest.append(do_get_expected_addon_name("addon1@tests.mozilla.org")); + dest.remove(true); + dest = userDir.clone(); + dest.append(do_get_expected_addon_name("addon2@tests.mozilla.org")); + dest.remove(true); + dest = globalDir.clone(); + dest.append(do_get_expected_addon_name("addon3@tests.mozilla.org")); + dest.remove(true); restartManager(); @@ -909,21 +897,18 @@ function run_test_12() { "addon3@tests.mozilla.org", "addon4@tests.mozilla.org", "addon5@tests.mozilla.org"], - function([a1_3, a2_3, a3_3, a4_3, a5_3]) { - do_check_neq(a1_3, null); - do_check_false(a1_3.userDisabled); - do_check_true(a1_3.seen); - do_check_true(a1_3.isActive); - - do_check_neq(a2_3, null); - do_check_true(a2_3.userDisabled); - do_check_false(a2_3.seen); - do_check_false(a2_3.isActive); - - do_check_neq(a3_3, null); - do_check_true(a3_3.userDisabled); - do_check_false(a3_3.seen); - do_check_false(a3_3.isActive); + function([a1, a2, a3, a4, a5]) { + do_check_neq(a1, null); + do_check_false(a1.userDisabled); + do_check_true(a1.isActive); + + do_check_neq(a2, null); + do_check_true(a2.userDisabled); + do_check_false(a2.isActive); + + do_check_neq(a3, null); + do_check_true(a3.userDisabled); + do_check_false(a3.isActive); do_execute_soon(end_test); }); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_strictcompatibility.js b/toolkit/mozapps/extensions/test/xpcshell/test_strictcompatibility.js index cb6704936..788e1ef79 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_strictcompatibility.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_strictcompatibility.js @@ -1,203 +1,203 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -// Tests AddonManager.strictCompatibility and it's related preference, -// extensions.strictCompatibility, and the strictCompatibility option in -// install.rdf - - -// Always compatible -var addon1 = { - id: "addon1@tests.mozilla.org", - version: "1.0", - name: "Test 1", - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "1", - maxVersion: "1" - }] -}; - -// Incompatible in strict compatibility mode -var addon2 = { - id: "addon2@tests.mozilla.org", - version: "1.0", - name: "Test 2", - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "0.7", - maxVersion: "0.8" - }] -}; - -// Theme - always uses strict compatibility, so is always incompatible -var addon3 = { - id: "addon3@tests.mozilla.org", - version: "1.0", - name: "Test 3", - internalName: "test-theme-3", - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "0.8", - maxVersion: "0.9" - }] -}; - -// Opt-in to strict compatibility - always incompatible -var addon4 = { - id: "addon4@tests.mozilla.org", - version: "1.0", - name: "Test 4", - strictCompatibility: true, - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "0.8", - maxVersion: "0.9" - }] -}; - -// Addon from the future - would be marked as compatibile-by-default, -// but minVersion is higher than the app version -var addon5 = { - id: "addon5@tests.mozilla.org", - version: "1.0", - name: "Test 5", - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "3", - maxVersion: "5" - }] -}; - -// Extremely old addon - maxVersion is less than the mimimum compat version -// set in extensions.minCompatibleVersion -var addon6 = { - id: "addon6@tests.mozilla.org", - version: "1.0", - name: "Test 6", - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "0.1", - maxVersion: "0.2" - }] -}; - -// Dictionary - incompatible in strict compatibility mode -var addon7= { - id: "addon7@tests.mozilla.org", - version: "1.0", - name: "Test 7", - type: "64", - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "0.8", - maxVersion: "0.9" - }] -}; - - - -const profileDir = gProfD.clone(); -profileDir.append("extensions"); - - -function do_check_compat_status(aStrict, aAddonCompat, aCallback) { - do_check_eq(AddonManager.strictCompatibility, aStrict); - AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", - "addon2@tests.mozilla.org", - "addon3@tests.mozilla.org", - "addon4@tests.mozilla.org", - "addon5@tests.mozilla.org", - "addon6@tests.mozilla.org", - "addon7@tests.mozilla.org"], - function([a1, a2, a3, a4, a5, a6, a7]) { - do_check_neq(a1, null); - do_check_eq(a1.isCompatible, aAddonCompat[0]); - do_check_eq(a1.appDisabled, !aAddonCompat[0]); - do_check_false(a1.strictCompatibility); - - do_check_neq(a2, null); - do_check_eq(a2.isCompatible, aAddonCompat[1]); - do_check_eq(a2.appDisabled, !aAddonCompat[1]); - do_check_false(a2.strictCompatibility); - - do_check_neq(a3, null); - do_check_eq(a3.isCompatible, aAddonCompat[2]); - do_check_eq(a3.appDisabled, !aAddonCompat[2]); - do_check_true(a3.strictCompatibility); - - do_check_neq(a4, null); - do_check_eq(a4.isCompatible, aAddonCompat[3]); - do_check_eq(a4.appDisabled, !aAddonCompat[3]); - do_check_true(a4.strictCompatibility); - - do_check_neq(a5, null); - do_check_eq(a5.isCompatible, aAddonCompat[4]); - do_check_eq(a5.appDisabled, !aAddonCompat[4]); - do_check_false(a5.strictCompatibility); - - do_check_neq(a6, null); - do_check_eq(a6.isCompatible, aAddonCompat[5]); - do_check_eq(a6.appDisabled, !aAddonCompat[5]); - do_check_false(a6.strictCompatibility); - - do_check_neq(a7, null); - do_check_eq(a7.isCompatible, aAddonCompat[6]); - do_check_eq(a7.appDisabled, !aAddonCompat[6]); - do_check_false(a7.strictCompatibility); - - do_execute_soon(aCallback); - }); -} - - -function run_test() { - do_test_pending(); - createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); - - writeInstallRDFForExtension(addon1, profileDir); - writeInstallRDFForExtension(addon2, profileDir); - writeInstallRDFForExtension(addon3, profileDir); - writeInstallRDFForExtension(addon4, profileDir); - writeInstallRDFForExtension(addon5, profileDir); - writeInstallRDFForExtension(addon6, profileDir); - writeInstallRDFForExtension(addon7, profileDir); - - Services.prefs.setCharPref(PREF_EM_MIN_COMPAT_APP_VERSION, "0.1"); - - startupManager(); - - // Should default to enabling strict compat. - do_check_compat_status(true, [true, false, false, false, false, false, false], run_test_1); -} - -function run_test_1() { - do_print("Test 1"); - Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, false); - do_check_compat_status(false, [true, true, false, false, false, true, true], run_test_2); -} - -function run_test_2() { - do_print("Test 2"); - restartManager(); - do_check_compat_status(false, [true, true, false, false, false, true, true], run_test_3); -} - -function run_test_3() { - do_print("Test 3"); - Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, true); - do_check_compat_status(true, [true, false, false, false, false, false, false], run_test_4); -} - -function run_test_4() { - do_print("Test 4"); - restartManager(); - do_check_compat_status(true, [true, false, false, false, false, false, false], run_test_5); -} - -function run_test_5() { - do_print("Test 5"); - Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, false); - Services.prefs.setCharPref(PREF_EM_MIN_COMPAT_APP_VERSION, "0.4"); - do_check_compat_status(false, [true, true, false, false, false, false, true], do_test_finished); -} +/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Tests AddonManager.strictCompatibility and it's related preference,
+// extensions.strictCompatibility, and the strictCompatibility option in
+// install.rdf
+
+
+// Always compatible
+var addon1 = {
+ id: "addon1@tests.mozilla.org",
+ version: "1.0",
+ name: "Test 1",
+ targetApplications: [{
+ id: "xpcshell@tests.mozilla.org",
+ minVersion: "1",
+ maxVersion: "1"
+ }]
+};
+
+// Incompatible in strict compatibility mode
+var addon2 = {
+ id: "addon2@tests.mozilla.org",
+ version: "1.0",
+ name: "Test 2",
+ targetApplications: [{
+ id: "xpcshell@tests.mozilla.org",
+ minVersion: "0.7",
+ maxVersion: "0.8"
+ }]
+};
+
+// Theme - always uses strict compatibility, so is always incompatible
+var addon3 = {
+ id: "addon3@tests.mozilla.org",
+ version: "1.0",
+ name: "Test 3",
+ internalName: "test-theme-3",
+ targetApplications: [{
+ id: "xpcshell@tests.mozilla.org",
+ minVersion: "0.8",
+ maxVersion: "0.9"
+ }]
+};
+
+// Opt-in to strict compatibility - always incompatible
+var addon4 = {
+ id: "addon4@tests.mozilla.org",
+ version: "1.0",
+ name: "Test 4",
+ strictCompatibility: true,
+ targetApplications: [{
+ id: "xpcshell@tests.mozilla.org",
+ minVersion: "0.8",
+ maxVersion: "0.9"
+ }]
+};
+
+// Addon from the future - would be marked as compatibile-by-default,
+// but minVersion is higher than the app version
+var addon5 = {
+ id: "addon5@tests.mozilla.org",
+ version: "1.0",
+ name: "Test 5",
+ targetApplications: [{
+ id: "xpcshell@tests.mozilla.org",
+ minVersion: "3",
+ maxVersion: "5"
+ }]
+};
+
+// Extremely old addon - maxVersion is less than the mimimum compat version
+// set in extensions.minCompatibleVersion
+var addon6 = {
+ id: "addon6@tests.mozilla.org",
+ version: "1.0",
+ name: "Test 6",
+ targetApplications: [{
+ id: "xpcshell@tests.mozilla.org",
+ minVersion: "0.1",
+ maxVersion: "0.2"
+ }]
+};
+
+// Dictionary - incompatible in strict compatibility mode
+var addon7= {
+ id: "addon7@tests.mozilla.org",
+ version: "1.0",
+ name: "Test 7",
+ type: "64",
+ targetApplications: [{
+ id: "xpcshell@tests.mozilla.org",
+ minVersion: "0.8",
+ maxVersion: "0.9"
+ }]
+};
+
+
+
+const profileDir = gProfD.clone();
+profileDir.append("extensions");
+
+
+function do_check_compat_status(aStrict, aAddonCompat, aCallback) {
+ do_check_eq(AddonManager.strictCompatibility, aStrict);
+ AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
+ "addon2@tests.mozilla.org",
+ "addon3@tests.mozilla.org",
+ "addon4@tests.mozilla.org",
+ "addon5@tests.mozilla.org",
+ "addon6@tests.mozilla.org",
+ "addon7@tests.mozilla.org"],
+ function([a1, a2, a3, a4, a5, a6, a7]) {
+ do_check_neq(a1, null);
+ do_check_eq(a1.isCompatible, aAddonCompat[0]);
+ do_check_eq(a1.appDisabled, !aAddonCompat[0]);
+ do_check_false(a1.strictCompatibility);
+
+ do_check_neq(a2, null);
+ do_check_eq(a2.isCompatible, aAddonCompat[1]);
+ do_check_eq(a2.appDisabled, !aAddonCompat[1]);
+ do_check_false(a2.strictCompatibility);
+
+ do_check_neq(a3, null);
+ do_check_eq(a3.isCompatible, aAddonCompat[2]);
+ do_check_eq(a3.appDisabled, !aAddonCompat[2]);
+ do_check_true(a3.strictCompatibility);
+
+ do_check_neq(a4, null);
+ do_check_eq(a4.isCompatible, aAddonCompat[3]);
+ do_check_eq(a4.appDisabled, !aAddonCompat[3]);
+ do_check_true(a4.strictCompatibility);
+
+ do_check_neq(a5, null);
+ do_check_eq(a5.isCompatible, aAddonCompat[4]);
+ do_check_eq(a5.appDisabled, !aAddonCompat[4]);
+ do_check_false(a5.strictCompatibility);
+
+ do_check_neq(a6, null);
+ do_check_eq(a6.isCompatible, aAddonCompat[5]);
+ do_check_eq(a6.appDisabled, !aAddonCompat[5]);
+ do_check_false(a6.strictCompatibility);
+
+ do_check_neq(a7, null);
+ do_check_eq(a7.isCompatible, aAddonCompat[6]);
+ do_check_eq(a7.appDisabled, !aAddonCompat[6]);
+ do_check_false(a7.strictCompatibility);
+
+ do_execute_soon(aCallback);
+ });
+}
+
+
+function run_test() {
+ do_test_pending();
+ createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
+
+ writeInstallRDFForExtension(addon1, profileDir);
+ writeInstallRDFForExtension(addon2, profileDir);
+ writeInstallRDFForExtension(addon3, profileDir);
+ writeInstallRDFForExtension(addon4, profileDir);
+ writeInstallRDFForExtension(addon5, profileDir);
+ writeInstallRDFForExtension(addon6, profileDir);
+ writeInstallRDFForExtension(addon7, profileDir);
+
+ Services.prefs.setCharPref(PREF_EM_MIN_COMPAT_APP_VERSION, "0.1");
+
+ startupManager();
+
+ // Should default to enabling strict compat.
+ do_check_compat_status(true, [true, false, false, false, false, false, false], run_test_1);
+}
+
+function run_test_1() {
+ do_print("Test 1");
+ Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, false);
+ do_check_compat_status(false, [true, true, false, false, false, true, true], run_test_2);
+}
+
+function run_test_2() {
+ do_print("Test 2");
+ restartManager();
+ do_check_compat_status(false, [true, true, false, false, false, true, true], run_test_3);
+}
+
+function run_test_3() {
+ do_print("Test 3");
+ Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, true);
+ do_check_compat_status(true, [true, false, false, false, false, false, false], run_test_4);
+}
+
+function run_test_4() {
+ do_print("Test 4");
+ restartManager();
+ do_check_compat_status(true, [true, false, false, false, false, false, false], run_test_5);
+}
+
+function run_test_5() {
+ do_print("Test 5");
+ Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, false);
+ Services.prefs.setCharPref(PREF_EM_MIN_COMPAT_APP_VERSION, "0.4");
+ do_check_compat_status(false, [true, true, false, false, false, false, true], do_test_finished);
+}
diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_switch_os.js b/toolkit/mozapps/extensions/test/xpcshell/test_switch_os.js deleted file mode 100644 index 552d7cfae..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_switch_os.js +++ /dev/null @@ -1,52 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -Components.utils.import("resource://gre/modules/AppConstants.jsm"); - -const ID = "bootstrap1@tests.mozilla.org"; - -BootstrapMonitor.init(); - -const profileDir = gProfD.clone(); -profileDir.append("extensions"); - -createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); - -add_task(function*() { - startupManager(); - - let install = yield new Promise(resolve => AddonManager.getInstallForFile(do_get_addon("test_bootstrap1_1"), resolve)); - yield promiseCompleteAllInstalls([install]); - - let addon = yield promiseAddonByID(ID); - do_check_neq(addon, null); - - BootstrapMonitor.checkAddonStarted(ID); - do_check_false(addon.userDisabled); - do_check_true(addon.isActive); - - yield promiseShutdownManager(); - - BootstrapMonitor.checkAddonNotStarted(ID); - - let jData = loadJSON(gExtensionsJSON); - - for (let addonInstance of jData.addons) { - if (addonInstance.id == ID) { - // Set to something that would be an invalid descriptor for this platform - addonInstance.descriptor = AppConstants.platform == "win" ? "/foo/bar" : "C:\\foo\\bar"; - } - } - - saveJSON(jData, gExtensionsJSON); - - startupManager(); - - addon = yield promiseAddonByID(ID); - do_check_neq(addon, null); - - BootstrapMonitor.checkAddonStarted(ID); - do_check_false(addon.userDisabled); - do_check_true(addon.isActive); -}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_syncGUID.js b/toolkit/mozapps/extensions/test/xpcshell/test_syncGUID.js index 385f58405..f1d6e0914 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_syncGUID.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_syncGUID.js @@ -22,8 +22,6 @@ function run_test() { run_next_test(); } -const UUID_PATTERN = /^\{[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\}$/i; - add_test(function test_getter_and_setter() { // Our test add-on requires a restart. let listener = { @@ -37,7 +35,7 @@ add_test(function test_getter_and_setter() { do_check_neq(addon, null); do_check_neq(addon.syncGUID, null); - do_check_true(UUID_PATTERN.test(addon.syncGUID)); + do_check_true(addon.syncGUID.length >= 9); let oldGUID = addon.SyncGUID; let newGUID = "foo"; @@ -113,7 +111,7 @@ add_test(function test_error_on_duplicate_syncguid_insert() { AddonManager.addInstallListener(listener); let getInstallCB = function(install) { install.install(); }; - for (let name of installNames) { + for each (let name in installNames) { AddonManager.getInstallForFile(do_get_addon(name), getInstallCB); } }); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_system_delay_update.js b/toolkit/mozapps/extensions/test/xpcshell/test_system_delay_update.js deleted file mode 100644 index 35964c663..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_system_delay_update.js +++ /dev/null @@ -1,461 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -// This verifies that delaying a system add-on update works. - -Components.utils.import("resource://testing-common/httpd.js"); -const profileDir = gProfD.clone(); -profileDir.append("extensions"); -const tempdir = gTmpD.clone(); - -const PREF_SYSTEM_ADDON_SET = "extensions.systemAddonSet"; -const PREF_SYSTEM_ADDON_UPDATE_URL = "extensions.systemAddon.update.url"; - -const IGNORE_ID = "system_delay_ignore@tests.mozilla.org"; -const COMPLETE_ID = "system_delay_complete@tests.mozilla.org"; -const DEFER_ID = "system_delay_defer@tests.mozilla.org"; -const DEFER_ALSO_ID = "system_delay_defer_also@tests.mozilla.org"; -const NORMAL_ID = "system1@tests.mozilla.org"; - - -const TEST_IGNORE_PREF = "delaytest.ignore"; - -const distroDir = FileUtils.getDir("ProfD", ["sysfeatures"], true); -registerDirectory("XREAppFeat", distroDir); - -let testserver = new HttpServer(); -testserver.registerDirectory("/data/", do_get_file("data/system_addons")); -testserver.start(); -let root = `${testserver.identity.primaryScheme}://${testserver.identity.primaryHost}:${testserver.identity.primaryPort}/data/`; -Services.prefs.setCharPref(PREF_SYSTEM_ADDON_UPDATE_URL, root + "update.xml"); - - -// Note that we would normally use BootstrapMonitor but it currently requires -// the objects in `data` to be serializable, and we need a real reference to the -// `instanceID` symbol to test. - -createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "42"); - -function promiseInstallPostponed(addonID1, addonID2) { - return new Promise((resolve, reject) => { - let seen = []; - let listener = { - onInstallFailed: () => { - AddonManager.removeInstallListener(listener); - reject("extension installation should not have failed"); - }, - onInstallEnded: (install) => { - AddonManager.removeInstallListener(listener); - reject(`extension installation should not have ended for ${install.addon.id}`); - }, - onInstallPostponed: (install) => { - seen.push(install.addon.id); - if (seen.includes(addonID1) && seen.includes(addonID2)) { - AddonManager.removeInstallListener(listener); - resolve(); - } - } - }; - - AddonManager.addInstallListener(listener); - }); -} - -function promiseInstallResumed(addonID1, addonID2) { - return new Promise((resolve, reject) => { - let seenPostponed = []; - let seenEnded = []; - let listener = { - onInstallFailed: () => { - AddonManager.removeInstallListener(listener); - reject("extension installation should not have failed"); - }, - onInstallEnded: (install) => { - seenEnded.push(install.addon.id); - if ((seenEnded.includes(addonID1) && seenEnded.includes(addonID2)) && - (seenPostponed.includes(addonID1) && seenPostponed.includes(addonID2))) { - AddonManager.removeInstallListener(listener); - resolve(); - } - }, - onInstallPostponed: (install) => { - seenPostponed.push(install.addon.id); - } - }; - - AddonManager.addInstallListener(listener); - }); -} - -function promiseInstallDeferred(addonID1, addonID2) { - return new Promise((resolve, reject) => { - let seenEnded = []; - let listener = { - onInstallFailed: () => { - AddonManager.removeInstallListener(listener); - reject("extension installation should not have failed"); - }, - onInstallEnded: (install) => { - seenEnded.push(install.addon.id); - if (seenEnded.includes(addonID1) && seenEnded.includes(addonID2)) { - AddonManager.removeInstallListener(listener); - resolve(); - } - }, - onInstallPostponed: (install) => { - AddonManager.removeInstallListener(listener); - reject(`extension installation should not have been postponed for ${install.addon.id}`); - } - }; - - AddonManager.addInstallListener(listener); - }); -} - - -// add-on registers upgrade listener, and ignores update. -add_task(function*() { - // discard system addon updates - Services.prefs.setCharPref(PREF_SYSTEM_ADDON_SET, ""); - - do_get_file("data/system_addons/system_delay_ignore.xpi").copyTo(distroDir, "system_delay_ignore@tests.mozilla.org.xpi"); - do_get_file("data/system_addons/system1_1.xpi").copyTo(distroDir, "system1@tests.mozilla.org.xpi"); - - startupManager(); - let updateList = [ - { id: IGNORE_ID, version: "2.0", path: "system_delay_ignore_2.xpi" }, - { id: NORMAL_ID, version: "2.0", path: "system1_2.xpi" }, - ]; - - let postponed = promiseInstallPostponed(IGNORE_ID, NORMAL_ID); - yield installSystemAddons(yield buildSystemAddonUpdates(updateList, root), testserver); - yield postponed; - - // addon upgrade has been delayed. - let addon_postponed = yield promiseAddonByID(IGNORE_ID, NORMAL_ID); - do_check_neq(addon_postponed, null); - do_check_eq(addon_postponed.version, "1.0"); - do_check_eq(addon_postponed.name, "System Test Delay Update Ignore"); - do_check_true(addon_postponed.isCompatible); - do_check_false(addon_postponed.appDisabled); - do_check_true(addon_postponed.isActive); - do_check_eq(addon_postponed.type, "extension"); - do_check_true(Services.prefs.getBoolPref(TEST_IGNORE_PREF)); - - // other addons in the set are delayed as well. - addon_postponed = yield promiseAddonByID(NORMAL_ID); - do_check_neq(addon_postponed, null); - do_check_eq(addon_postponed.version, "1.0"); - do_check_eq(addon_postponed.name, "System Add-on 1"); - do_check_true(addon_postponed.isCompatible); - do_check_false(addon_postponed.appDisabled); - do_check_true(addon_postponed.isActive); - do_check_eq(addon_postponed.type, "extension"); - - // restarting allows upgrades to proceed - yield promiseRestartManager(); - - let addon_upgraded = yield promiseAddonByID(IGNORE_ID); - do_check_neq(addon_upgraded, null); - do_check_eq(addon_upgraded.version, "2.0"); - do_check_eq(addon_upgraded.name, "System Test Delay Update Ignore"); - do_check_true(addon_upgraded.isCompatible); - do_check_false(addon_upgraded.appDisabled); - do_check_true(addon_upgraded.isActive); - do_check_eq(addon_upgraded.type, "extension"); - - addon_upgraded = yield promiseAddonByID(NORMAL_ID); - do_check_neq(addon_upgraded, null); - do_check_eq(addon_upgraded.version, "2.0"); - do_check_eq(addon_upgraded.name, "System Add-on 1"); - do_check_true(addon_upgraded.isCompatible); - do_check_false(addon_upgraded.appDisabled); - do_check_true(addon_upgraded.isActive); - do_check_eq(addon_upgraded.type, "extension"); - - yield shutdownManager(); -}); - -// add-on registers upgrade listener, and allows update. -add_task(function*() { - // discard system addon updates - Services.prefs.setCharPref(PREF_SYSTEM_ADDON_SET, ""); - - do_get_file("data/system_addons/system_delay_complete.xpi").copyTo(distroDir, "system_delay_complete@tests.mozilla.org.xpi"); - do_get_file("data/system_addons/system1_1.xpi").copyTo(distroDir, "system1@tests.mozilla.org.xpi"); - - startupManager(); - - let updateList = [ - { id: COMPLETE_ID, version: "2.0", path: "system_delay_complete_2.xpi" }, - { id: NORMAL_ID, version: "2.0", path: "system1_2.xpi" }, - ]; - - // initial state - let addon_allowed = yield promiseAddonByID(COMPLETE_ID); - do_check_neq(addon_allowed, null); - do_check_eq(addon_allowed.version, "1.0"); - do_check_eq(addon_allowed.name, "System Test Delay Update Complete"); - do_check_true(addon_allowed.isCompatible); - do_check_false(addon_allowed.appDisabled); - do_check_true(addon_allowed.isActive); - do_check_eq(addon_allowed.type, "extension"); - - addon_allowed = yield promiseAddonByID(NORMAL_ID); - do_check_neq(addon_allowed, null); - do_check_eq(addon_allowed.version, "1.0"); - do_check_eq(addon_allowed.name, "System Add-on 1"); - do_check_true(addon_allowed.isCompatible); - do_check_false(addon_allowed.appDisabled); - do_check_true(addon_allowed.isActive); - do_check_eq(addon_allowed.type, "extension"); - - let resumed = promiseInstallResumed(COMPLETE_ID, NORMAL_ID); - yield installSystemAddons(yield buildSystemAddonUpdates(updateList, root), testserver); - - // update is initially postponed, then resumed - yield resumed; - - // addon upgrade has been allowed - addon_allowed = yield promiseAddonByID(COMPLETE_ID); - do_check_neq(addon_allowed, null); - do_check_eq(addon_allowed.version, "2.0"); - do_check_eq(addon_allowed.name, "System Test Delay Update Complete"); - do_check_true(addon_allowed.isCompatible); - do_check_false(addon_allowed.appDisabled); - do_check_true(addon_allowed.isActive); - do_check_eq(addon_allowed.type, "extension"); - - // other upgrades in the set are allowed as well - addon_allowed = yield promiseAddonByID(NORMAL_ID); - do_check_neq(addon_allowed, null); - do_check_eq(addon_allowed.version, "2.0"); - do_check_eq(addon_allowed.name, "System Add-on 1"); - do_check_true(addon_allowed.isCompatible); - do_check_false(addon_allowed.appDisabled); - do_check_true(addon_allowed.isActive); - do_check_eq(addon_allowed.type, "extension"); - - // restarting changes nothing - yield promiseRestartManager(); - - let addon_upgraded = yield promiseAddonByID(COMPLETE_ID); - do_check_neq(addon_upgraded, null); - do_check_eq(addon_upgraded.version, "2.0"); - do_check_eq(addon_upgraded.name, "System Test Delay Update Complete"); - do_check_true(addon_upgraded.isCompatible); - do_check_false(addon_upgraded.appDisabled); - do_check_true(addon_upgraded.isActive); - do_check_eq(addon_upgraded.type, "extension"); - - addon_upgraded = yield promiseAddonByID(NORMAL_ID); - do_check_neq(addon_upgraded, null); - do_check_eq(addon_upgraded.version, "2.0"); - do_check_eq(addon_upgraded.name, "System Add-on 1"); - do_check_true(addon_upgraded.isCompatible); - do_check_false(addon_upgraded.appDisabled); - do_check_true(addon_upgraded.isActive); - do_check_eq(addon_upgraded.type, "extension"); - - yield shutdownManager(); -}); - -// add-on registers upgrade listener, initially defers update then allows upgrade -add_task(function*() { - // discard system addon updates - Services.prefs.setCharPref(PREF_SYSTEM_ADDON_SET, ""); - - do_get_file("data/system_addons/system_delay_defer.xpi").copyTo(distroDir, "system_delay_defer@tests.mozilla.org.xpi"); - do_get_file("data/system_addons/system1_1.xpi").copyTo(distroDir, "system1@tests.mozilla.org.xpi"); - - startupManager(); - - let updateList = [ - { id: DEFER_ID, version: "2.0", path: "system_delay_defer_2.xpi" }, - { id: NORMAL_ID, version: "2.0", path: "system1_2.xpi" }, - ]; - - let postponed = promiseInstallPostponed(DEFER_ID, NORMAL_ID); - yield installSystemAddons(yield buildSystemAddonUpdates(updateList, root), testserver); - yield postponed; - - // upgrade is initially postponed - let addon_postponed = yield promiseAddonByID(DEFER_ID); - do_check_neq(addon_postponed, null); - do_check_eq(addon_postponed.version, "1.0"); - do_check_eq(addon_postponed.name, "System Test Delay Update Defer"); - do_check_true(addon_postponed.isCompatible); - do_check_false(addon_postponed.appDisabled); - do_check_true(addon_postponed.isActive); - do_check_eq(addon_postponed.type, "extension"); - - // other addons in the set are postponed as well. - addon_postponed = yield promiseAddonByID(NORMAL_ID); - do_check_neq(addon_postponed, null); - do_check_eq(addon_postponed.version, "1.0"); - do_check_eq(addon_postponed.name, "System Add-on 1"); - do_check_true(addon_postponed.isCompatible); - do_check_false(addon_postponed.appDisabled); - do_check_true(addon_postponed.isActive); - do_check_eq(addon_postponed.type, "extension"); - - let deferred = promiseInstallDeferred(DEFER_ID, NORMAL_ID); - // add-on will not allow upgrade until fake event fires - AddonManagerPrivate.callAddonListeners("onFakeEvent"); - - yield deferred; - - // addon upgrade has been allowed - let addon_allowed = yield promiseAddonByID(DEFER_ID); - do_check_neq(addon_allowed, null); - do_check_eq(addon_allowed.version, "2.0"); - do_check_eq(addon_allowed.name, "System Test Delay Update Defer"); - do_check_true(addon_allowed.isCompatible); - do_check_false(addon_allowed.appDisabled); - do_check_true(addon_allowed.isActive); - do_check_eq(addon_allowed.type, "extension"); - - // other addons in the set are allowed as well. - addon_allowed = yield promiseAddonByID(NORMAL_ID); - do_check_neq(addon_allowed, null); - do_check_eq(addon_allowed.version, "2.0"); - do_check_eq(addon_allowed.name, "System Add-on 1"); - do_check_true(addon_allowed.isCompatible); - do_check_false(addon_allowed.appDisabled); - do_check_true(addon_allowed.isActive); - do_check_eq(addon_allowed.type, "extension"); - - // restarting changes nothing - yield promiseRestartManager(); - - let addon_upgraded = yield promiseAddonByID(DEFER_ID); - do_check_neq(addon_upgraded, null); - do_check_eq(addon_upgraded.version, "2.0"); - do_check_eq(addon_upgraded.name, "System Test Delay Update Defer"); - do_check_true(addon_upgraded.isCompatible); - do_check_false(addon_upgraded.appDisabled); - do_check_true(addon_upgraded.isActive); - do_check_eq(addon_upgraded.type, "extension"); - - addon_upgraded = yield promiseAddonByID(NORMAL_ID); - do_check_neq(addon_upgraded, null); - do_check_eq(addon_upgraded.version, "2.0"); - do_check_eq(addon_upgraded.name, "System Add-on 1"); - do_check_true(addon_upgraded.isCompatible); - do_check_false(addon_upgraded.appDisabled); - do_check_true(addon_upgraded.isActive); - do_check_eq(addon_upgraded.type, "extension"); - - yield shutdownManager(); -}); - -// multiple add-ons registers upgrade listeners, initially defers then each unblock in turn. -add_task(function*() { - // discard system addon updates. - Services.prefs.setCharPref(PREF_SYSTEM_ADDON_SET, ""); - - do_get_file("data/system_addons/system_delay_defer.xpi").copyTo(distroDir, "system_delay_defer@tests.mozilla.org.xpi"); - do_get_file("data/system_addons/system_delay_defer_also.xpi").copyTo(distroDir, "system_delay_defer_also@tests.mozilla.org.xpi"); - - startupManager(); - - let updateList = [ - { id: DEFER_ID, version: "2.0", path: "system_delay_defer_2.xpi" }, - { id: DEFER_ALSO_ID, version: "2.0", path: "system_delay_defer_also_2.xpi" }, - ]; - - let postponed = promiseInstallPostponed(DEFER_ID, DEFER_ALSO_ID); - yield installSystemAddons(yield buildSystemAddonUpdates(updateList, root), testserver); - yield postponed; - - // upgrade is initially postponed - let addon_postponed = yield promiseAddonByID(DEFER_ID); - do_check_neq(addon_postponed, null); - do_check_eq(addon_postponed.version, "1.0"); - do_check_eq(addon_postponed.name, "System Test Delay Update Defer"); - do_check_true(addon_postponed.isCompatible); - do_check_false(addon_postponed.appDisabled); - do_check_true(addon_postponed.isActive); - do_check_eq(addon_postponed.type, "extension"); - - // other addons in the set are postponed as well. - addon_postponed = yield promiseAddonByID(DEFER_ALSO_ID); - do_check_neq(addon_postponed, null); - do_check_eq(addon_postponed.version, "1.0"); - do_check_eq(addon_postponed.name, "System Test Delay Update Defer Also"); - do_check_true(addon_postponed.isCompatible); - do_check_false(addon_postponed.appDisabled); - do_check_true(addon_postponed.isActive); - do_check_eq(addon_postponed.type, "extension"); - - let deferred = promiseInstallDeferred(DEFER_ID, DEFER_ALSO_ID); - // add-on will not allow upgrade until fake event fires - AddonManagerPrivate.callAddonListeners("onFakeEvent"); - - // Upgrade blockers still present. - addon_postponed = yield promiseAddonByID(DEFER_ID); - do_check_neq(addon_postponed, null); - do_check_eq(addon_postponed.version, "1.0"); - do_check_eq(addon_postponed.name, "System Test Delay Update Defer"); - do_check_true(addon_postponed.isCompatible); - do_check_false(addon_postponed.appDisabled); - do_check_true(addon_postponed.isActive); - do_check_eq(addon_postponed.type, "extension"); - - addon_postponed = yield promiseAddonByID(DEFER_ALSO_ID); - do_check_neq(addon_postponed, null); - do_check_eq(addon_postponed.version, "1.0"); - do_check_eq(addon_postponed.name, "System Test Delay Update Defer Also"); - do_check_true(addon_postponed.isCompatible); - do_check_false(addon_postponed.appDisabled); - do_check_true(addon_postponed.isActive); - do_check_eq(addon_postponed.type, "extension"); - - AddonManagerPrivate.callAddonListeners("onOtherFakeEvent"); - - yield deferred; - - // addon upgrade has been allowed - let addon_allowed = yield promiseAddonByID(DEFER_ID); - do_check_neq(addon_allowed, null); - do_check_eq(addon_allowed.version, "2.0"); - do_check_eq(addon_allowed.name, "System Test Delay Update Defer"); - do_check_true(addon_allowed.isCompatible); - do_check_false(addon_allowed.appDisabled); - do_check_true(addon_allowed.isActive); - do_check_eq(addon_allowed.type, "extension"); - - // other addons in the set are allowed as well. - addon_allowed = yield promiseAddonByID(DEFER_ALSO_ID); - do_check_neq(addon_allowed, null); - // do_check_eq(addon_allowed.version, "2.0"); - do_check_eq(addon_allowed.name, "System Test Delay Update Defer Also"); - do_check_true(addon_allowed.isCompatible); - do_check_false(addon_allowed.appDisabled); - do_check_true(addon_allowed.isActive); - do_check_eq(addon_allowed.type, "extension"); - - // restarting changes nothing - yield promiseRestartManager(); - - let addon_upgraded = yield promiseAddonByID(DEFER_ID); - do_check_neq(addon_upgraded, null); - do_check_eq(addon_upgraded.version, "2.0"); - do_check_eq(addon_upgraded.name, "System Test Delay Update Defer"); - do_check_true(addon_upgraded.isCompatible); - do_check_false(addon_upgraded.appDisabled); - do_check_true(addon_upgraded.isActive); - do_check_eq(addon_upgraded.type, "extension"); - - addon_upgraded = yield promiseAddonByID(DEFER_ALSO_ID); - do_check_neq(addon_upgraded, null); - do_check_eq(addon_upgraded.version, "2.0"); - do_check_eq(addon_upgraded.name, "System Test Delay Update Defer Also"); - do_check_true(addon_upgraded.isCompatible); - do_check_false(addon_upgraded.appDisabled); - do_check_true(addon_upgraded.isActive); - do_check_eq(addon_upgraded.type, "extension"); - - yield shutdownManager(); -}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_system_reset.js b/toolkit/mozapps/extensions/test/xpcshell/test_system_reset.js deleted file mode 100644 index 31b7e5783..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_system_reset.js +++ /dev/null @@ -1,418 +0,0 @@ -// Tests that we reset to the default system add-ons correctly when switching -// application versions -const PREF_SYSTEM_ADDON_SET = "extensions.systemAddonSet"; - -BootstrapMonitor.init(); - -const updatesDir = FileUtils.getDir("ProfD", ["features"]); - -// Build the test sets -var dir = FileUtils.getDir("ProfD", ["sysfeatures", "app1"], true); -do_get_file("data/system_addons/system1_1.xpi").copyTo(dir, "system1@tests.mozilla.org.xpi"); -do_get_file("data/system_addons/system2_1.xpi").copyTo(dir, "system2@tests.mozilla.org.xpi"); - -dir = FileUtils.getDir("ProfD", ["sysfeatures", "app2"], true); -do_get_file("data/system_addons/system1_2.xpi").copyTo(dir, "system1@tests.mozilla.org.xpi"); -do_get_file("data/system_addons/system3_1.xpi").copyTo(dir, "system3@tests.mozilla.org.xpi"); - -dir = FileUtils.getDir("ProfD", ["sysfeatures", "app3"], true); -do_get_file("data/system_addons/system1_1_badcert.xpi").copyTo(dir, "system1@tests.mozilla.org.xpi"); -do_get_file("data/system_addons/system3_1.xpi").copyTo(dir, "system3@tests.mozilla.org.xpi"); - -const distroDir = FileUtils.getDir("ProfD", ["sysfeatures", "app0"], true); -registerDirectory("XREAppFeat", distroDir); - -createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "0"); - -function makeUUID() { - let uuidGen = AM_Cc["@mozilla.org/uuid-generator;1"]. - getService(AM_Ci.nsIUUIDGenerator); - return uuidGen.generateUUID().toString(); -} - -function* check_installed(conditions) { - for (let i = 0; i < conditions.length; i++) { - let condition = conditions[i]; - let id = "system" + (i + 1) + "@tests.mozilla.org"; - let addon = yield promiseAddonByID(id); - - if (!("isUpgrade" in condition) || !("version" in condition)) { - throw Error("condition must contain isUpgrade and version"); - } - let isUpgrade = conditions[i].isUpgrade; - let version = conditions[i].version; - - let expectedDir = isUpgrade ? updatesDir : distroDir; - - if (version) { - // Add-on should be installed - do_check_neq(addon, null); - do_check_eq(addon.version, version); - do_check_true(addon.isActive); - do_check_false(addon.foreignInstall); - do_check_true(addon.hidden); - do_check_true(addon.isSystem); - do_check_false(hasFlag(addon.permissions, AddonManager.PERM_CAN_UPGRADE)); - if (isUpgrade) { - do_check_true(hasFlag(addon.permissions, AddonManager.PERM_CAN_UNINSTALL)); - } else { - do_check_false(hasFlag(addon.permissions, AddonManager.PERM_CAN_UNINSTALL)); - } - - // Verify the add-ons file is in the right place - let file = expectedDir.clone(); - file.append(id + ".xpi"); - do_check_true(file.exists()); - do_check_true(file.isFile()); - - let uri = addon.getResourceURI(null); - do_check_true(uri instanceof AM_Ci.nsIFileURL); - do_check_eq(uri.file.path, file.path); - - if (isUpgrade) { - do_check_eq(addon.signedState, AddonManager.SIGNEDSTATE_SYSTEM); - } - - // Verify the add-on actually started - BootstrapMonitor.checkAddonStarted(id, version); - } - else { - if (isUpgrade) { - // Add-on should not be installed - do_check_eq(addon, null); - } - else { - // Either add-on should not be installed or it shouldn't be active - do_check_true(!addon || !addon.isActive); - } - - BootstrapMonitor.checkAddonNotStarted(id); - - if (addon) - BootstrapMonitor.checkAddonInstalled(id); - else - BootstrapMonitor.checkAddonNotInstalled(id); - } - } -} - -// Test with a missing features directory -add_task(function* test_missing_app_dir() { - startupManager(); - - let conditions = [ - { isUpgrade: false, version: null }, - { isUpgrade: false, version: null }, - { isUpgrade: false, version: null }, - ]; - - yield check_installed(conditions); - - do_check_false(updatesDir.exists()); - - yield promiseShutdownManager(); -}); - -// Add some features in a new version -add_task(function* test_new_version() { - gAppInfo.version = "1"; - distroDir.leafName = "app1"; - startupManager(); - - let conditions = [ - { isUpgrade: false, version: "1.0" }, - { isUpgrade: false, version: "1.0" }, - { isUpgrade: false, version: null }, - ]; - - yield check_installed(conditions); - - do_check_false(updatesDir.exists()); - - yield promiseShutdownManager(); -}); - -// Another new version swaps one feature and upgrades another -add_task(function* test_upgrade() { - gAppInfo.version = "2"; - distroDir.leafName = "app2"; - startupManager(); - - let conditions = [ - { isUpgrade: false, version: "2.0" }, - { isUpgrade: false, version: null }, - { isUpgrade: false, version: "1.0" }, - ]; - - yield check_installed(conditions); - - do_check_false(updatesDir.exists()); - - yield promiseShutdownManager(); -}); - -// Downgrade -add_task(function* test_downgrade() { - gAppInfo.version = "1"; - distroDir.leafName = "app1"; - startupManager(); - - let conditions = [ - { isUpgrade: false, version: "1.0" }, - { isUpgrade: false, version: "1.0" }, - { isUpgrade: false, version: null }, - ]; - - yield check_installed(conditions); - - do_check_false(updatesDir.exists()); - - yield promiseShutdownManager(); -}); - -// Fake a mid-cycle install -add_task(function* test_updated() { - // Create a random dir to install into - let dirname = makeUUID(); - FileUtils.getDir("ProfD", ["features", dirname], true); - updatesDir.append(dirname); - - // Copy in the system add-ons - let file = do_get_file("data/system_addons/system2_2.xpi"); - file.copyTo(updatesDir, "system2@tests.mozilla.org.xpi"); - file = do_get_file("data/system_addons/system3_2.xpi"); - file.copyTo(updatesDir, "system3@tests.mozilla.org.xpi"); - - // Inject it into the system set - let addonSet = { - schema: 1, - directory: updatesDir.leafName, - addons: { - "system2@tests.mozilla.org": { - version: "2.0" - }, - "system3@tests.mozilla.org": { - version: "2.0" - }, - } - }; - Services.prefs.setCharPref(PREF_SYSTEM_ADDON_SET, JSON.stringify(addonSet)); - - startupManager(false); - - let conditions = [ - { isUpgrade: false, version: "1.0" }, - { isUpgrade: true, version: "2.0" }, - { isUpgrade: true, version: "2.0" }, - ]; - - yield check_installed(conditions); - - yield promiseShutdownManager(); -}); - -// Entering safe mode should disable the updated system add-ons and use the -// default system add-ons -add_task(function* safe_mode_disabled() { - gAppInfo.inSafeMode = true; - startupManager(false); - - let conditions = [ - { isUpgrade: false, version: "1.0" }, - { isUpgrade: false, version: "1.0" }, - { isUpgrade: false, version: null }, - ]; - - yield check_installed(conditions); - - yield promiseShutdownManager(); -}); - -// Leaving safe mode should re-enable the updated system add-ons -add_task(function* normal_mode_enabled() { - gAppInfo.inSafeMode = false; - startupManager(false); - - let conditions = [ - { isUpgrade: false, version: "1.0" }, - { isUpgrade: true, version: "2.0" }, - { isUpgrade: true, version: "2.0" }, - ]; - - yield check_installed(conditions); - - yield promiseShutdownManager(); -}); - -// An additional add-on in the directory should be ignored -add_task(function* test_skips_additional() { - // Copy in the system add-ons - let file = do_get_file("data/system_addons/system4_1.xpi"); - file.copyTo(updatesDir, "system4@tests.mozilla.org.xpi"); - - startupManager(false); - - let conditions = [ - { isUpgrade: false, version: "1.0" }, - { isUpgrade: true, version: "2.0" }, - { isUpgrade: true, version: "2.0" }, - ]; - - yield check_installed(conditions); - - yield promiseShutdownManager(); -}); - -// Missing add-on should revert to the default set -add_task(function* test_revert() { - manuallyUninstall(updatesDir, "system2@tests.mozilla.org"); - - // With the add-on physically gone from disk we won't see uninstall events - BootstrapMonitor.clear("system2@tests.mozilla.org"); - - startupManager(false); - - // With system add-on 2 gone the updated set is now invalid so it reverts to - // the default set which is system add-ons 1 and 2. - let conditions = [ - { isUpgrade: false, version: "1.0" }, - { isUpgrade: false, version: "1.0" }, - { isUpgrade: false, version: null }, - ]; - - yield check_installed(conditions); - - yield promiseShutdownManager(); -}); - -// Putting it back will make the set work again -add_task(function* test_reuse() { - let file = do_get_file("data/system_addons/system2_2.xpi"); - file.copyTo(updatesDir, "system2@tests.mozilla.org.xpi"); - - startupManager(false); - - let conditions = [ - { isUpgrade: false, version: "1.0" }, - { isUpgrade: true, version: "2.0" }, - { isUpgrade: true, version: "2.0" }, - ]; - - yield check_installed(conditions); - - yield promiseShutdownManager(); -}); - -// Making the pref corrupt should revert to the default set -add_task(function* test_corrupt_pref() { - Services.prefs.setCharPref(PREF_SYSTEM_ADDON_SET, "foo"); - - startupManager(false); - - let conditions = [ - { isUpgrade: false, version: "1.0" }, - { isUpgrade: false, version: "1.0" }, - { isUpgrade: false, version: null }, - ]; - - yield check_installed(conditions); - - yield promiseShutdownManager(); -}); - -// An add-on with a bad certificate should cause us to use the default set -add_task(function* test_bad_profile_cert() { - let file = do_get_file("data/system_addons/system1_1_badcert.xpi"); - file.copyTo(updatesDir, "system1@tests.mozilla.org.xpi"); - - // Inject it into the system set - let addonSet = { - schema: 1, - directory: updatesDir.leafName, - addons: { - "system1@tests.mozilla.org": { - version: "2.0" - }, - "system2@tests.mozilla.org": { - version: "1.0" - }, - "system3@tests.mozilla.org": { - version: "1.0" - }, - } - }; - Services.prefs.setCharPref(PREF_SYSTEM_ADDON_SET, JSON.stringify(addonSet)); - - startupManager(false); - - let conditions = [ - { isUpgrade: false, version: "1.0" }, - { isUpgrade: false, version: "1.0" }, - { isUpgrade: false, version: null }, - ]; - - yield check_installed(conditions); - - yield promiseShutdownManager(); -}); - -// Switching to app defaults that contain a bad certificate should still work -add_task(function* test_bad_app_cert() { - gAppInfo.version = "3"; - distroDir.leafName = "app3"; - startupManager(); - - // Add-on will still be present - let addon = yield promiseAddonByID("system1@tests.mozilla.org"); - do_check_neq(addon, null); - do_check_eq(addon.signedState, AddonManager.SIGNEDSTATE_NOT_REQUIRED); - - let conditions = [ - { isUpgrade: false, version: "1.0" }, - { isUpgrade: false, version: null }, - { isUpgrade: false, version: "1.0" }, - ]; - - yield check_installed(conditions); - - yield promiseShutdownManager(); -}); - -// A failed upgrade should revert to the default set. -add_task(function* test_updated() { - // Create a random dir to install into - let dirname = makeUUID(); - FileUtils.getDir("ProfD", ["features", dirname], true); - updatesDir.append(dirname); - - // Copy in the system add-ons - let file = do_get_file("data/system_addons/system2_2.xpi"); - file.copyTo(updatesDir, "system2@tests.mozilla.org.xpi"); - file = do_get_file("data/system_addons/system_failed_update.xpi"); - file.copyTo(updatesDir, "system_failed_update@tests.mozilla.org.xpi"); - - // Inject it into the system set - let addonSet = { - schema: 1, - directory: updatesDir.leafName, - addons: { - "system2@tests.mozilla.org": { - version: "2.0" - }, - "system_failed_update@tests.mozilla.org": { - version: "1.0" - }, - } - }; - Services.prefs.setCharPref(PREF_SYSTEM_ADDON_SET, JSON.stringify(addonSet)); - - startupManager(false); - - let conditions = [ - { isUpgrade: false, version: "1.0" }, - ]; - - yield check_installed(conditions); - - yield promiseShutdownManager(); -}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_system_update.js b/toolkit/mozapps/extensions/test/xpcshell/test_system_update.js deleted file mode 100644 index c8e314427..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_system_update.js +++ /dev/null @@ -1,788 +0,0 @@ -// Tests that we reset to the default system add-ons correctly when switching -// application versions -const PREF_SYSTEM_ADDON_SET = "extensions.systemAddonSet"; -const PREF_SYSTEM_ADDON_UPDATE_URL = "extensions.systemAddon.update.url"; -const PREF_XPI_STATE = "extensions.xpiState"; -const PREF_APP_UPDATE_ENABLED = "app.update.enabled"; - -Components.utils.import("resource://testing-common/httpd.js"); -const { computeHash } = Components.utils.import("resource://gre/modules/addons/ProductAddonChecker.jsm"); - -BootstrapMonitor.init(); - -const updatesDir = FileUtils.getDir("ProfD", ["features"], false); - -function getCurrentUpdatesDir() { - let dir = updatesDir.clone(); - let set = JSON.parse(Services.prefs.getCharPref(PREF_SYSTEM_ADDON_SET)); - dir.append(set.directory); - return dir; -} - -function clearUpdatesDir() { - // Delete any existing directories - if (updatesDir.exists()) - updatesDir.remove(true); - - Services.prefs.clearUserPref(PREF_SYSTEM_ADDON_SET); -} - -function buildPrefilledUpdatesDir() { - clearUpdatesDir(); - - // Build the test set - let dir = FileUtils.getDir("ProfD", ["features", "prefilled"], true); - - do_get_file("data/system_addons/system2_2.xpi").copyTo(dir, "system2@tests.mozilla.org.xpi"); - do_get_file("data/system_addons/system3_2.xpi").copyTo(dir, "system3@tests.mozilla.org.xpi"); - - // Mark these in the past so the startup file scan notices when files have changed properly - FileUtils.getFile("ProfD", ["features", "prefilled", "system2@tests.mozilla.org.xpi"]).lastModifiedTime -= 10000; - FileUtils.getFile("ProfD", ["features", "prefilled", "system3@tests.mozilla.org.xpi"]).lastModifiedTime -= 10000; - - Services.prefs.setCharPref(PREF_SYSTEM_ADDON_SET, JSON.stringify({ - schema: 1, - directory: dir.leafName, - addons: { - "system2@tests.mozilla.org": { - version: "2.0" - }, - "system3@tests.mozilla.org": { - version: "2.0" - }, - } - })); -} - -let dir = FileUtils.getDir("ProfD", ["sysfeatures", "hidden"], true); -do_get_file("data/system_addons/system1_1.xpi").copyTo(dir, "system1@tests.mozilla.org.xpi"); -do_get_file("data/system_addons/system2_1.xpi").copyTo(dir, "system2@tests.mozilla.org.xpi"); - -dir = FileUtils.getDir("ProfD", ["sysfeatures", "prefilled"], true); -do_get_file("data/system_addons/system2_2.xpi").copyTo(dir, "system2@tests.mozilla.org.xpi"); -do_get_file("data/system_addons/system3_2.xpi").copyTo(dir, "system3@tests.mozilla.org.xpi"); - -const distroDir = FileUtils.getDir("ProfD", ["sysfeatures", "empty"], true); -registerDirectory("XREAppFeat", distroDir); - -createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2"); - -var testserver = new HttpServer(); -testserver.registerDirectory("/data/", do_get_file("data/system_addons")); -testserver.start(); -var root = testserver.identity.primaryScheme + "://" + - testserver.identity.primaryHost + ":" + - testserver.identity.primaryPort + "/data/" -Services.prefs.setCharPref(PREF_SYSTEM_ADDON_UPDATE_URL, root + "update.xml"); - -function makeUUID() { - let uuidGen = AM_Cc["@mozilla.org/uuid-generator;1"]. - getService(AM_Ci.nsIUUIDGenerator); - return uuidGen.generateUUID().toString(); -} - -function* check_installed(conditions) { - for (let i = 0; i < conditions.length; i++) { - let condition = conditions[i]; - let id = "system" + (i + 1) + "@tests.mozilla.org"; - let addon = yield promiseAddonByID(id); - - if (!("isUpgrade" in condition) || !("version" in condition)) { - throw Error("condition must contain isUpgrade and version"); - } - let isUpgrade = conditions[i].isUpgrade; - let version = conditions[i].version; - - let expectedDir = isUpgrade ? getCurrentUpdatesDir() : distroDir; - - if (version) { - do_print(`Checking state of add-on ${id}, expecting version ${version}`); - - // Add-on should be installed - do_check_neq(addon, null); - do_check_eq(addon.version, version); - do_check_true(addon.isActive); - do_check_false(addon.foreignInstall); - do_check_true(addon.hidden); - do_check_true(addon.isSystem); - - // Verify the add-ons file is in the right place - let file = expectedDir.clone(); - file.append(id + ".xpi"); - do_check_true(file.exists()); - do_check_true(file.isFile()); - - let uri = addon.getResourceURI(null); - do_check_true(uri instanceof AM_Ci.nsIFileURL); - do_check_eq(uri.file.path, file.path); - - if (isUpgrade) { - do_check_eq(addon.signedState, AddonManager.SIGNEDSTATE_SYSTEM); - } - - // Verify the add-on actually started - BootstrapMonitor.checkAddonStarted(id, version); - } - else { - do_print(`Checking state of add-on ${id}, expecting it to be missing`); - - if (isUpgrade) { - // Add-on should not be installed - do_check_eq(addon, null); - } - - BootstrapMonitor.checkAddonNotStarted(id); - - if (addon) - BootstrapMonitor.checkAddonInstalled(id); - else - BootstrapMonitor.checkAddonNotInstalled(id); - } - } -} - - -/** - * Defines the set of initial conditions to run each test against. Each should - * define the following properties: - * - * setup: A task to setup the profile into the initial state. - * initialState: The initial expected system add-on state after setup has run. - */ -const TEST_CONDITIONS = { - // Runs tests with no updated or default system add-ons initially installed - blank: { - setup: function*() { - clearUpdatesDir(); - distroDir.leafName = "empty"; - }, - initialState: [ - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null} - ], - }, - // Runs tests with default system add-ons installed - withAppSet: { - setup: function*() { - clearUpdatesDir(); - distroDir.leafName = "prefilled"; - }, - initialState: [ - { isUpgrade: false, version: null}, - { isUpgrade: false, version: "2.0"}, - { isUpgrade: false, version: "2.0"}, - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null} - ] - }, - - // Runs tests with updated system add-ons installed - withProfileSet: { - setup: function*() { - buildPrefilledUpdatesDir(); - distroDir.leafName = "empty"; - }, - initialState: [ - { isUpgrade: false, version: null}, - { isUpgrade: true, version: "2.0"}, - { isUpgrade: true, version: "2.0"}, - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null} - ] - }, - - // Runs tests with both default and updated system add-ons installed - withBothSets: { - setup: function*() { - buildPrefilledUpdatesDir(); - distroDir.leafName = "hidden"; - }, - initialState: [ - { isUpgrade: false, version: "1.0"}, - { isUpgrade: true, version: "2.0"}, - { isUpgrade: true, version: "2.0"}, - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null} - ] - }, -}; - - -/** - * The tests to run. Each test must define an updateList or test. The following - * properties are used: - * - * updateList: The set of add-ons the server should respond with. - * test: A function to run to perform the update check (replaces - * updateList) - * fails: An optional property, if true the update check is expected to - * fail. - * finalState: An optional property, the expected final state of system add-ons, - * if missing the test condition's initialState is used. - */ -const TESTS = { - // Test that a blank response does nothing - blank: { - updateList: null, - }, - - // Test that an empty list removes existing updates, leaving defaults. - empty: { - updateList: [], - finalState: { - blank: [ - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null} - ], - withAppSet: [ - { isUpgrade: false, version: null}, - { isUpgrade: false, version: "2.0"}, - { isUpgrade: false, version: "2.0"}, - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null} - ], - withProfileSet: [ - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null} - ], - withBothSets: [ - { isUpgrade: false, version: "1.0"}, - { isUpgrade: false, version: "1.0"}, - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null}, - // Set this to `true` to so `verify_state()` expects a blank profile dir - { isUpgrade: true, version: null} - ] - }, - }, - // Tests that a new set of system add-ons gets installed - newset: { - updateList: [ - { id: "system4@tests.mozilla.org", version: "1.0", path: "system4_1.xpi" }, - { id: "system5@tests.mozilla.org", version: "1.0", path: "system5_1.xpi" } - ], - finalState: { - blank: [ - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null}, - { isUpgrade: true, version: "1.0"}, - { isUpgrade: true, version: "1.0"} - ], - withAppSet: [ - { isUpgrade: false, version: null}, - { isUpgrade: false, version: "2.0"}, - { isUpgrade: false, version: "2.0"}, - { isUpgrade: true, version: "1.0"}, - { isUpgrade: true, version: "1.0"} - ], - withProfileSet: [ - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null}, - { isUpgrade: true, version: "1.0"}, - { isUpgrade: true, version: "1.0"} - ], - withBothSets: [ - { isUpgrade: false, version: "1.0"}, - { isUpgrade: false, version: "1.0"}, - { isUpgrade: false, version: null}, - { isUpgrade: true, version: "1.0"}, - { isUpgrade: true, version: "1.0"} - ] - } - }, - - // Tests that an upgraded set of system add-ons gets installed - upgrades: { - updateList: [ - { id: "system2@tests.mozilla.org", version: "3.0", path: "system2_3.xpi" }, - { id: "system3@tests.mozilla.org", version: "3.0", path: "system3_3.xpi" } - ], - finalState: { - blank: [ - { isUpgrade: false, version: null}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null} - ], - withAppSet: [ - { isUpgrade: false, version: null}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null} - ], - withProfileSet: [ - { isUpgrade: false, version: null}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null} - ], - withBothSets: [ - { isUpgrade: false, version: "1.0"}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null} - ] - } - }, - - // Tests that a set of system add-ons, some new, some existing gets installed - overlapping: { - updateList: [ - { id: "system1@tests.mozilla.org", version: "2.0", path: "system1_2.xpi" }, - { id: "system2@tests.mozilla.org", version: "2.0", path: "system2_2.xpi" }, - { id: "system3@tests.mozilla.org", version: "3.0", path: "system3_3.xpi" }, - { id: "system4@tests.mozilla.org", version: "1.0", path: "system4_1.xpi" } - ], - finalState: { - blank: [ - { isUpgrade: true, version: "2.0"}, - { isUpgrade: true, version: "2.0"}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: true, version: "1.0"}, - { isUpgrade: false, version: null} - ], - withAppSet: [ - { isUpgrade: true, version: "2.0"}, - { isUpgrade: true, version: "2.0"}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: true, version: "1.0"}, - { isUpgrade: false, version: null} - ], - withProfileSet: [ - { isUpgrade: true, version: "2.0"}, - { isUpgrade: true, version: "2.0"}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: true, version: "1.0"}, - { isUpgrade: false, version: null} - ], - withBothSets: [ - { isUpgrade: true, version: "2.0"}, - { isUpgrade: true, version: "2.0"}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: true, version: "1.0"}, - { isUpgrade: false, version: null} - ] - } - }, - - // Specifying an incorrect version should stop us updating anything - badVersion: { - fails: true, - updateList: [ - { id: "system2@tests.mozilla.org", version: "4.0", path: "system2_3.xpi" }, - { id: "system3@tests.mozilla.org", version: "3.0", path: "system3_3.xpi" } - ], - }, - - // Specifying an invalid size should stop us updating anything - badSize: { - fails: true, - updateList: [ - { id: "system2@tests.mozilla.org", version: "3.0", path: "system2_3.xpi", size: 2 }, - { id: "system3@tests.mozilla.org", version: "3.0", path: "system3_3.xpi" } - ], - }, - - // Specifying an incorrect hash should stop us updating anything - badHash: { - fails: true, - updateList: [ - { id: "system2@tests.mozilla.org", version: "3.0", path: "system2_3.xpi" }, - { id: "system3@tests.mozilla.org", version: "3.0", path: "system3_3.xpi", hashFunction: "sha1", hashValue: "205a4c49bd513ebd30594e380c19e86bba1f83e2" } - ], - }, - - // Correct sizes and hashes should work - checkSizeHash: { - updateList: [ - { id: "system2@tests.mozilla.org", version: "3.0", path: "system2_3.xpi", size: 4697 }, - { id: "system3@tests.mozilla.org", version: "3.0", path: "system3_3.xpi", hashFunction: "sha1", hashValue: "a4c7198d56deb315511c02937fd96c696de6cb84" }, - { id: "system5@tests.mozilla.org", version: "1.0", path: "system5_1.xpi", size: 4691, hashFunction: "sha1", hashValue: "6887b916a1a9a5338b0df4181f6187f5396861eb" } - ], - finalState: { - blank: [ - { isUpgrade: false, version: null}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: false, version: null}, - { isUpgrade: true, version: "1.0"} - ], - withAppSet: [ - { isUpgrade: false, version: null}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: false, version: null}, - { isUpgrade: true, version: "1.0"} - ], - withProfileSet: [ - { isUpgrade: false, version: null}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: false, version: null}, - { isUpgrade: true, version: "1.0"} - ], - withBothSets: [ - { isUpgrade: false, version: "1.0"}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: false, version: null}, - { isUpgrade: true, version: "1.0"} - ] - } - }, - - // A bad certificate should stop updates - badCert: { - fails: true, - updateList: [ - { id: "system1@tests.mozilla.org", version: "1.0", path: "system1_1_badcert.xpi" }, - { id: "system3@tests.mozilla.org", version: "1.0", path: "system3_1.xpi" } - ], - }, - - // An unpacked add-on should stop updates. - notPacked: { - fails: true, - updateList: [ - { id: "system6@tests.mozilla.org", version: "1.0", path: "system6_1_unpack.xpi" }, - { id: "system3@tests.mozilla.org", version: "1.0", path: "system3_1.xpi" } - ], - }, - - // A non-bootstrap add-on should stop updates. - notBootstrap: { - fails: true, - updateList: [ - { id: "system6@tests.mozilla.org", version: "1.0", path: "system6_2_notBootstrap.xpi" }, - { id: "system3@tests.mozilla.org", version: "1.0", path: "system3_1.xpi" } - ], - }, - - // A non-multiprocess add-on should stop updates. - notMultiprocess: { - fails: true, - updateList: [ - { id: "system6@tests.mozilla.org", version: "1.0", path: "system6_3_notMultiprocess.xpi" }, - { id: "system3@tests.mozilla.org", version: "1.0", path: "system3_1.xpi" } - ], - } -} - -add_task(function* setup() { - // Initialise the profile - startupManager(); - yield promiseShutdownManager(); -}) - -function* get_directories() { - let subdirs = []; - - if (yield OS.File.exists(updatesDir.path)) { - let iterator = new OS.File.DirectoryIterator(updatesDir.path); - yield iterator.forEach(entry => { - if (entry.isDir) { - subdirs.push(entry); - } - }); - iterator.close(); - } - - return subdirs; -} - -function* setup_conditions(setup) { - do_print("Clearing existing database."); - Services.prefs.clearUserPref(PREF_SYSTEM_ADDON_SET); - distroDir.leafName = "empty"; - startupManager(false); - yield promiseShutdownManager(); - - do_print("Setting up conditions."); - yield setup.setup(); - - startupManager(false); - - // Make sure the initial state is correct - do_print("Checking initial state."); - yield check_installed(setup.initialState); -} - -function* verify_state(initialState, finalState = undefined, alreadyUpgraded = false) { - let expectedDirs = 0; - - // If the initial state was using the profile set then that directory will - // still exist. - - if (initialState.some(a => a.isUpgrade)) { - expectedDirs++; - } - - if (finalState == undefined) { - finalState = initialState; - } - else if (finalState.some(a => a.isUpgrade)) { - // If the new state is using the profile then that directory will exist. - expectedDirs++; - } - - // Since upgrades are restartless now, the previous update dir hasn't been removed. - if (alreadyUpgraded) { - expectedDirs++; - } - - do_print("Checking final state."); - - let dirs = yield get_directories(); - do_check_eq(dirs.length, expectedDirs); - - yield check_installed(...finalState); - - // Check that the new state is active after a restart - yield promiseRestartManager(); - yield check_installed(finalState); -} - -function* exec_test(setupName, testName) { - let setup = TEST_CONDITIONS[setupName]; - let test = TESTS[testName]; - - yield setup_conditions(setup); - - try { - if ("test" in test) { - yield test.test(); - } - else { - yield installSystemAddons(yield buildSystemAddonUpdates(test.updateList, root), testserver); - } - - if (test.fails) { - do_throw("Expected this test to fail"); - } - } - catch (e) { - if (!test.fails) { - do_throw(e); - } - } - - // some tests have a different expected combination of default - // and updated add-ons. - if (test.finalState && setupName in test.finalState) { - yield verify_state(setup.initialState, test.finalState[setupName]); - } - else { - yield verify_state(setup.initialState, test.finalState); - } - - yield promiseShutdownManager(); -} - -add_task(function*() { - for (let setup of Object.keys(TEST_CONDITIONS)) { - for (let test of Object.keys(TESTS)) { - do_print("Running test " + setup + " " + test); - - yield exec_test(setup, test); - } - } -}); - -// Some custom tests -// Test that the update check is performed as part of the regular add-on update -// check -add_task(function* test_addon_update() { - yield setup_conditions(TEST_CONDITIONS.blank); - - yield updateAllSystemAddons(yield buildSystemAddonUpdates([ - { id: "system2@tests.mozilla.org", version: "2.0", path: "system2_2.xpi" }, - { id: "system3@tests.mozilla.org", version: "2.0", path: "system3_2.xpi" } - ], root), testserver); - - yield verify_state(TEST_CONDITIONS.blank.initialState, [ - {isUpgrade: false, version: null}, - {isUpgrade: true, version: "2.0"}, - {isUpgrade: true, version: "2.0"}, - {isUpgrade: false, version: null}, - {isUpgrade: false, version: null} - ]); - - yield promiseShutdownManager(); -}); - -// Disabling app updates should block system add-on updates -add_task(function* test_app_update_disabled() { - yield setup_conditions(TEST_CONDITIONS.blank); - - Services.prefs.setBoolPref(PREF_APP_UPDATE_ENABLED, false); - yield updateAllSystemAddons(yield buildSystemAddonUpdates([ - { id: "system2@tests.mozilla.org", version: "2.0", path: "system2_2.xpi" }, - { id: "system3@tests.mozilla.org", version: "2.0", path: "system3_2.xpi" } - ], root), testserver); - Services.prefs.clearUserPref(PREF_APP_UPDATE_ENABLED); - - yield verify_state(TEST_CONDITIONS.blank.initialState); - - yield promiseShutdownManager(); -}); - -// Safe mode should block system add-on updates -add_task(function* test_safe_mode() { - gAppInfo.inSafeMode = true; - - yield setup_conditions(TEST_CONDITIONS.blank); - - Services.prefs.setBoolPref(PREF_APP_UPDATE_ENABLED, false); - yield updateAllSystemAddons(yield buildSystemAddonUpdates([ - { id: "system2@tests.mozilla.org", version: "2.0", path: "system2_2.xpi" }, - { id: "system3@tests.mozilla.org", version: "2.0", path: "system3_2.xpi" } - ], root), testserver); - Services.prefs.clearUserPref(PREF_APP_UPDATE_ENABLED); - - yield verify_state(TEST_CONDITIONS.blank.initialState); - - yield promiseShutdownManager(); - - gAppInfo.inSafeMode = false; -}); - -// Tests that a set that matches the default set does nothing -add_task(function* test_match_default() { - yield setup_conditions(TEST_CONDITIONS.withAppSet); - - yield installSystemAddons(yield buildSystemAddonUpdates([ - { id: "system2@tests.mozilla.org", version: "2.0", path: "system2_2.xpi" }, - { id: "system3@tests.mozilla.org", version: "2.0", path: "system3_2.xpi" } - ], root), testserver); - - // Shouldn't have installed an updated set - yield verify_state(TEST_CONDITIONS.withAppSet.initialState); - - yield promiseShutdownManager(); -}); - -// Tests that a set that matches the hidden default set works -add_task(function* test_match_default_revert() { - yield setup_conditions(TEST_CONDITIONS.withBothSets); - - yield installSystemAddons(yield buildSystemAddonUpdates([ - { id: "system1@tests.mozilla.org", version: "1.0", path: "system1_1.xpi" }, - { id: "system2@tests.mozilla.org", version: "1.0", path: "system2_1.xpi" } - ], root), testserver); - - // This should revert to the default set instead of installing new versions - // into an updated set. - yield verify_state(TEST_CONDITIONS.withBothSets.initialState, [ - {isUpgrade: false, version: "1.0"}, - {isUpgrade: false, version: "1.0"}, - {isUpgrade: false, version: null}, - {isUpgrade: false, version: null}, - {isUpgrade: false, version: null} - ]); - - yield promiseShutdownManager(); -}); - -// Tests that a set that matches the current set works -add_task(function* test_match_current() { - yield setup_conditions(TEST_CONDITIONS.withBothSets); - - yield installSystemAddons(yield buildSystemAddonUpdates([ - { id: "system2@tests.mozilla.org", version: "2.0", path: "system2_2.xpi" }, - { id: "system3@tests.mozilla.org", version: "2.0", path: "system3_2.xpi" } - ], root), testserver); - - // This should remain with the current set instead of creating a new copy - let set = JSON.parse(Services.prefs.getCharPref(PREF_SYSTEM_ADDON_SET)); - do_check_eq(set.directory, "prefilled"); - - yield verify_state(TEST_CONDITIONS.withBothSets.initialState); - - yield promiseShutdownManager(); -}); - -// Tests that a set with a minor change doesn't re-download existing files -add_task(function* test_no_download() { - yield setup_conditions(TEST_CONDITIONS.withBothSets); - - // The missing file here is unneeded since there is a local version already - yield installSystemAddons(yield buildSystemAddonUpdates([ - { id: "system2@tests.mozilla.org", version: "2.0", path: "missing.xpi" }, - { id: "system4@tests.mozilla.org", version: "1.0", path: "system4_1.xpi" } - ], root), testserver); - - yield verify_state(TEST_CONDITIONS.withBothSets.initialState, [ - {isUpgrade: false, version: "1.0"}, - {isUpgrade: true, version: "2.0"}, - {isUpgrade: false, version: null}, - {isUpgrade: true, version: "1.0"}, - {isUpgrade: false, version: null} - ]); - - yield promiseShutdownManager(); -}); - -// Tests that a second update before a restart works -add_task(function* test_double_update() { - yield setup_conditions(TEST_CONDITIONS.withAppSet); - - yield installSystemAddons(yield buildSystemAddonUpdates([ - { id: "system2@tests.mozilla.org", version: "2.0", path: "system2_2.xpi" }, - { id: "system3@tests.mozilla.org", version: "1.0", path: "system3_1.xpi" } - ], root), testserver); - - yield installSystemAddons(yield buildSystemAddonUpdates([ - { id: "system3@tests.mozilla.org", version: "2.0", path: "system3_2.xpi" }, - { id: "system4@tests.mozilla.org", version: "1.0", path: "system4_1.xpi" } - ], root), testserver); - - yield verify_state(TEST_CONDITIONS.withAppSet.initialState, [ - {isUpgrade: false, version: null}, - {isUpgrade: false, version: "2.0"}, - {isUpgrade: true, version: "2.0"}, - {isUpgrade: true, version: "1.0"}, - {isUpgrade: false, version: null} - ], true); - - yield promiseShutdownManager(); -}); - -// A second update after a restart will delete the original unused set -add_task(function* test_update_purges() { - yield setup_conditions(TEST_CONDITIONS.withBothSets); - - yield installSystemAddons(yield buildSystemAddonUpdates([ - { id: "system2@tests.mozilla.org", version: "2.0", path: "system2_2.xpi" }, - { id: "system3@tests.mozilla.org", version: "1.0", path: "system3_1.xpi" } - ], root), testserver); - - yield verify_state(TEST_CONDITIONS.withBothSets.initialState, [ - {isUpgrade: false, version: "1.0"}, - {isUpgrade: true, version: "2.0"}, - {isUpgrade: true, version: "1.0"}, - {isUpgrade: false, version: null}, - {isUpgrade: false, version: null} - ]); - - yield installSystemAddons(yield buildSystemAddonUpdates(null), testserver); - - let dirs = yield get_directories(); - do_check_eq(dirs.length, 1); - - yield promiseShutdownManager(); -}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_temporary.js b/toolkit/mozapps/extensions/test/xpcshell/test_temporary.js deleted file mode 100644 index ec9e25a0b..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_temporary.js +++ /dev/null @@ -1,760 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -const ID = "bootstrap1@tests.mozilla.org"; -const sampleRDFManifest = { - id: ID, - version: "1.0", - bootstrap: true, - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "1", - maxVersion: "1" - }], - name: "Test Bootstrap 1 (temporary)", -}; - -createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "42"); -startupManager(); - -const {Management} = Components.utils.import("resource://gre/modules/Extension.jsm", {}); - -function promiseAddonStartup() { - return new Promise(resolve => { - let listener = (extension) => { - Management.off("startup", listener); - resolve(extension); - }; - - Management.on("startup", listener); - }); -} - -BootstrapMonitor.init(); - -// Partial list of bootstrap reasons from XPIProvider.jsm -const BOOTSTRAP_REASONS = { - ADDON_INSTALL: 5, - ADDON_UPGRADE: 7, - ADDON_DOWNGRADE: 8, -}; - -function waitForBootstrapEvent(expectedEvent, addonId) { - return new Promise(resolve => { - const observer = { - observe: (subject, topic, data) => { - const info = JSON.parse(data); - const targetAddonId = info.data.id; - if (targetAddonId === addonId && info.event === expectedEvent) { - resolve(info); - Services.obs.removeObserver(observer); - } else { - do_print( - `Ignoring bootstrap event: ${info.event} for ${targetAddonId}`); - } - }, - }; - Services.obs.addObserver(observer, "bootstrapmonitor-event", false); - }); -} - -// Install a temporary add-on with no existing add-on present. -// Restart and make sure it has gone away. -add_task(function*() { - let extInstallCalled = false; - AddonManager.addInstallListener({ - onExternalInstall: (aInstall) => { - do_check_eq(aInstall.id, ID); - do_check_eq(aInstall.version, "1.0"); - extInstallCalled = true; - }, - }); - - let installingCalled = false; - let installedCalled = false; - AddonManager.addAddonListener({ - onInstalling: (aInstall) => { - do_check_eq(aInstall.id, ID); - do_check_eq(aInstall.version, "1.0"); - installingCalled = true; - }, - onInstalled: (aInstall) => { - do_check_eq(aInstall.id, ID); - do_check_eq(aInstall.version, "1.0"); - installedCalled = true; - }, - onInstallStarted: (aInstall) => { - do_throw("onInstallStarted called unexpectedly"); - } - }); - - yield AddonManager.installTemporaryAddon(do_get_addon("test_bootstrap1_1")); - - do_check_true(extInstallCalled); - do_check_true(installingCalled); - do_check_true(installedCalled); - - const install = BootstrapMonitor.checkAddonInstalled(ID, "1.0"); - equal(install.reason, BOOTSTRAP_REASONS.ADDON_INSTALL); - BootstrapMonitor.checkAddonStarted(ID, "1.0"); - - let addon = yield promiseAddonByID(ID); - - do_check_neq(addon, null); - do_check_eq(addon.version, "1.0"); - do_check_eq(addon.name, "Test Bootstrap 1"); - do_check_true(addon.isCompatible); - do_check_false(addon.appDisabled); - do_check_true(addon.isActive); - do_check_eq(addon.type, "extension"); - do_check_eq(addon.signedState, mozinfo.addon_signing ? AddonManager.SIGNEDSTATE_SIGNED : AddonManager.SIGNEDSTATE_NOT_REQUIRED); - - yield promiseRestartManager(); - - BootstrapMonitor.checkAddonNotInstalled(ID); - BootstrapMonitor.checkAddonNotStarted(ID); - - addon = yield promiseAddonByID(ID); - do_check_eq(addon, null); - - yield promiseRestartManager(); -}); - -// Install a temporary add-on over the top of an existing add-on. -// Restart and make sure the existing add-on comes back. -add_task(function*() { - yield promiseInstallAllFiles([do_get_addon("test_bootstrap1_1")], true); - - BootstrapMonitor.checkAddonInstalled(ID, "1.0"); - BootstrapMonitor.checkAddonStarted(ID, "1.0"); - - let addon = yield promiseAddonByID(ID); - - do_check_neq(addon, null); - do_check_eq(addon.version, "1.0"); - do_check_eq(addon.name, "Test Bootstrap 1"); - do_check_true(addon.isCompatible); - do_check_false(addon.appDisabled); - do_check_true(addon.isActive); - do_check_eq(addon.type, "extension"); - do_check_eq(addon.signedState, mozinfo.addon_signing ? AddonManager.SIGNEDSTATE_SIGNED : AddonManager.SIGNEDSTATE_NOT_REQUIRED); - - let tempdir = gTmpD.clone(); - - // test that an unpacked add-on works too - writeInstallRDFToDir({ - id: ID, - version: "3.0", - bootstrap: true, - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "1", - maxVersion: "1" - }], - name: "Test Bootstrap 1 (temporary)", - }, tempdir, "bootstrap1@tests.mozilla.org", "bootstrap.js"); - - let unpacked_addon = tempdir.clone(); - unpacked_addon.append(ID); - do_get_file("data/test_temporary/bootstrap.js") - .copyTo(unpacked_addon, "bootstrap.js"); - - yield AddonManager.installTemporaryAddon(unpacked_addon); - - BootstrapMonitor.checkAddonInstalled(ID, "3.0"); - BootstrapMonitor.checkAddonStarted(ID, "3.0"); - - addon = yield promiseAddonByID(ID); - - // temporary add-on is installed and started - do_check_neq(addon, null); - do_check_eq(addon.version, "3.0"); - do_check_eq(addon.name, "Test Bootstrap 1 (temporary)"); - do_check_true(addon.isCompatible); - do_check_false(addon.appDisabled); - do_check_true(addon.isActive); - do_check_eq(addon.type, "extension"); - do_check_eq(addon.signedState, mozinfo.addon_signing ? AddonManager.SIGNEDSTATE_SIGNED : AddonManager.SIGNEDSTATE_NOT_REQUIRED); - - restartManager(); - - BootstrapMonitor.checkAddonInstalled(ID, "1.0"); - BootstrapMonitor.checkAddonStarted(ID, "1.0"); - - addon = yield promiseAddonByID(ID); - - // existing add-on is back - do_check_neq(addon, null); - do_check_eq(addon.version, "1.0"); - do_check_eq(addon.name, "Test Bootstrap 1"); - do_check_true(addon.isCompatible); - do_check_false(addon.appDisabled); - do_check_true(addon.isActive); - do_check_eq(addon.type, "extension"); - do_check_eq(addon.signedState, mozinfo.addon_signing ? AddonManager.SIGNEDSTATE_SIGNED : AddonManager.SIGNEDSTATE_NOT_REQUIRED); - - unpacked_addon.remove(true); - - // on Windows XPI files will be locked by the JAR cache, skip this test there. - if (!("nsIWindowsRegKey" in Components.interfaces)) { - // test that a packed (XPI) add-on works - writeInstallRDFToXPI({ - id: ID, - version: "2.0", - bootstrap: true, - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "1", - maxVersion: "1" - }], - name: "Test Bootstrap 1 (temporary)", - }, tempdir, "bootstrap1@tests.mozilla.org"); - - let packed_addon = tempdir.clone(); - packed_addon.append(ID + ".xpi"); - - yield AddonManager.installTemporaryAddon(packed_addon); - - addon = yield promiseAddonByID(ID); - - // temporary add-on is installed and started - do_check_neq(addon, null); - do_check_eq(addon.version, "2.0"); - do_check_eq(addon.name, "Test Bootstrap 1 (temporary)"); - do_check_true(addon.isCompatible); - do_check_false(addon.appDisabled); - do_check_true(addon.isActive); - do_check_eq(addon.type, "extension"); - do_check_eq(addon.signedState, mozinfo.addon_signing ? AddonManager.SIGNEDSTATE_SIGNED : AddonManager.SIGNEDSTATE_NOT_REQUIRED); - - restartManager(); - - BootstrapMonitor.checkAddonInstalled(ID, "1.0"); - BootstrapMonitor.checkAddonStarted(ID, "1.0"); - - addon = yield promiseAddonByID(ID); - - // existing add-on is back - do_check_neq(addon, null); - do_check_eq(addon.version, "1.0"); - do_check_eq(addon.name, "Test Bootstrap 1"); - do_check_true(addon.isCompatible); - do_check_false(addon.appDisabled); - do_check_true(addon.isActive); - do_check_eq(addon.type, "extension"); - do_check_eq(addon.signedState, mozinfo.addon_signing ? AddonManager.SIGNEDSTATE_SIGNED : AddonManager.SIGNEDSTATE_NOT_REQUIRED); - - packed_addon.remove(false); - - // test that a webextension works - let webext = createTempWebExtensionFile({ - manifest: { - version: "4.0", - name: "Test WebExtension 1 (temporary)", - applications: { - gecko: { - id: ID - } - } - } - }); - - yield Promise.all([ - AddonManager.installTemporaryAddon(webext), - promiseAddonStartup(), - ]); - addon = yield promiseAddonByID(ID); - - // temporary add-on is installed and started - do_check_neq(addon, null); - do_check_eq(addon.version, "4.0"); - do_check_eq(addon.name, "Test WebExtension 1 (temporary)"); - do_check_true(addon.isCompatible); - do_check_false(addon.appDisabled); - do_check_true(addon.isActive); - do_check_eq(addon.type, "extension"); - do_check_eq(addon.signedState, mozinfo.addon_signing ? AddonManager.SIGNEDSTATE_SIGNED : AddonManager.SIGNEDSTATE_NOT_REQUIRED); - - // test that re-loading a webextension works, using the same filename - webext.remove(false); - webext = createTempWebExtensionFile({ - manifest: { - version: "5.0", - name: "Test WebExtension 1 (temporary)", - applications: { - gecko: { - id: ID - } - } - } - }); - - yield Promise.all([ - AddonManager.installTemporaryAddon(webext), - promiseAddonStartup(), - ]); - addon = yield promiseAddonByID(ID); - - // temporary add-on is installed and started - do_check_neq(addon, null); - do_check_eq(addon.version, "5.0"); - do_check_eq(addon.name, "Test WebExtension 1 (temporary)"); - do_check_true(addon.isCompatible); - do_check_false(addon.appDisabled); - do_check_true(addon.isActive); - do_check_eq(addon.type, "extension"); - do_check_eq(addon.signedState, mozinfo.addon_signing ? AddonManager.SIGNEDSTATE_SIGNED : AddonManager.SIGNEDSTATE_NOT_REQUIRED); - - restartManager(); - - BootstrapMonitor.checkAddonInstalled(ID, "1.0"); - BootstrapMonitor.checkAddonStarted(ID, "1.0"); - - addon = yield promiseAddonByID(ID); - - // existing add-on is back - do_check_neq(addon, null); - do_check_eq(addon.version, "1.0"); - do_check_eq(addon.name, "Test Bootstrap 1"); - do_check_true(addon.isCompatible); - do_check_false(addon.appDisabled); - do_check_true(addon.isActive); - do_check_eq(addon.type, "extension"); - do_check_eq(addon.signedState, mozinfo.addon_signing ? AddonManager.SIGNEDSTATE_SIGNED : AddonManager.SIGNEDSTATE_NOT_REQUIRED); - } - - // remove original add-on - addon.uninstall(); - - BootstrapMonitor.checkAddonNotInstalled(ID); - BootstrapMonitor.checkAddonNotStarted(ID); - - yield promiseRestartManager(); -}); - -// Install a temporary add-on over the top of an existing add-on. -// Uninstall it and make sure the existing add-on comes back. -add_task(function*() { - yield promiseInstallAllFiles([do_get_addon("test_bootstrap1_1")], true); - - BootstrapMonitor.checkAddonInstalled(ID, "1.0"); - BootstrapMonitor.checkAddonStarted(ID, "1.0"); - - let tempdir = gTmpD.clone(); - writeInstallRDFToDir({ - id: ID, - version: "2.0", - bootstrap: true, - unpack: true, - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "1", - maxVersion: "1" - }], - name: "Test Bootstrap 1 (temporary)", - }, tempdir); - - let unpacked_addon = tempdir.clone(); - unpacked_addon.append(ID); - - let extInstallCalled = false; - AddonManager.addInstallListener({ - onExternalInstall: (aInstall) => { - do_check_eq(aInstall.id, ID); - do_check_eq(aInstall.version, "2.0"); - extInstallCalled = true; - }, - }); - - let installingCalled = false; - let installedCalled = false; - AddonManager.addAddonListener({ - onInstalling: (aInstall) => { - do_check_eq(aInstall.id, ID); - if (!installingCalled) - do_check_eq(aInstall.version, "2.0"); - installingCalled = true; - }, - onInstalled: (aInstall) => { - do_check_eq(aInstall.id, ID); - if (!installedCalled) - do_check_eq(aInstall.version, "2.0"); - installedCalled = true; - }, - onInstallStarted: (aInstall) => { - do_throw("onInstallStarted called unexpectedly"); - } - }); - - yield AddonManager.installTemporaryAddon(unpacked_addon); - - do_check_true(extInstallCalled); - do_check_true(installingCalled); - do_check_true(installedCalled); - - let addon = yield promiseAddonByID(ID); - - BootstrapMonitor.checkAddonNotInstalled(ID); - BootstrapMonitor.checkAddonNotStarted(ID); - - // temporary add-on is installed and started - do_check_neq(addon, null); - do_check_eq(addon.version, "2.0"); - do_check_eq(addon.name, "Test Bootstrap 1 (temporary)"); - do_check_true(addon.isCompatible); - do_check_false(addon.appDisabled); - do_check_true(addon.isActive); - do_check_eq(addon.type, "extension"); - do_check_eq(addon.signedState, mozinfo.addon_signing ? AddonManager.SIGNEDSTATE_SIGNED : AddonManager.SIGNEDSTATE_NOT_REQUIRED); - - addon.uninstall(); - - addon = yield promiseAddonByID(ID); - - BootstrapMonitor.checkAddonInstalled(ID); - BootstrapMonitor.checkAddonStarted(ID); - - // existing add-on is back - do_check_neq(addon, null); - do_check_eq(addon.version, "1.0"); - do_check_eq(addon.name, "Test Bootstrap 1"); - do_check_true(addon.isCompatible); - do_check_false(addon.appDisabled); - do_check_true(addon.isActive); - do_check_eq(addon.type, "extension"); - do_check_eq(addon.signedState, mozinfo.addon_signing ? AddonManager.SIGNEDSTATE_SIGNED : AddonManager.SIGNEDSTATE_NOT_REQUIRED); - - unpacked_addon.remove(true); - addon.uninstall(); - - BootstrapMonitor.checkAddonNotInstalled(ID); - BootstrapMonitor.checkAddonNotStarted(ID); - - yield promiseRestartManager(); -}); - -// Install a temporary add-on as a version upgrade over the top of an -// existing temporary add-on. -add_task(function*() { - const tempdir = gTmpD.clone(); - - writeInstallRDFToDir(sampleRDFManifest, tempdir, - "bootstrap1@tests.mozilla.org", "bootstrap.js"); - - const unpackedAddon = tempdir.clone(); - unpackedAddon.append(ID); - do_get_file("data/test_temporary/bootstrap.js") - .copyTo(unpackedAddon, "bootstrap.js"); - - yield AddonManager.installTemporaryAddon(unpackedAddon); - - // Increment the version number, re-install it, and make sure it - // gets marked as an upgrade. - writeInstallRDFToDir(Object.assign({}, sampleRDFManifest, { - version: "2.0" - }), tempdir, "bootstrap1@tests.mozilla.org"); - - const onUninstall = waitForBootstrapEvent("uninstall", ID); - const onInstall = waitForBootstrapEvent("install", ID); - yield AddonManager.installTemporaryAddon(unpackedAddon); - - const uninstall = yield onUninstall; - equal(uninstall.data.version, "1.0"); - equal(uninstall.reason, BOOTSTRAP_REASONS.ADDON_UPGRADE); - - const install = yield onInstall; - equal(install.data.version, "2.0"); - equal(install.reason, BOOTSTRAP_REASONS.ADDON_UPGRADE); - - const addon = yield promiseAddonByID(ID); - addon.uninstall(); - - unpackedAddon.remove(true); - yield promiseRestartManager(); -}); - -// Install a temporary add-on as a version downgrade over the top of an -// existing temporary add-on. -add_task(function*() { - const tempdir = gTmpD.clone(); - - writeInstallRDFToDir(sampleRDFManifest, tempdir, - "bootstrap1@tests.mozilla.org", "bootstrap.js"); - - const unpackedAddon = tempdir.clone(); - unpackedAddon.append(ID); - do_get_file("data/test_temporary/bootstrap.js") - .copyTo(unpackedAddon, "bootstrap.js"); - - yield AddonManager.installTemporaryAddon(unpackedAddon); - - // Decrement the version number, re-install, and make sure - // it gets marked as a downgrade. - writeInstallRDFToDir(Object.assign({}, sampleRDFManifest, { - version: "0.8" - }), tempdir, "bootstrap1@tests.mozilla.org"); - - const onUninstall = waitForBootstrapEvent("uninstall", ID); - const onInstall = waitForBootstrapEvent("install", ID); - yield AddonManager.installTemporaryAddon(unpackedAddon); - - const uninstall = yield onUninstall; - equal(uninstall.data.version, "1.0"); - equal(uninstall.reason, BOOTSTRAP_REASONS.ADDON_DOWNGRADE); - - const install = yield onInstall; - equal(install.data.version, "0.8"); - equal(install.reason, BOOTSTRAP_REASONS.ADDON_DOWNGRADE); - - const addon = yield promiseAddonByID(ID); - addon.uninstall(); - - unpackedAddon.remove(true); - yield promiseRestartManager(); -}); - -// Installing a temporary add-on over an existing add-on with the same -// version number should be installed as an upgrade. -add_task(function*() { - const tempdir = gTmpD.clone(); - - writeInstallRDFToDir(sampleRDFManifest, tempdir, - "bootstrap1@tests.mozilla.org", "bootstrap.js"); - - const unpackedAddon = tempdir.clone(); - unpackedAddon.append(ID); - do_get_file("data/test_temporary/bootstrap.js") - .copyTo(unpackedAddon, "bootstrap.js"); - - const onInitialInstall = waitForBootstrapEvent("install", ID); - yield AddonManager.installTemporaryAddon(unpackedAddon); - - const initialInstall = yield onInitialInstall; - equal(initialInstall.data.version, "1.0"); - equal(initialInstall.reason, BOOTSTRAP_REASONS.ADDON_INSTALL); - - // Install it again. - const onUninstall = waitForBootstrapEvent("uninstall", ID); - const onInstall = waitForBootstrapEvent("install", ID); - yield AddonManager.installTemporaryAddon(unpackedAddon); - - const uninstall = yield onUninstall; - equal(uninstall.data.version, "1.0"); - equal(uninstall.reason, BOOTSTRAP_REASONS.ADDON_UPGRADE); - - const reInstall = yield onInstall; - equal(reInstall.data.version, "1.0"); - equal(reInstall.reason, BOOTSTRAP_REASONS.ADDON_UPGRADE); - - const addon = yield promiseAddonByID(ID); - addon.uninstall(); - - unpackedAddon.remove(true); - yield promiseRestartManager(); -}); - -// Install a temporary add-on over the top of an existing disabled add-on. -// After restart, the existing add-on should continue to be installed and disabled. -add_task(function*() { - yield promiseInstallAllFiles([do_get_addon("test_bootstrap1_1")], true); - - BootstrapMonitor.checkAddonInstalled(ID, "1.0"); - BootstrapMonitor.checkAddonStarted(ID, "1.0"); - - let addon = yield promiseAddonByID(ID); - - addon.userDisabled = true; - - BootstrapMonitor.checkAddonInstalled(ID, "1.0"); - BootstrapMonitor.checkAddonNotStarted(ID); - - let tempdir = gTmpD.clone(); - writeInstallRDFToDir({ - id: ID, - version: "2.0", - bootstrap: true, - unpack: true, - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "1", - maxVersion: "1" - }], - name: "Test Bootstrap 1 (temporary)", - }, tempdir, "bootstrap1@tests.mozilla.org", "bootstrap.js"); - - let unpacked_addon = tempdir.clone(); - unpacked_addon.append(ID); - do_get_file("data/test_temporary/bootstrap.js") - .copyTo(unpacked_addon, "bootstrap.js"); - - let extInstallCalled = false; - AddonManager.addInstallListener({ - onExternalInstall: (aInstall) => { - do_check_eq(aInstall.id, ID); - do_check_eq(aInstall.version, "2.0"); - extInstallCalled = true; - }, - }); - - yield AddonManager.installTemporaryAddon(unpacked_addon); - - do_check_true(extInstallCalled); - - let tempAddon = yield promiseAddonByID(ID); - - BootstrapMonitor.checkAddonInstalled(ID, "2.0"); - BootstrapMonitor.checkAddonStarted(ID); - - // temporary add-on is installed and started - do_check_neq(tempAddon, null); - do_check_eq(tempAddon.version, "2.0"); - do_check_eq(tempAddon.name, "Test Bootstrap 1 (temporary)"); - do_check_true(tempAddon.isCompatible); - do_check_false(tempAddon.appDisabled); - do_check_true(tempAddon.isActive); - do_check_eq(tempAddon.type, "extension"); - do_check_eq(tempAddon.signedState, mozinfo.addon_signing ? AddonManager.SIGNEDSTATE_SIGNED : AddonManager.SIGNEDSTATE_NOT_REQUIRED); - - tempAddon.uninstall(); - unpacked_addon.remove(true); - - addon.userDisabled = false; - addon = yield promiseAddonByID(ID); - - BootstrapMonitor.checkAddonInstalled(ID, "1.0"); - BootstrapMonitor.checkAddonStarted(ID); - - // existing add-on is back - do_check_neq(addon, null); - do_check_eq(addon.version, "1.0"); - do_check_eq(addon.name, "Test Bootstrap 1"); - do_check_true(addon.isCompatible); - do_check_false(addon.appDisabled); - do_check_true(addon.isActive); - do_check_eq(addon.type, "extension"); - do_check_eq(addon.signedState, mozinfo.addon_signing ? AddonManager.SIGNEDSTATE_SIGNED : AddonManager.SIGNEDSTATE_NOT_REQUIRED); - - addon.uninstall(); - - BootstrapMonitor.checkAddonNotInstalled(ID); - BootstrapMonitor.checkAddonNotStarted(ID); - - yield promiseRestartManager(); -}); - -// Installing a temporary add-on over a non-restartless add-on should fail. -add_task(function*() { - yield promiseInstallAllFiles([do_get_addon("test_install1")], true); - - let non_restartless_ID = "addon1@tests.mozilla.org"; - - BootstrapMonitor.checkAddonNotInstalled(non_restartless_ID); - BootstrapMonitor.checkAddonNotStarted(non_restartless_ID); - - restartManager(); - - BootstrapMonitor.checkAddonNotInstalled(non_restartless_ID); - BootstrapMonitor.checkAddonNotStarted(non_restartless_ID); - - let addon = yield promiseAddonByID(non_restartless_ID); - - // non-restartless add-on is installed and started - do_check_neq(addon, null); - do_check_eq(addon.id, non_restartless_ID); - do_check_eq(addon.version, "1.0"); - do_check_eq(addon.name, "Test 1"); - do_check_true(addon.isCompatible); - do_check_false(addon.appDisabled); - do_check_true(addon.isActive); - do_check_eq(addon.type, "extension"); - do_check_eq(addon.signedState, mozinfo.addon_signing ? AddonManager.SIGNEDSTATE_SIGNED : AddonManager.SIGNEDSTATE_NOT_REQUIRED); - - let tempdir = gTmpD.clone(); - writeInstallRDFToDir({ - id: non_restartless_ID, - version: "2.0", - bootstrap: true, - unpack: true, - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "1", - maxVersion: "1" - }], - name: "Test 1 (temporary)", - }, tempdir); - - let unpacked_addon = tempdir.clone(); - unpacked_addon.append(non_restartless_ID); - - try { - yield AddonManager.installTemporaryAddon(unpacked_addon); - do_throw("Installing over a non-restartless add-on should return" - + " a rejected promise"); - } catch (err) { - do_check_eq(err.message, - "Non-restartless add-on with ID addon1@tests.mozilla.org is" - + " already installed"); - } - - unpacked_addon.remove(true); - addon.uninstall(); - - BootstrapMonitor.checkAddonNotInstalled(ID); - BootstrapMonitor.checkAddonNotStarted(ID); - - yield promiseRestartManager(); -}); - -// Installing a temporary add-on when there is already a temporary -// add-on should fail. -add_task(function*() { - yield AddonManager.installTemporaryAddon(do_get_addon("test_bootstrap1_1")); - - let addon = yield promiseAddonByID(ID); - - BootstrapMonitor.checkAddonInstalled(ID, "1.0"); - BootstrapMonitor.checkAddonStarted(ID, "1.0"); - - do_check_neq(addon, null); - do_check_eq(addon.version, "1.0"); - do_check_eq(addon.name, "Test Bootstrap 1"); - do_check_true(addon.isCompatible); - do_check_false(addon.appDisabled); - do_check_true(addon.isActive); - do_check_eq(addon.type, "extension"); - do_check_false(addon.isWebExtension); - do_check_eq(addon.signedState, mozinfo.addon_signing ? AddonManager.SIGNEDSTATE_SIGNED : AddonManager.SIGNEDSTATE_NOT_REQUIRED); - - yield AddonManager.installTemporaryAddon(do_get_addon("test_bootstrap1_1")); - - BootstrapMonitor.checkAddonInstalled(ID, "1.0"); - BootstrapMonitor.checkAddonStarted(ID, "1.0"); - - yield promiseRestartManager(); - - BootstrapMonitor.checkAddonNotInstalled(ID); - BootstrapMonitor.checkAddonNotStarted(ID); -}); - -// Check that a temporary add-on is marked as such. -add_task(function*() { - yield AddonManager.installTemporaryAddon(do_get_addon("test_bootstrap1_1")); - const addon = yield promiseAddonByID(ID); - - notEqual(addon, null); - equal(addon.temporarilyInstalled, true); - - yield promiseRestartManager(); -}); - -// Check that a permanent add-on is not marked as temporarily installed. -add_task(function*() { - yield promiseInstallAllFiles([do_get_addon("test_bootstrap1_1")], true); - const addon = yield promiseAddonByID(ID); - - notEqual(addon, null); - equal(addon.temporarilyInstalled, false); - - yield promiseRestartManager(); -}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_theme.js b/toolkit/mozapps/extensions/test/xpcshell/test_theme.js index 84d6f1d0d..f201c776d 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_theme.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_theme.js @@ -95,12 +95,10 @@ function run_test() { do_check_neq(d, null); do_check_false(d.skinnable); do_check_false(d.foreignInstall); - do_check_eq(d.signedState, undefined); do_check_neq(t1, null); do_check_false(t1.userDisabled); do_check_false(t1.appDisabled); - do_check_eq(t1.signedState, undefined); do_check_true(t1.isActive); do_check_true(t1.skinnable); do_check_true(t1.foreignInstall); @@ -114,7 +112,6 @@ function run_test() { do_check_neq(t2, null); do_check_true(t2.userDisabled); do_check_false(t2.appDisabled); - do_check_eq(t2.signedState, undefined); do_check_false(t2.isActive); do_check_false(t2.skinnable); do_check_true(t2.foreignInstall); @@ -857,27 +854,27 @@ function run_test_15() { do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "theme1/1.0"); AddonManager.getAddonsByIDs(["default@tests.mozilla.org", "theme1@tests.mozilla.org"], - callback_soon(function([d_2, t1_2]) { - do_check_true(d_2.userDisabled); - do_check_false(d_2.appDisabled); - do_check_false(d_2.isActive); + callback_soon(function([d, t1]) { + do_check_true(d.userDisabled); + do_check_false(d.appDisabled); + do_check_false(d.isActive); - do_check_false(t1_2.userDisabled); - do_check_false(t1_2.appDisabled); - do_check_true(t1_2.isActive); + do_check_false(t1.userDisabled); + do_check_false(t1.appDisabled); + do_check_true(t1.isActive); restartManager("2"); do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "theme1/1.0"); AddonManager.getAddonsByIDs(["default@tests.mozilla.org", - "theme1@tests.mozilla.org"], function([d_3, t1_3]) { - do_check_true(d_3.userDisabled); - do_check_false(d_3.appDisabled); - do_check_false(d_3.isActive); + "theme1@tests.mozilla.org"], function([d, t1]) { + do_check_true(d.userDisabled); + do_check_false(d.appDisabled); + do_check_false(d.isActive); - do_check_false(t1_3.userDisabled); - do_check_false(t1_3.appDisabled); - do_check_true(t1_3.isActive); + do_check_false(t1.userDisabled); + do_check_false(t1.appDisabled); + do_check_true(t1.isActive); do_execute_soon(run_test_16); }); @@ -943,14 +940,14 @@ function run_test_18() { AddonManager.getAddonsByIDs(["default@tests.mozilla.org", "theme1@tests.mozilla.org"], - callback_soon(function([d_2, t1_2]) { - do_check_true(d_2.userDisabled); - do_check_false(d_2.appDisabled); - do_check_false(d_2.isActive); + callback_soon(function([d, t1]) { + do_check_true(d.userDisabled); + do_check_false(d.appDisabled); + do_check_false(d.isActive); - do_check_false(t1_2.userDisabled); - do_check_false(t1_2.appDisabled); - do_check_true(t1_2.isActive); + do_check_false(t1.userDisabled); + do_check_false(t1.appDisabled); + do_check_true(t1.isActive); prepare_test({ "theme1@tests.mozilla.org": [ @@ -960,28 +957,28 @@ function run_test_18() { "onEnabling", ] }); - t1_2.userDisabled = true; + t1.userDisabled = true; ensure_test_completed(); - do_check_false(d_2.userDisabled); - do_check_false(d_2.appDisabled); - do_check_false(d_2.isActive); + do_check_false(d.userDisabled); + do_check_false(d.appDisabled); + do_check_false(d.isActive); - do_check_true(t1_2.userDisabled); - do_check_false(t1_2.appDisabled); - do_check_true(t1_2.isActive); + do_check_true(t1.userDisabled); + do_check_false(t1.appDisabled); + do_check_true(t1.isActive); restartManager(); AddonManager.getAddonsByIDs(["default@tests.mozilla.org", - "theme1@tests.mozilla.org"], function([d_3, t1_3]) { - do_check_false(d_3.userDisabled); - do_check_false(d_3.appDisabled); - do_check_true(d_3.isActive); + "theme1@tests.mozilla.org"], function([d, t1]) { + do_check_false(d.userDisabled); + do_check_false(d.appDisabled); + do_check_true(d.isActive); - do_check_true(t1_3.userDisabled); - do_check_false(t1_3.appDisabled); - do_check_false(t1_3.isActive); + do_check_true(t1.userDisabled); + do_check_false(t1.appDisabled); + do_check_false(t1.isActive); do_execute_soon(run_test_19); }); @@ -1089,51 +1086,7 @@ function run_test_21() { p1.userDisabled = false; ensure_test_completed(); - run_test_22(); - }); - })); -} - -// Detecting a new add-on during the startup file check should not disable an -// active lightweight theme -function run_test_22() { - restartManager(); - - AddonManager.getAddonsByIDs(["default@tests.mozilla.org", - "1@personas.mozilla.org"], function([d, p1]) { - do_check_true(d.userDisabled); - do_check_false(d.appDisabled); - do_check_false(d.isActive); - - do_check_false(p1.userDisabled); - do_check_false(p1.appDisabled); - do_check_true(p1.isActive); - - writeInstallRDFForExtension({ - id: "theme3@tests.mozilla.org", - version: "1.0", - name: "Test 3", - internalName: "theme3/1.0", - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "1", - maxVersion: "2" - }] - }, profileDir); - - restartManager(); - - AddonManager.getAddonsByIDs(["default@tests.mozilla.org", - "1@personas.mozilla.org"], function([d_2, p1_2]) { - do_check_true(d_2.userDisabled); - do_check_false(d_2.appDisabled); - do_check_false(d_2.isActive); - - do_check_false(p1_2.userDisabled); - do_check_false(p1_2.appDisabled); - do_check_true(p1_2.isActive); - end_test(); }); - }); + })); } diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_undothemeuninstall.js b/toolkit/mozapps/extensions/test/xpcshell/test_undothemeuninstall.js index 36ca95aec..c804b3bd6 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_undothemeuninstall.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_undothemeuninstall.js @@ -133,7 +133,7 @@ add_task(function* uninstallEnabledOffersUndo() { do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "classic/1.0"); }); -// Tests that uninstalling an enabled theme can be undone +//Tests that uninstalling an enabled theme can be undone add_task(function* canUndoUninstallEnabled() { writeInstallRDFForExtension(theme1, profileDir); @@ -228,7 +228,7 @@ add_task(function* canUndoUninstallEnabled() { yield promiseRestartManager(); }); -// Tests that uninstalling a disabled theme offers the option to undo +//Tests that uninstalling a disabled theme offers the option to undo add_task(function* uninstallDisabledOffersUndo() { writeInstallRDFForExtension(theme1, profileDir); @@ -283,7 +283,7 @@ add_task(function* uninstallDisabledOffersUndo() { do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "classic/1.0"); }); -// Tests that uninstalling a disabled theme can be undone +//Tests that uninstalling a disabled theme can be undone add_task(function* canUndoUninstallDisabled() { writeInstallRDFForExtension(theme1, profileDir); @@ -362,11 +362,10 @@ add_task(function* canUndoUninstallDisabled() { yield promiseRestartManager(); }); -// Tests that uninstalling an enabled lightweight theme offers the option to undo +//Tests that uninstalling an enabled lightweight theme offers the option to undo add_task(function* uninstallLWTOffersUndo() { // skipped since lightweight themes don't support undoable uninstall yet return; - /* LightweightThemeManager.currentTheme = dummyLWTheme("theme1"); let [ t1, d ] = yield promiseAddonsByIDs(["theme1@personas.mozilla.org", @@ -419,5 +418,4 @@ add_task(function* uninstallLWTOffersUndo() { do_check_eq(t1, null); do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "classic/1.0"); - */ }); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_undouninstall.js b/toolkit/mozapps/extensions/test/xpcshell/test_undouninstall.js index 4680a3c4a..a589361b6 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_undouninstall.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_undouninstall.js @@ -253,7 +253,7 @@ add_task(function* uninstallInactiveIsCancellable() { yield promiseRestartManager(); }); -// Test that an inactive item can be uninstalled +//Test that an inactive item can be uninstalled add_task(function* uninstallInactive() { let a1 = yield promiseAddonByID("addon1@tests.mozilla.org"); @@ -335,7 +335,7 @@ add_task(function* uninstallRestartless() { BootstrapMonitor.checkAddonNotStarted(ID); }); -// Tests that an enabled restartless add-on can be uninstalled and then cancelled +//Tests that an enabled restartless add-on can be uninstalled and then cancelled add_task(function* cancelUninstallOfRestartless() { prepare_test({ "undouninstall1@tests.mozilla.org": [ @@ -350,7 +350,7 @@ add_task(function* cancelUninstallOfRestartless() { yield promiseInstallAllFiles([do_get_addon("test_undouninstall1")]); ensure_test_completed(); - let a1 = yield promiseAddonByID(ID); + a1 = yield promiseAddonByID(ID); do_check_neq(a1, null); BootstrapMonitor.checkAddonInstalled(ID, "1.0"); @@ -547,7 +547,7 @@ add_task(function* uninstallDisabledRestartless() { do_check_eq(getUninstallReason(ID), ADDON_UNINSTALL); }); -// Tests that a disabled restartless add-on can be uninstalled and then cancelled +//Tests that a disabled restartless add-on can be uninstalled and then cancelled add_task(function* cancelUninstallDisabledRestartless() { prepare_test({ "undouninstall1@tests.mozilla.org": [ @@ -633,8 +633,8 @@ add_task(function* cancelUninstallDisabledRestartless() { a1.uninstall(); }); -// Tests that reinstalling a disabled restartless add-on waiting to be -// uninstalled aborts the uninstall and leaves the add-on disabled +//Tests that reinstalling a disabled restartless add-on waiting to be +//uninstalled aborts the uninstall and leaves the add-on disabled add_task(function* reinstallDisabledAddonAwaitingUninstall() { yield promiseInstallAllFiles([do_get_addon("test_undouninstall1")]); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_update.js b/toolkit/mozapps/extensions/test/xpcshell/test_update.js index 4db488ab5..b7e32d59f 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_update.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_update.js @@ -23,1178 +23,400 @@ const PARAMS = "?%REQ_VERSION%/%ITEM_ID%/%ITEM_VERSION%/%ITEM_MAXAPPVERSION%/" + var gInstallDate; -var testserver = createHttpServer(); +Components.utils.import("resource://testing-common/httpd.js"); +var testserver = new HttpServer(); +testserver.start(-1); gPort = testserver.identity.primaryPort; mapFile("/data/test_update.rdf", testserver); -mapFile("/data/test_update.json", testserver); mapFile("/data/test_update.xml", testserver); testserver.registerDirectory("/addons/", do_get_file("addons")); const profileDir = gProfD.clone(); profileDir.append("extensions"); -var originalSyncGUID; +let originalSyncGUID; function run_test() { - createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1"); - + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); Services.prefs.setBoolPref(PREF_MATCH_OS_LOCALE, false); Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "fr-FR"); - run_next_test(); -} - -let testParams = [ - { updateFile: "test_update.rdf", - appId: "xpcshell@tests.mozilla.org" }, - { updateFile: "test_update.json", - appId: "toolkit@mozilla.org" }, -]; - -for (let test of testParams) { - let { updateFile, appId } = test; - - add_test(function() { - writeInstallRDFForExtension({ - id: "addon1@tests.mozilla.org", - version: "1.0", - updateURL: "http://localhost:" + gPort + "/data/" + updateFile, - targetApplications: [{ - id: appId, - minVersion: "1", - maxVersion: "1" - }], - name: "Test Addon 1", - }, profileDir); - - writeInstallRDFForExtension({ - id: "addon2@tests.mozilla.org", - version: "1.0", - updateURL: "http://localhost:" + gPort + "/data/" + updateFile, - targetApplications: [{ - id: appId, - minVersion: "0", - maxVersion: "0" - }], - name: "Test Addon 2", - }, profileDir); - - writeInstallRDFForExtension({ - id: "addon3@tests.mozilla.org", - version: "1.0", - updateURL: "http://localhost:" + gPort + "/data/" + updateFile, - targetApplications: [{ - id: appId, - minVersion: "5", - maxVersion: "5" - }], - name: "Test Addon 3", - }, profileDir); - - startupManager(); - - run_next_test(); - }); - - // Verify that an update is available and can be installed. - let check_test_1; - add_test(function run_test_1() { - AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { - do_check_neq(a1, null); - do_check_eq(a1.version, "1.0"); - do_check_eq(a1.applyBackgroundUpdates, AddonManager.AUTOUPDATE_DEFAULT); - do_check_eq(a1.releaseNotesURI, null); - do_check_true(a1.foreignInstall); - do_check_neq(a1.syncGUID, null); + writeInstallRDFForExtension({ + id: "addon1@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 1", + }, profileDir); - originalSyncGUID = a1.syncGUID; - a1.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DEFAULT; + writeInstallRDFForExtension({ + id: "addon2@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "0", + maxVersion: "0" + }], + name: "Test Addon 2", + }, profileDir); - prepare_test({ - "addon1@tests.mozilla.org": [ - ["onPropertyChanged", ["applyBackgroundUpdates"]] - ] - }); - a1.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DISABLE; - check_test_completed(); + writeInstallRDFForExtension({ + id: "addon3@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "5", + maxVersion: "5" + }], + name: "Test Addon 3", + }, profileDir); - a1.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DISABLE; + startupManager(); - prepare_test({}, [ - "onNewInstall", - ]); + do_test_pending(); + run_test_1(); +} - a1.findUpdates({ - onNoCompatibilityUpdateAvailable: function(addon) { - ok(false, "Should not have seen onNoCompatibilityUpdateAvailable notification"); - }, +function end_test() { + testserver.stop(do_test_finished); +} - onUpdateAvailable: function(addon, install) { - ensure_test_completed(); - - AddonManager.getAllInstalls(function(aInstalls) { - do_check_eq(aInstalls.length, 1); - do_check_eq(aInstalls[0], install); - - do_check_eq(addon, a1); - do_check_eq(install.name, addon.name); - do_check_eq(install.version, "2.0"); - do_check_eq(install.state, AddonManager.STATE_AVAILABLE); - do_check_eq(install.existingAddon, addon); - do_check_eq(install.releaseNotesURI.spec, "http://example.com/updateInfo.xhtml"); - - // Verify that another update check returns the same AddonInstall - a1.findUpdates({ - onNoCompatibilityUpdateAvailable: function() { - ok(false, "Should not have seen onNoCompatibilityUpdateAvailable notification"); - }, - - onUpdateAvailable: function(newAddon, newInstall) { - AddonManager.getAllInstalls(function(aInstalls2) { - do_check_eq(aInstalls2.length, 1); - do_check_eq(aInstalls2[0], install); - do_check_eq(newAddon, addon); - do_check_eq(newInstall, install); - - prepare_test({}, [ - "onDownloadStarted", - "onDownloadEnded", - ], check_test_1); - install.install(); - }); - }, +// Verify that an update is available and can be installed. +function run_test_1() { + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.version, "1.0"); + do_check_eq(a1.applyBackgroundUpdates, AddonManager.AUTOUPDATE_DEFAULT); + do_check_eq(a1.releaseNotesURI, null); + do_check_true(a1.foreignInstall); + do_check_neq(a1.syncGUID, null); - onNoUpdateAvailable: function() { - ok(false, "Should not have seen onNoUpdateAvailable notification"); - } - }, AddonManager.UPDATE_WHEN_USER_REQUESTED); - }); - }, + originalSyncGUID = a1.syncGUID; + a1.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DEFAULT; - onNoUpdateAvailable: function(addon) { - ok(false, "Should not have seen onNoUpdateAvailable notification"); - } - }, AddonManager.UPDATE_WHEN_USER_REQUESTED); + prepare_test({ + "addon1@tests.mozilla.org": [ + ["onPropertyChanged", ["applyBackgroundUpdates"]] + ] }); - }); + a1.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DISABLE; + check_test_completed(); - let run_test_2; - check_test_1 = (install) => { - ensure_test_completed(); - do_check_eq(install.state, AddonManager.STATE_DOWNLOADED); - run_test_2(install); - return false; - }; + a1.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DISABLE; - // Continue installing the update. - let check_test_2; - run_test_2 = (install) => { - // Verify that another update check returns no new update - install.existingAddon.findUpdates({ + prepare_test({}, [ + "onNewInstall", + ]); + + a1.findUpdates({ onNoCompatibilityUpdateAvailable: function(addon) { - ok(false, "Should not have seen onNoCompatibilityUpdateAvailable notification"); + do_throw("Should not have seen onNoCompatibilityUpdateAvailable notification"); }, - onUpdateAvailable: function() { - ok(false, "Should find no available update when one is already downloading"); - }, + onUpdateAvailable: function(addon, install) { + ensure_test_completed(); - onNoUpdateAvailable: function(addon) { AddonManager.getAllInstalls(function(aInstalls) { do_check_eq(aInstalls.length, 1); do_check_eq(aInstalls[0], install); - prepare_test({ - "addon1@tests.mozilla.org": [ - "onInstalling" - ] - }, [ - "onInstallStarted", - "onInstallEnded", - ], check_test_2); - install.install(); + do_check_eq(addon, a1); + do_check_eq(install.name, addon.name); + do_check_eq(install.version, "2.0"); + do_check_eq(install.state, AddonManager.STATE_AVAILABLE); + do_check_eq(install.existingAddon, addon); + do_check_eq(install.releaseNotesURI.spec, "http://example.com/updateInfo.xhtml"); + + // Verify that another update check returns the same AddonInstall + a1.findUpdates({ + onNoCompatibilityUpdateAvailable: function(addon) { + do_throw("Should not have seen onNoCompatibilityUpdateAvailable notification"); + }, + + onUpdateAvailable: function(newAddon, newInstall) { + AddonManager.getAllInstalls(function(aInstalls) { + do_check_eq(aInstalls.length, 1); + do_check_eq(aInstalls[0], install); + do_check_eq(newAddon, addon); + do_check_eq(newInstall, install); + + prepare_test({}, [ + "onDownloadStarted", + "onDownloadEnded", + ], check_test_1); + install.install(); + }); + }, + + onNoUpdateAvailable: function(addon) { + do_throw("Should not have seen onNoUpdateAvailable notification"); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); }); + }, + + onNoUpdateAvailable: function(addon) { + do_throw("Should not have seen onNoUpdateAvailable notification"); } }, AddonManager.UPDATE_WHEN_USER_REQUESTED); - }; - - check_test_2 = () => { - ensure_test_completed(); - - AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(olda1) { - do_check_neq(olda1, null); - do_check_eq(olda1.version, "1.0"); - do_check_true(isExtensionInAddonsList(profileDir, olda1.id)); - - shutdownManager(); - - startupManager(); - - do_check_true(isExtensionInAddonsList(profileDir, "addon1@tests.mozilla.org")); - - AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { - do_check_neq(a1, null); - do_check_eq(a1.version, "2.0"); - do_check_true(isExtensionInAddonsList(profileDir, a1.id)); - do_check_eq(a1.applyBackgroundUpdates, AddonManager.AUTOUPDATE_DISABLE); - do_check_eq(a1.releaseNotesURI.spec, "http://example.com/updateInfo.xhtml"); - do_check_true(a1.foreignInstall); - do_check_neq(a1.syncGUID, null); - do_check_eq(originalSyncGUID, a1.syncGUID); - - // Make sure that the extension lastModifiedTime was updated. - let testURI = a1.getResourceURI(TEST_UNPACKED ? "install.rdf" : ""); - let testFile = testURI.QueryInterface(Components.interfaces.nsIFileURL).file; - let difference = testFile.lastModifiedTime - Date.now(); - do_check_true(Math.abs(difference) < MAX_TIME_DIFFERENCE); - - a1.uninstall(); - run_next_test(); - }); - })); - }; - - // Check that an update check finds compatibility updates and applies them - let check_test_3; - add_test(function run_test_3() { - restartManager(); - - AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { - do_check_neq(a2, null); - do_check_true(a2.isActive); - do_check_true(a2.isCompatible); - do_check_false(a2.appDisabled); - do_check_true(a2.isCompatibleWith("0", "0")); - - a2.findUpdates({ - onCompatibilityUpdateAvailable: function(addon) { - do_check_true(a2.isCompatible); - do_check_false(a2.appDisabled); - do_check_true(a2.isActive); - }, - - onUpdateAvailable: function(addon, install) { - ok(false, "Should not have seen an available update"); - }, - - onNoUpdateAvailable: function(addon) { - do_check_eq(addon, a2); - do_execute_soon(check_test_3); - } - }, AddonManager.UPDATE_WHEN_USER_REQUESTED); - }); - }); - - check_test_3 = () => { - restartManager(); - AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { - do_check_neq(a2, null); - do_check_true(a2.isActive); - do_check_true(a2.isCompatible); - do_check_false(a2.appDisabled); - a2.uninstall(); - - run_next_test(); - }); - } - - // Checks that we see no compatibility information when there is none. - add_test(function run_test_4() { - AddonManager.getAddonByID("addon3@tests.mozilla.org", function(a3) { - do_check_neq(a3, null); - do_check_false(a3.isActive); - do_check_false(a3.isCompatible); - do_check_true(a3.appDisabled); - do_check_true(a3.isCompatibleWith("5", "5")); - do_check_false(a3.isCompatibleWith("2", "2")); - - a3.findUpdates({ - sawUpdate: false, - onCompatibilityUpdateAvailable: function(addon) { - ok(false, "Should not have seen compatibility information"); - }, - - onNoCompatibilityUpdateAvailable: function(addon) { - this.sawUpdate = true; - }, - - onUpdateAvailable: function(addon, install) { - ok(false, "Should not have seen an available update"); - }, - - onNoUpdateAvailable: function(addon) { - do_check_true(this.sawUpdate); - run_next_test(); - } - }, AddonManager.UPDATE_WHEN_USER_REQUESTED); - }); - }); - - // Checks that compatibility info for future apps are detected but don't make - // the item compatibile. - let check_test_5; - add_test(function run_test_5() { - AddonManager.getAddonByID("addon3@tests.mozilla.org", function(a3) { - do_check_neq(a3, null); - do_check_false(a3.isActive); - do_check_false(a3.isCompatible); - do_check_true(a3.appDisabled); - do_check_true(a3.isCompatibleWith("5", "5")); - do_check_false(a3.isCompatibleWith("2", "2")); - - a3.findUpdates({ - sawUpdate: false, - onCompatibilityUpdateAvailable: function(addon) { - do_check_false(a3.isCompatible); - do_check_true(a3.appDisabled); - do_check_false(a3.isActive); - this.sawUpdate = true; - }, - - onNoCompatibilityUpdateAvailable: function(addon) { - ok(false, "Should have seen some compatibility information"); - }, - - onUpdateAvailable: function(addon, install) { - ok(false, "Should not have seen an available update"); - }, - - onNoUpdateAvailable: function(addon) { - do_check_true(this.sawUpdate); - do_execute_soon(check_test_5); - } - }, AddonManager.UPDATE_WHEN_USER_REQUESTED, "3.0", "3.0"); - }); }); +} - check_test_5 = () => { - restartManager(); - AddonManager.getAddonByID("addon3@tests.mozilla.org", function(a3) { - do_check_neq(a3, null); - do_check_false(a3.isActive); - do_check_false(a3.isCompatible); - do_check_true(a3.appDisabled); - - a3.uninstall(); - run_next_test(); - }); - } +function check_test_1(install) { + ensure_test_completed(); + do_check_eq(install.state, AddonManager.STATE_DOWNLOADED); + run_test_2(install); + return false; +} - // Test that background update checks work - let continue_test_6; - add_test(function run_test_6() { - restartManager(); +// Continue installing the update. +function run_test_2(install) { + // Verify that another update check returns no new update + install.existingAddon.findUpdates({ + onNoCompatibilityUpdateAvailable: function(addon) { + do_throw("Should not have seen onNoCompatibilityUpdateAvailable notification"); + }, + + onUpdateAvailable: function(addon, install) { + do_throw("Should find no available update when one is already downloading"); + }, + + onNoUpdateAvailable: function(addon) { + AddonManager.getAllInstalls(function(aInstalls) { + do_check_eq(aInstalls.length, 1); + do_check_eq(aInstalls[0], install); + + prepare_test({ + "addon1@tests.mozilla.org": [ + "onInstalling" + ] + }, [ + "onInstallStarted", + "onInstallEnded", + ], check_test_2); + install.install(); + }); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); +} - writeInstallRDFForExtension({ - id: "addon1@tests.mozilla.org", - version: "1.0", - updateURL: "http://localhost:" + gPort + "/data/" + updateFile, - targetApplications: [{ - id: appId, - minVersion: "1", - maxVersion: "1" - }], - name: "Test Addon 1", - }, profileDir); - restartManager(); +function check_test_2() { + ensure_test_completed(); - prepare_test({}, [ - "onNewInstall", - "onDownloadStarted", - "onDownloadEnded" - ], continue_test_6); + AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(olda1) { + do_check_neq(olda1, null); + do_check_eq(olda1.version, "1.0"); + do_check_true(isExtensionInAddonsList(profileDir, olda1.id)); - AddonManagerInternal.backgroundUpdateCheck(); - }); - - let check_test_6; - continue_test_6 = (install) => { - do_check_neq(install.existingAddon, null); - do_check_eq(install.existingAddon.id, "addon1@tests.mozilla.org"); + shutdownManager(); - prepare_test({ - "addon1@tests.mozilla.org": [ - "onInstalling" - ] - }, [ - "onInstallStarted", - "onInstallEnded", - ], callback_soon(check_test_6)); - } + startupManager(); - check_test_6 = (install) => { - do_check_eq(install.existingAddon.pendingUpgrade.install, install); + do_check_true(isExtensionInAddonsList(profileDir, olda1.id)); - restartManager(); AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { do_check_neq(a1, null); do_check_eq(a1.version, "2.0"); + do_check_true(isExtensionInAddonsList(profileDir, a1.id)); + do_check_eq(a1.applyBackgroundUpdates, AddonManager.AUTOUPDATE_DISABLE); do_check_eq(a1.releaseNotesURI.spec, "http://example.com/updateInfo.xhtml"); - a1.uninstall(); - run_next_test(); - }); - } - - // Verify the parameter escaping in update urls. - add_test(function run_test_8() { - restartManager(); - - writeInstallRDFForExtension({ - id: "addon1@tests.mozilla.org", - version: "5.0", - updateURL: "http://localhost:" + gPort + "/data/param_test.rdf" + PARAMS, - targetApplications: [{ - id: appId, - minVersion: "1", - maxVersion: "2" - }], - name: "Test Addon 1", - }, profileDir); - - writeInstallRDFForExtension({ - id: "addon2@tests.mozilla.org", - version: "67.0.5b1", - updateURL: "http://localhost:" + gPort + "/data/param_test.rdf" + PARAMS, - targetApplications: [{ - id: "toolkit@mozilla.org", - minVersion: "0", - maxVersion: "3" - }], - name: "Test Addon 2", - }, profileDir); - - writeInstallRDFForExtension({ - id: "addon3@tests.mozilla.org", - version: "1.3+", - updateURL: "http://localhost:" + gPort + "/data/param_test.rdf" + PARAMS, - targetApplications: [{ - id: appId, - minVersion: "0", - maxVersion: "0" - }, { - id: "toolkit@mozilla.org", - minVersion: "0", - maxVersion: "3" - }], - name: "Test Addon 3", - }, profileDir); - - writeInstallRDFForExtension({ - id: "addon4@tests.mozilla.org", - version: "0.5ab6", - updateURL: "http://localhost:" + gPort + "/data/param_test.rdf" + PARAMS, - targetApplications: [{ - id: appId, - minVersion: "1", - maxVersion: "5" - }], - name: "Test Addon 4", - }, profileDir); - - writeInstallRDFForExtension({ - id: "addon5@tests.mozilla.org", - version: "1.0", - updateURL: "http://localhost:" + gPort + "/data/param_test.rdf" + PARAMS, - targetApplications: [{ - id: appId, - minVersion: "1", - maxVersion: "1" - }], - name: "Test Addon 5", - }, profileDir); - - writeInstallRDFForExtension({ - id: "addon6@tests.mozilla.org", - version: "1.0", - updateURL: "http://localhost:" + gPort + "/data/param_test.rdf" + PARAMS, - targetApplications: [{ - id: appId, - minVersion: "1", - maxVersion: "1" - }], - name: "Test Addon 6", - }, profileDir); - - restartManager(); - - AddonManager.getAddonByID("addon2@tests.mozilla.org", callback_soon(function(a2) { - a2.userDisabled = true; - restartManager(); - - testserver.registerPathHandler("/data/param_test.rdf", function(request, response) { - do_check_neq(request.queryString, ""); - let [req_version, item_id, item_version, - item_maxappversion, item_status, - app_id, app_version, current_app_version, - app_os, app_abi, app_locale, update_type] = - request.queryString.split("/").map(a => decodeURIComponent(a)); - - do_check_eq(req_version, "2"); - - switch (item_id) { - case "addon1@tests.mozilla.org": - do_check_eq(item_version, "5.0"); - do_check_eq(item_maxappversion, "2"); - do_check_eq(item_status, "userEnabled"); - do_check_eq(app_version, "1"); - do_check_eq(update_type, "97"); - break; - case "addon2@tests.mozilla.org": - do_check_eq(item_version, "67.0.5b1"); - do_check_eq(item_maxappversion, "3"); - do_check_eq(item_status, "userDisabled"); - do_check_eq(app_version, "1"); - do_check_eq(update_type, "49"); - break; - case "addon3@tests.mozilla.org": - do_check_eq(item_version, "1.3+"); - do_check_eq(item_maxappversion, "0"); - do_check_eq(item_status, "userEnabled"); - do_check_eq(app_version, "1"); - do_check_eq(update_type, "112"); - break; - case "addon4@tests.mozilla.org": - do_check_eq(item_version, "0.5ab6"); - do_check_eq(item_maxappversion, "5"); - do_check_eq(item_status, "userEnabled"); - do_check_eq(app_version, "2"); - do_check_eq(update_type, "98"); - break; - case "addon5@tests.mozilla.org": - do_check_eq(item_version, "1.0"); - do_check_eq(item_maxappversion, "1"); - do_check_eq(item_status, "userEnabled"); - do_check_eq(app_version, "1"); - do_check_eq(update_type, "35"); - break; - case "addon6@tests.mozilla.org": - do_check_eq(item_version, "1.0"); - do_check_eq(item_maxappversion, "1"); - do_check_eq(item_status, "userEnabled"); - do_check_eq(app_version, "1"); - do_check_eq(update_type, "99"); - break; - default: - ok(false, "Update request for unexpected add-on " + item_id); - } - - do_check_eq(app_id, "xpcshell@tests.mozilla.org"); - do_check_eq(current_app_version, "1"); - do_check_eq(app_os, "XPCShell"); - do_check_eq(app_abi, "noarch-spidermonkey"); - do_check_eq(app_locale, "fr-FR"); - - request.setStatusLine(null, 500, "Server Error"); - }); - - AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", - "addon2@tests.mozilla.org", - "addon3@tests.mozilla.org", - "addon4@tests.mozilla.org", - "addon5@tests.mozilla.org", - "addon6@tests.mozilla.org"], - function([a1_2, a2_2, a3_2, a4_2, a5_2, a6_2]) { - let count = 6; - - function next_test() { - a1_2.uninstall(); - a2_2.uninstall(); - a3_2.uninstall(); - a4_2.uninstall(); - a5_2.uninstall(); - a6_2.uninstall(); - - restartManager(); - run_next_test(); - } - - let compatListener = { - onUpdateFinished: function(addon, error) { - if (--count == 0) - do_execute_soon(next_test); - } - }; - - let updateListener = { - onUpdateAvailable: function(addon, update) { - // Dummy so the update checker knows we care about new versions - }, - - onUpdateFinished: function(addon, error) { - if (--count == 0) - do_execute_soon(next_test); - } - }; - - a1_2.findUpdates(updateListener, AddonManager.UPDATE_WHEN_USER_REQUESTED); - a2_2.findUpdates(compatListener, AddonManager.UPDATE_WHEN_ADDON_INSTALLED); - a3_2.findUpdates(updateListener, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE); - a4_2.findUpdates(updateListener, AddonManager.UPDATE_WHEN_NEW_APP_DETECTED, "2"); - a5_2.findUpdates(compatListener, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED); - a6_2.findUpdates(updateListener, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED); - }); - })); - }); - - // Tests that if an install.rdf claims compatibility then the add-on will be - // seen as compatible regardless of what the update.rdf says. - add_test(function run_test_9() { - writeInstallRDFForExtension({ - id: "addon4@tests.mozilla.org", - version: "5.0", - updateURL: "http://localhost:" + gPort + "/data/" + updateFile, - targetApplications: [{ - id: appId, - minVersion: "0", - maxVersion: "1" - }], - name: "Test Addon 1", - }, profileDir); - - restartManager(); - - AddonManager.getAddonByID("addon4@tests.mozilla.org", function(a4) { - do_check_true(a4.isActive, "addon4 is active"); - do_check_true(a4.isCompatible, "addon4 is compatible"); - - run_next_test(); - }); - }); - - // Tests that a normal update check won't decrease a targetApplication's - // maxVersion. - add_test(function run_test_10() { - AddonManager.getAddonByID("addon4@tests.mozilla.org", function(a4) { - a4.findUpdates({ - onUpdateFinished: function(addon) { - do_check_true(addon.isCompatible, "addon4 is compatible"); - - run_next_test(); - } - }, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE); - }); - }); - - // Tests that an update check for a new application will decrease a - // targetApplication's maxVersion. - add_test(function run_test_11() { - AddonManager.getAddonByID("addon4@tests.mozilla.org", function(a4) { - a4.findUpdates({ - onUpdateFinished: function(addon) { - do_check_true(addon.isCompatible, "addon4 is not compatible"); - - run_next_test(); - } - }, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED); - }); - }); - - // Check that the decreased maxVersion applied and disables the add-on - add_test(function run_test_12() { - restartManager(); - - AddonManager.getAddonByID("addon4@tests.mozilla.org", function(a4) { - do_check_true(a4.isActive); - do_check_true(a4.isCompatible); - - a4.uninstall(); - run_next_test(); - }); - }); - - // Tests that a compatibility update is passed to the listener when there is - // compatibility info for the current version of the app but not for the - // version of the app that the caller requested an update check for, when - // strict compatibility checking is disabled. - let check_test_13; - add_test(function run_test_13() { - restartManager(); - - // Not initially compatible but the update check will make it compatible - writeInstallRDFForExtension({ - id: "addon7@tests.mozilla.org", - version: "1.0", - updateURL: "http://localhost:" + gPort + "/data/" + updateFile, - targetApplications: [{ - id: appId, - minVersion: "0", - maxVersion: "0" - }], - name: "Test Addon 7", - }, profileDir); - restartManager(); - - AddonManager.getAddonByID("addon7@tests.mozilla.org", function(a7) { - do_check_neq(a7, null); - do_check_true(a7.isActive); - do_check_true(a7.isCompatible); - do_check_false(a7.appDisabled); - do_check_true(a7.isCompatibleWith("0", "0")); - - a7.findUpdates({ - sawUpdate: false, - onNoCompatibilityUpdateAvailable: function(addon) { - ok(false, "Should have seen compatibility information"); - }, - - onUpdateAvailable: function(addon, install) { - ok(false, "Should not have seen an available update"); - }, - - onUpdateFinished: function(addon) { - do_check_true(addon.isCompatible); - do_execute_soon(check_test_13); - } - }, AddonManager.UPDATE_WHEN_NEW_APP_DETECTED, "3.0", "3.0"); - }); - }); - - check_test_13 = () => { - restartManager(); - AddonManager.getAddonByID("addon7@tests.mozilla.org", function(a7) { - do_check_neq(a7, null); - do_check_true(a7.isActive); - do_check_true(a7.isCompatible); - do_check_false(a7.appDisabled); - - a7.uninstall(); - run_next_test(); - }); - } - - // Test that background update checks doesn't update an add-on that isn't - // allowed to update automatically. - let check_test_14; - add_test(function run_test_14() { - restartManager(); - - // Have an add-on there that will be updated so we see some events from it - writeInstallRDFForExtension({ - id: "addon1@tests.mozilla.org", - version: "1.0", - updateURL: "http://localhost:" + gPort + "/data/" + updateFile, - targetApplications: [{ - id: appId, - minVersion: "1", - maxVersion: "1" - }], - name: "Test Addon 1", - }, profileDir); - - writeInstallRDFForExtension({ - id: "addon8@tests.mozilla.org", - version: "1.0", - updateURL: "http://localhost:" + gPort + "/data/" + updateFile, - targetApplications: [{ - id: appId, - minVersion: "1", - maxVersion: "1" - }], - name: "Test Addon 8", - }, profileDir); - restartManager(); - - AddonManager.getAddonByID("addon8@tests.mozilla.org", function(a8) { - a8.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DISABLE; - - // The background update check will find updates for both add-ons but only - // proceed to install one of them. - AddonManager.addInstallListener({ - onNewInstall: function(aInstall) { - let id = aInstall.existingAddon.id; - ok((id == "addon1@tests.mozilla.org" || id == "addon8@tests.mozilla.org"), - "Saw unexpected onNewInstall for " + id); - }, - - onDownloadStarted: function(aInstall) { - do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); - }, - - onDownloadEnded: function(aInstall) { - do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); - }, - - onDownloadFailed: function(aInstall) { - ok(false, "Should not have seen onDownloadFailed event"); - }, - - onDownloadCancelled: function(aInstall) { - ok(false, "Should not have seen onDownloadCancelled event"); - }, - - onInstallStarted: function(aInstall) { - do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); - }, - - onInstallEnded: function(aInstall) { - do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); - do_check_eq(aInstall.existingAddon.pendingUpgrade.install, aInstall); - - do_execute_soon(check_test_14); - }, - - onInstallFailed: function(aInstall) { - ok(false, "Should not have seen onInstallFailed event"); - }, - - onInstallCancelled: function(aInstall) { - ok(false, "Should not have seen onInstallCancelled event"); - }, - }); - - AddonManagerInternal.backgroundUpdateCheck(); - }); - }); + do_check_true(a1.foreignInstall); + do_check_neq(a1.syncGUID, null); + do_check_eq(originalSyncGUID, a1.syncGUID); - check_test_14 = () => { - restartManager(); - AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", - "addon8@tests.mozilla.org"], function([a1, a8]) { - do_check_neq(a1, null); - do_check_eq(a1.version, "2.0"); a1.uninstall(); - - do_check_neq(a8, null); - do_check_eq(a8.version, "1.0"); - a8.uninstall(); - - run_next_test(); + do_execute_soon(run_test_3); }); - } - - // Test that background update checks doesn't update an add-on that is - // pending uninstall - let check_test_15; - add_test(function run_test_15() { - restartManager(); - - // Have an add-on there that will be updated so we see some events from it - writeInstallRDFForExtension({ - id: "addon1@tests.mozilla.org", - version: "1.0", - updateURL: "http://localhost:" + gPort + "/data/" + updateFile, - targetApplications: [{ - id: appId, - minVersion: "1", - maxVersion: "1" - }], - name: "Test Addon 1", - }, profileDir); - - writeInstallRDFForExtension({ - id: "addon8@tests.mozilla.org", - version: "1.0", - updateURL: "http://localhost:" + gPort + "/data/" + updateFile, - targetApplications: [{ - id: appId, - minVersion: "1", - maxVersion: "1" - }], - name: "Test Addon 8", - }, profileDir); - restartManager(); - - AddonManager.getAddonByID("addon8@tests.mozilla.org", function(a8) { - a8.uninstall(); - do_check_false(hasFlag(a8.permissions, AddonManager.PERM_CAN_UPGRADE)); - - // The background update check will find updates for both add-ons but only - // proceed to install one of them. - AddonManager.addInstallListener({ - onNewInstall: function(aInstall) { - let id = aInstall.existingAddon.id; - ok((id == "addon1@tests.mozilla.org" || id == "addon8@tests.mozilla.org"), - "Saw unexpected onNewInstall for " + id); - }, - - onDownloadStarted: function(aInstall) { - do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); - }, - - onDownloadEnded: function(aInstall) { - do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); - }, - - onDownloadFailed: function(aInstall) { - ok(false, "Should not have seen onDownloadFailed event"); - }, + })); +} - onDownloadCancelled: function(aInstall) { - ok(false, "Should not have seen onDownloadCancelled event"); - }, - onInstallStarted: function(aInstall) { - do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); - }, - - onInstallEnded: function(aInstall) { - do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); - do_execute_soon(check_test_15); - }, +// Check that an update check finds compatibility updates and applies them +function run_test_3() { + restartManager(); - onInstallFailed: function(aInstall) { - ok(false, "Should not have seen onInstallFailed event"); - }, + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { + do_check_neq(a2, null); + do_check_true(a2.isActive); + do_check_true(a2.isCompatible); + do_check_false(a2.appDisabled); + do_check_true(a2.isCompatibleWith("0")); + + a2.findUpdates({ + onCompatibilityUpdateAvailable: function(addon) { + do_check_true(a2.isCompatible); + do_check_false(a2.appDisabled); + do_check_true(a2.isActive); + }, - onInstallCancelled: function(aInstall) { - ok(false, "Should not have seen onInstallCancelled event"); - }, - }); + onUpdateAvailable: function(addon, install) { + do_throw("Should not have seen an available update"); + }, - AddonManagerInternal.backgroundUpdateCheck(); - }); + onNoUpdateAvailable: function(addon) { + do_check_eq(addon, a2); + do_execute_soon(check_test_3); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); }); +} - check_test_15 = () => { - restartManager(); - AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", - "addon8@tests.mozilla.org"], function([a1, a8]) { - do_check_neq(a1, null); - do_check_eq(a1.version, "2.0"); - a1.uninstall(); - - do_check_eq(a8, null); - - run_next_test(); - }); - } - - add_test(function run_test_16() { - restartManager(); - - restartManager(); - - let url = "http://localhost:" + gPort + "/addons/test_install2_1.xpi"; - AddonManager.getInstallForURL(url, function(aInstall) { - aInstall.addListener({ - onInstallEnded: function() { - do_execute_soon(function install_2_1_ended() { - restartManager(); - - AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a1) { - do_check_neq(a1.syncGUID, null); - let oldGUID = a1.syncGUID; - - let url_2 = "http://localhost:" + gPort + "/addons/test_install2_2.xpi"; - AddonManager.getInstallForURL(url_2, function(aInstall_2) { - aInstall_2.addListener({ - onInstallEnded: function() { - do_execute_soon(function install_2_2_ended() { - restartManager(); - - AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { - do_check_neq(a2.syncGUID, null); - do_check_eq(oldGUID, a2.syncGUID); - - a2.uninstall(); - run_next_test(); - }); - }); - } - }); - aInstall_2.install(); - }, "application/x-xpinstall"); - }); - }); - } - }); - aInstall.install(); - }, "application/x-xpinstall"); +function check_test_3() { + restartManager(); + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { + do_check_neq(a2, null); + do_check_true(a2.isActive); + do_check_true(a2.isCompatible); + do_check_false(a2.appDisabled); + a2.uninstall(); + + run_test_4(); }); +} - // Test that the update check correctly observes the - // extensions.strictCompatibility pref and compatibility overrides. - add_test(function run_test_17() { - restartManager(); - - writeInstallRDFForExtension({ - id: "addon9@tests.mozilla.org", - version: "1.0", - updateURL: "http://localhost:" + gPort + "/data/" + updateFile, - targetApplications: [{ - id: appId, - minVersion: "0.1", - maxVersion: "0.2" - }], - name: "Test Addon 9", - }, profileDir); - restartManager(); - - AddonManager.addInstallListener({ - onNewInstall: function(aInstall) { - equal(aInstall.existingAddon.id, "addon9@tests.mozilla.org", - "Saw unexpected onNewInstall for " + aInstall.existingAddon.id); - do_check_eq(aInstall.version, "3.0"); +// Checks that we see no compatibility information when there is none. +function run_test_4() { + AddonManager.getAddonByID("addon3@tests.mozilla.org", function(a3) { + do_check_neq(a3, null); + do_check_false(a3.isActive); + do_check_false(a3.isCompatible); + do_check_true(a3.appDisabled); + do_check_true(a3.isCompatibleWith("5")); + do_check_false(a3.isCompatibleWith("2")); + + a3.findUpdates({ + sawUpdate: false, + onCompatibilityUpdateAvailable: function(addon) { + do_throw("Should not have seen compatibility information"); }, - onDownloadFailed: function(aInstall) { - AddonManager.getAddonByID("addon9@tests.mozilla.org", function(a9) { - a9.uninstall(); - run_next_test(); - }); - } - }); - - Services.prefs.setCharPref(PREF_GETADDONS_BYIDS, - "http://localhost:" + gPort + "/data/test_update.xml"); - Services.prefs.setCharPref(PREF_GETADDONS_BYIDS_PERFORMANCE, - "http://localhost:" + gPort + "/data/test_update.xml"); - Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true); - - AddonManagerInternal.backgroundUpdateCheck(); - }); - // Tests that compatibility updates are applied to addons when the updated - // compatibility data wouldn't match with strict compatibility enabled. - add_test(function run_test_18() { - restartManager(); - writeInstallRDFForExtension({ - id: "addon10@tests.mozilla.org", - version: "1.0", - updateURL: "http://localhost:" + gPort + "/data/" + updateFile, - targetApplications: [{ - id: appId, - minVersion: "0.1", - maxVersion: "0.2" - }], - name: "Test Addon 10", - }, profileDir); - restartManager(); - - AddonManager.getAddonByID("addon10@tests.mozilla.org", function(a10) { - do_check_neq(a10, null); - - a10.findUpdates({ - onNoCompatibilityUpdateAvailable: function() { - ok(false, "Should have seen compatibility information"); - }, + onNoCompatibilityUpdateAvailable: function(addon) { + this.sawUpdate = true; + }, - onUpdateAvailable: function() { - ok(false, "Should not have seen an available update"); - }, + onUpdateAvailable: function(addon, install) { + do_throw("Should not have seen an available update"); + }, - onUpdateFinished: function() { - a10.uninstall(); - run_next_test(); - } - }, AddonManager.UPDATE_WHEN_USER_REQUESTED); - }); + onNoUpdateAvailable: function(addon) { + do_check_true(this.sawUpdate); + run_test_5(); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); }); +} - // Test that the update check correctly observes when an addon opts-in to - // strict compatibility checking. - add_test(function run_test_19() { - restartManager(); - writeInstallRDFForExtension({ - id: "addon11@tests.mozilla.org", - version: "1.0", - updateURL: "http://localhost:" + gPort + "/data/" + updateFile, - targetApplications: [{ - id: appId, - minVersion: "0.1", - maxVersion: "0.2" - }], - name: "Test Addon 11", - }, profileDir); - restartManager(); - - AddonManager.getAddonByID("addon11@tests.mozilla.org", function(a11) { - do_check_neq(a11, null); +// Checks that compatibility info for future apps are detected but don't make +// the item compatibile. +function run_test_5() { + AddonManager.getAddonByID("addon3@tests.mozilla.org", function(a3) { + do_check_neq(a3, null); + do_check_false(a3.isActive); + do_check_false(a3.isCompatible); + do_check_true(a3.appDisabled); + do_check_true(a3.isCompatibleWith("5")); + do_check_false(a3.isCompatibleWith("2")); + + a3.findUpdates({ + sawUpdate: false, + onCompatibilityUpdateAvailable: function(addon) { + do_check_false(a3.isCompatible); + do_check_true(a3.appDisabled); + do_check_false(a3.isActive); + this.sawUpdate = true; + }, - a11.findUpdates({ - onCompatibilityUpdateAvailable: function() { - ok(false, "Should have not have seen compatibility information"); - }, + onNoCompatibilityUpdateAvailable: function(addon) { + do_throw("Should have seen some compatibility information"); + }, - onUpdateAvailable: function() { - ok(false, "Should not have seen an available update"); - }, + onUpdateAvailable: function(addon, install) { + do_throw("Should not have seen an available update"); + }, - onUpdateFinished: function() { - a11.uninstall(); - run_next_test(); - } - }, AddonManager.UPDATE_WHEN_USER_REQUESTED); - }); + onNoUpdateAvailable: function(addon) { + do_check_true(this.sawUpdate); + do_execute_soon(check_test_5); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED, "3.0"); }); +} - // Test that the update succeeds when the update.rdf URN contains a type prefix - // different from the add-on type - let continue_test_20; - add_test(function run_test_20() { - restartManager(); - writeInstallRDFForExtension({ - id: "addon12@tests.mozilla.org", - version: "1.0", - updateURL: "http://localhost:" + gPort + "/data/" + updateFile, - targetApplications: [{ - id: appId, - minVersion: "1", - maxVersion: "1" - }], - name: "Test Addon 12", - }, profileDir); - restartManager(); - - prepare_test({}, [ - "onNewInstall", - "onDownloadStarted", - "onDownloadEnded" - ], continue_test_20); - - AddonManagerPrivate.backgroundUpdateCheck(); +function check_test_5() { + restartManager(); + AddonManager.getAddonByID("addon3@tests.mozilla.org", function(a3) { + do_check_neq(a3, null); + do_check_false(a3.isActive); + do_check_false(a3.isCompatible); + do_check_true(a3.appDisabled); + + a3.uninstall(); + do_execute_soon(run_test_6); }); +} - let check_test_20; - continue_test_20 = (install) => { - do_check_neq(install.existingAddon, null); - do_check_eq(install.existingAddon.id, "addon12@tests.mozilla.org"); - - prepare_test({ - "addon12@tests.mozilla.org": [ - "onInstalling" - ] - }, [ - "onInstallStarted", - "onInstallEnded", - ], callback_soon(check_test_20)); - } - - check_test_20 = (install) => { - do_check_eq(install.existingAddon.pendingUpgrade.install, install); - - restartManager(); - AddonManager.getAddonByID("addon12@tests.mozilla.org", function(a12) { - do_check_neq(a12, null); - do_check_eq(a12.version, "2.0"); - do_check_eq(a12.type, "extension"); - a12.uninstall(); +// Test that background update checks work +function run_test_6() { + restartManager(); - do_execute_soon(() => { - restartManager(); - run_next_test() - }); - }); - } + writeInstallRDFForExtension({ + id: "addon1@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 1", + }, profileDir); + restartManager(); - add_task(function* cleanup() { - let addons = yield new Promise(resolve => { - AddonManager.getAddonsByTypes(["extension"], resolve); - }); + prepare_test({}, [ + "onNewInstall", + "onDownloadStarted", + "onDownloadEnded" + ], continue_test_6); - for (let addon of addons) - addon.uninstall(); + AddonManagerInternal.backgroundUpdateCheck(); +} - yield promiseRestartManager(); +function continue_test_6(install) { + do_check_neq(install.existingAddon, null); + do_check_eq(install.existingAddon.id, "addon1@tests.mozilla.org"); + + prepare_test({ + "addon1@tests.mozilla.org": [ + "onInstalling" + ] + }, [ + "onInstallStarted", + "onInstallEnded", + ], callback_soon(check_test_6)); +} - shutdownManager(); +function check_test_6(install) { + do_check_eq(install.existingAddon.pendingUpgrade.install, install); - yield new Promise(do_execute_soon); + restartManager(); + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.version, "2.0"); + do_check_eq(a1.releaseNotesURI.spec, "http://example.com/updateInfo.xhtml"); + a1.uninstall(); + do_execute_soon(run_test_7); }); } // Test that background update checks work for lightweight themes -add_test(function run_test_7() { - startupManager(); +function run_test_7() { + restartManager(); LightweightThemeManager.currentTheme = { id: "1", @@ -1262,7 +484,7 @@ add_test(function run_test_7() { AddonManagerInternal.backgroundUpdateCheck(); }); -}); +} function check_test_7() { AddonManager.getAddonByID("1@personas.mozilla.org", function(p1) { @@ -1279,13 +501,13 @@ function check_test_7() { gInstallDate = p1.installDate.getTime(); - run_next_test(); + run_test_7_cache(); }); } // Test that background update checks for lightweight themes do not use the cache // The update body from test 7 shouldn't be used since the cache should be bypassed. -add_test(function () { +function run_test_7_cache() { // XXX The lightweight theme manager strips non-https updateURLs so hack it // back in. let themes = JSON.parse(Services.prefs.getCharPref("lightweightThemes.usedThemes")); @@ -1328,7 +550,7 @@ add_test(function () { AddonManagerInternal.backgroundUpdateCheck(); }); -}); +} function check_test_7_cache() { AddonManager.getAddonByID("1@personas.mozilla.org", function(p1) { @@ -1349,19 +571,579 @@ function check_test_7_cache() { do_check_eq(p1.installDate.getTime(), gInstallDate); do_check_true(p1.installDate.getTime() < p1.updateDate.getTime()); - run_next_test(); + do_execute_soon(run_test_8); + }); +} + +// Verify the parameter escaping in update urls. +function run_test_8() { + writeInstallRDFForExtension({ + id: "addon1@tests.mozilla.org", + version: "5.0", + updateURL: "http://localhost:" + gPort + "/data/param_test.rdf" + PARAMS, + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "2" + }], + name: "Test Addon 1", + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon2@tests.mozilla.org", + version: "67.0.5b1", + updateURL: "http://localhost:" + gPort + "/data/param_test.rdf" + PARAMS, + targetApplications: [{ + id: "toolkit@mozilla.org", + minVersion: "0", + maxVersion: "3" + }], + name: "Test Addon 2", + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon3@tests.mozilla.org", + version: "1.3+", + updateURL: "http://localhost:" + gPort + "/data/param_test.rdf" + PARAMS, + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "0", + maxVersion: "0" + }, { + id: "toolkit@mozilla.org", + minVersion: "0", + maxVersion: "3" + }], + name: "Test Addon 3", + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon4@tests.mozilla.org", + version: "0.5ab6", + updateURL: "http://localhost:" + gPort + "/data/param_test.rdf" + PARAMS, + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "5" + }], + name: "Test Addon 4", + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon5@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/param_test.rdf" + PARAMS, + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 5", + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon6@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/param_test.rdf" + PARAMS, + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 6", + }, profileDir); + + restartManager(); + + AddonManager.getAddonByID("addon2@tests.mozilla.org", callback_soon(function(a2) { + a2.userDisabled = true; + restartManager(); + + testserver.registerPathHandler("/data/param_test.rdf", function(request, response) { + do_check_neq(request.queryString, ""); + let [req_version, item_id, item_version, + item_maxappversion, item_status, + app_id, app_version, current_app_version, + app_os, app_abi, app_locale, update_type] = + [decodeURIComponent(a) for each (a in request.queryString.split("/"))]; + + do_check_eq(req_version, "2"); + + switch(item_id) { + case "addon1@tests.mozilla.org": + do_check_eq(item_version, "5.0"); + do_check_eq(item_maxappversion, "2"); + do_check_eq(item_status, "userEnabled"); + do_check_eq(app_version, "1"); + do_check_eq(update_type, "97"); + break; + case "addon2@tests.mozilla.org": + do_check_eq(item_version, "67.0.5b1"); + do_check_eq(item_maxappversion, "3"); + do_check_eq(item_status, "userDisabled"); + do_check_eq(app_version, "1"); + do_check_eq(update_type, "49"); + break; + case "addon3@tests.mozilla.org": + do_check_eq(item_version, "1.3+"); + do_check_eq(item_maxappversion, "0"); + do_check_eq(item_status, "userEnabled"); + do_check_eq(app_version, "1"); + do_check_eq(update_type, "112"); + break; + case "addon4@tests.mozilla.org": + do_check_eq(item_version, "0.5ab6"); + do_check_eq(item_maxappversion, "5"); + do_check_eq(item_status, "userEnabled"); + do_check_eq(app_version, "2"); + do_check_eq(update_type, "98"); + break; + case "addon5@tests.mozilla.org": + do_check_eq(item_version, "1.0"); + do_check_eq(item_maxappversion, "1"); + do_check_eq(item_status, "userEnabled"); + do_check_eq(app_version, "1"); + do_check_eq(update_type, "35"); + break; + case "addon6@tests.mozilla.org": + do_check_eq(item_version, "1.0"); + do_check_eq(item_maxappversion, "1"); + do_check_eq(item_status, "userEnabled"); + do_check_eq(app_version, "1"); + do_check_eq(update_type, "99"); + break; + default: + do_throw("Update request for unexpected add-on " + item_id); + } + + do_check_eq(app_id, "xpcshell@tests.mozilla.org"); + do_check_eq(current_app_version, "1"); + do_check_eq(app_os, "XPCShell"); + do_check_eq(app_abi, "noarch-spidermonkey"); + do_check_eq(app_locale, "fr-FR"); + + request.setStatusLine(null, 500, "Server Error"); + }); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org", + "addon5@tests.mozilla.org", + "addon6@tests.mozilla.org"], + function([a1, a2, a3, a4, a5, a6]) { + let count = 6; + + function run_next_test() { + a1.uninstall(); + a2.uninstall(); + a3.uninstall(); + a4.uninstall(); + a5.uninstall(); + a6.uninstall(); + + restartManager(); + run_test_9(); + } + + let compatListener = { + onUpdateFinished: function(addon, error) { + if (--count == 0) + do_execute_soon(run_next_test); + } + }; + + let updateListener = { + onUpdateAvailable: function(addon, update) { + // Dummy so the update checker knows we care about new versions + }, + + onUpdateFinished: function(addon, error) { + if (--count == 0) + do_execute_soon(run_next_test); + } + }; + + a1.findUpdates(updateListener, AddonManager.UPDATE_WHEN_USER_REQUESTED); + a2.findUpdates(compatListener, AddonManager.UPDATE_WHEN_ADDON_INSTALLED); + a3.findUpdates(updateListener, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE); + a4.findUpdates(updateListener, AddonManager.UPDATE_WHEN_NEW_APP_DETECTED, "2"); + a5.findUpdates(compatListener, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED); + a6.findUpdates(updateListener, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED); + }); + })); +} + +// Tests that if an install.rdf claims compatibility then the add-on will be +// seen as compatible regardless of what the update.rdf says. +function run_test_9() { + writeInstallRDFForExtension({ + id: "addon4@tests.mozilla.org", + version: "5.0", + updateURL: "http://localhost:" + gPort + "/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "0", + maxVersion: "1" + }], + name: "Test Addon 1", + }, profileDir); + + restartManager(); + + AddonManager.getAddonByID("addon4@tests.mozilla.org", function(a4) { + do_check_true(a4.isActive); + do_check_true(a4.isCompatible); + + run_test_10(); + }); +} + +// Tests that a normal update check won't decrease a targetApplication's +// maxVersion. +function run_test_10() { + AddonManager.getAddonByID("addon4@tests.mozilla.org", function(a4) { + a4.findUpdates({ + onUpdateFinished: function(addon) { + do_check_true(addon.isCompatible); + + run_test_11(); + } + }, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE); + }); +} + +// Tests that an update check for a new application will decrease a +// targetApplication's maxVersion. +function run_test_11() { + AddonManager.getAddonByID("addon4@tests.mozilla.org", function(a4) { + a4.findUpdates({ + onUpdateFinished: function(addon) { + do_check_true(addon.isCompatible); + + do_execute_soon(run_test_12); + } + }, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED); + }); +} + +// Check that the decreased maxVersion applied and disables the add-on +function run_test_12() { + restartManager(); + + AddonManager.getAddonByID("addon4@tests.mozilla.org", function(a4) { + do_check_true(a4.isActive); + do_check_true(a4.isCompatible); + + a4.uninstall(); + do_execute_soon(run_test_13); + }); +} + +// Tests that a compatibility update is passed to the listener when there is +// compatibility info for the current version of the app but not for the +// version of the app that the caller requested an update check for, when +// strict compatibility checking is disabled. +function run_test_13() { + restartManager(); + + // Not initially compatible but the update check will make it compatible + writeInstallRDFForExtension({ + id: "addon7@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "0", + maxVersion: "0" + }], + name: "Test Addon 7", + }, profileDir); + restartManager(); + + AddonManager.getAddonByID("addon7@tests.mozilla.org", function(a7) { + do_check_neq(a7, null); + do_check_true(a7.isActive); + do_check_true(a7.isCompatible); + do_check_false(a7.appDisabled); + do_check_true(a7.isCompatibleWith("0")); + + a7.findUpdates({ + sawUpdate: false, + onNoCompatibilityUpdateAvailable: function(addon) { + do_throw("Should have seen compatibility information"); + }, + + onUpdateAvailable: function(addon, install) { + do_throw("Should not have seen an available update"); + }, + + onUpdateFinished: function(addon) { + do_check_true(addon.isCompatible); + do_execute_soon(check_test_13); + } + }, AddonManager.UPDATE_WHEN_NEW_APP_DETECTED, "3.0"); }); } -// Test that the update check returns nothing for addons in locked install -// locations. -add_test(function run_test_locked_install() { - const lockedDir = gProfD.clone(); - lockedDir.append("locked_extensions"); - registerDirectory("XREAppFeat", lockedDir); +function check_test_13() { restartManager(); + AddonManager.getAddonByID("addon7@tests.mozilla.org", function(a7) { + do_check_neq(a7, null); + do_check_true(a7.isActive); + do_check_true(a7.isCompatible); + do_check_false(a7.appDisabled); + + a7.uninstall(); + do_execute_soon(run_test_14); + }); +} + +// Test that background update checks doesn't update an add-on that isn't +// allowed to update automatically. +function run_test_14() { + restartManager(); + + // Have an add-on there that will be updated so we see some events from it writeInstallRDFForExtension({ - id: "addon13@tests.mozilla.org", + id: "addon1@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 1", + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon8@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 8", + }, profileDir); + restartManager(); + + AddonManager.getAddonByID("addon8@tests.mozilla.org", function(a8) { + a8.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DISABLE; + + // The background update check will find updates for both add-ons but only + // proceed to install one of them. + AddonManager.addInstallListener({ + onNewInstall: function(aInstall) { + if (aInstall.existingAddon.id != "addon1@tests.mozilla.org" && + aInstall.existingAddon.id != "addon8@tests.mozilla.org") + do_throw("Saw unexpected onNewInstall for " + aInstall.existingAddon.id); + }, + + onDownloadStarted: function(aInstall) { + do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); + }, + + onDownloadEnded: function(aInstall) { + do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); + }, + + onDownloadFailed: function(aInstall) { + do_throw("Should not have seen onDownloadFailed event"); + }, + + onDownloadCancelled: function(aInstall) { + do_throw("Should not have seen onDownloadCancelled event"); + }, + + onInstallStarted: function(aInstall) { + do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); + }, + + onInstallEnded: function(aInstall) { + do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); + do_check_eq(aInstall.existingAddon.pendingUpgrade.install, aInstall); + + do_execute_soon(check_test_14); + }, + + onInstallFailed: function(aInstall) { + do_throw("Should not have seen onInstallFailed event"); + }, + + onInstallCancelled: function(aInstall) { + do_throw("Should not have seen onInstallCancelled event"); + }, + }); + + AddonManagerInternal.backgroundUpdateCheck(); + }); +} + +function check_test_14() { + restartManager(); + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon8@tests.mozilla.org"], function([a1, a8]) { + do_check_neq(a1, null); + do_check_eq(a1.version, "2.0"); + a1.uninstall(); + + do_check_neq(a8, null); + do_check_eq(a8.version, "1.0"); + a8.uninstall(); + + do_execute_soon(run_test_15); + }); +} + +// Test that background update checks doesn't update an add-on that is +// pending uninstall +function run_test_15() { + restartManager(); + + // Have an add-on there that will be updated so we see some events from it + writeInstallRDFForExtension({ + id: "addon1@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 1", + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon8@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 8", + }, profileDir); + restartManager(); + + AddonManager.getAddonByID("addon8@tests.mozilla.org", function(a8) { + a8.uninstall(); + do_check_false(hasFlag(a8.permissions, AddonManager.PERM_CAN_UPGRADE)); + + // The background update check will find updates for both add-ons but only + // proceed to install one of them. + AddonManager.addInstallListener({ + onNewInstall: function(aInstall) { + if (aInstall.existingAddon.id != "addon1@tests.mozilla.org" && + aInstall.existingAddon.id != "addon8@tests.mozilla.org") + do_throw("Saw unexpected onNewInstall for " + aInstall.existingAddon.id); + }, + + onDownloadStarted: function(aInstall) { + do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); + }, + + onDownloadEnded: function(aInstall) { + do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); + }, + + onDownloadFailed: function(aInstall) { + do_throw("Should not have seen onDownloadFailed event"); + }, + + onDownloadCancelled: function(aInstall) { + do_throw("Should not have seen onDownloadCancelled event"); + }, + + onInstallStarted: function(aInstall) { + do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); + }, + + onInstallEnded: function(aInstall) { + do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); + do_execute_soon(check_test_15); + }, + + onInstallFailed: function(aInstall) { + do_throw("Should not have seen onInstallFailed event"); + }, + + onInstallCancelled: function(aInstall) { + do_throw("Should not have seen onInstallCancelled event"); + }, + }); + + AddonManagerInternal.backgroundUpdateCheck(); + }); +} + +function check_test_15() { + restartManager(); + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon8@tests.mozilla.org"], function([a1, a8]) { + do_check_neq(a1, null); + do_check_eq(a1.version, "2.0"); + a1.uninstall(); + + do_check_eq(a8, null); + + do_execute_soon(run_test_16); + }); +} + +function run_test_16() { + restartManager(); + + restartManager(); + + let url = "http://localhost:" + gPort + "/addons/test_install2_1.xpi"; + AddonManager.getInstallForURL(url, function(aInstall) { + aInstall.addListener({ + onInstallEnded: function() { + do_execute_soon(function install_2_1_ended() { + restartManager(); + + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a1) { + do_check_neq(a1.syncGUID, null); + let oldGUID = a1.syncGUID; + + let url = "http://localhost:" + gPort + "/addons/test_install2_2.xpi"; + AddonManager.getInstallForURL(url, function(aInstall) { + aInstall.addListener({ + onInstallEnded: function() { + do_execute_soon(function install_2_2_ended() { + restartManager(); + + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { + do_check_neq(a2.syncGUID, null); + do_check_eq(oldGUID, a2.syncGUID); + + a2.uninstall(); + do_execute_soon(run_test_17); + }); + }); + } + }); + aInstall.install(); + }, "application/x-xpinstall"); + }); + }); + } + }); + aInstall.install(); + }, "application/x-xpinstall"); +} + +// Test that the update check correctly observes the +// extensions.strictCompatibility pref and compatibility overrides. +function run_test_17() { + restartManager(); + + writeInstallRDFForExtension({ + id: "addon9@tests.mozilla.org", version: "1.0", updateURL: "http://localhost:" + gPort + "/data/test_update.rdf", targetApplications: [{ @@ -1369,30 +1151,160 @@ add_test(function run_test_locked_install() { minVersion: "0.1", maxVersion: "0.2" }], - name: "Test Addon 13", - }, lockedDir); + name: "Test Addon 9", + }, profileDir); restartManager(); - AddonManager.getAddonByID("addon13@tests.mozilla.org", function(a13) { - do_check_neq(a13, null); + AddonManager.addInstallListener({ + onNewInstall: function(aInstall) { + if (aInstall.existingAddon.id != "addon9@tests.mozilla.org") + do_throw("Saw unexpected onNewInstall for " + aInstall.existingAddon.id); + do_check_eq(aInstall.version, "3.0"); + }, + onDownloadFailed: function(aInstall) { + AddonManager.getAddonByID("addon9@tests.mozilla.org", function(a9) { + a9.uninstall(); + do_execute_soon(run_test_18); + }); + } + }); - a13.findUpdates({ - onCompatibilityUpdateAvailable: function() { - ok(false, "Should have not have seen compatibility information"); + Services.prefs.setCharPref(PREF_GETADDONS_BYIDS, + "http://localhost:" + gPort + "/data/test_update.xml"); + Services.prefs.setCharPref(PREF_GETADDONS_BYIDS_PERFORMANCE, + "http://localhost:" + gPort + "/data/test_update.xml"); + Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true); + + AddonManagerInternal.backgroundUpdateCheck(); +} + +// Tests that compatibility updates are applied to addons when the updated +// compatibility data wouldn't match with strict compatibility enabled. +function run_test_18() { + restartManager(); + writeInstallRDFForExtension({ + id: "addon10@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "0.1", + maxVersion: "0.2" + }], + name: "Test Addon 10", + }, profileDir); + restartManager(); + + AddonManager.getAddonByID("addon10@tests.mozilla.org", function(a10) { + do_check_neq(a10, null); + + a10.findUpdates({ + onNoCompatibilityUpdateAvailable: function() { + do_throw("Should have seen compatibility information"); }, onUpdateAvailable: function() { - ok(false, "Should not have seen an available update"); + do_throw("Should not have seen an available update"); }, onUpdateFinished: function() { - ok(true, "Should have seen an onUpdateFinished"); + a10.uninstall(); + do_execute_soon(run_test_19); } }, AddonManager.UPDATE_WHEN_USER_REQUESTED); }); +} - AddonManager.getAllInstalls(aInstalls => { - do_check_eq(aInstalls.length, 0); +// Test that the update check correctly observes when an addon opts-in to +// strict compatibility checking. +function run_test_19() { + restartManager(); + writeInstallRDFForExtension({ + id: "addon11@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "0.1", + maxVersion: "0.2" + }], + name: "Test Addon 11", + }, profileDir); + restartManager(); + + AddonManager.getAddonByID("addon11@tests.mozilla.org", function(a11) { + do_check_neq(a11, null); + + a11.findUpdates({ + onCompatibilityUpdateAvailable: function() { + do_throw("Should have not have seen compatibility information"); + }, + + onUpdateAvailable: function() { + do_throw("Should not have seen an available update"); + }, + + onUpdateFinished: function() { + a11.uninstall(); + do_execute_soon(run_test_20); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); + }); +} + +// Test that the update succeeds when the update.rdf URN contains a type prefix +// different from the add-on type +function run_test_20() { + restartManager(); + writeInstallRDFForExtension({ + id: "addon12@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 12", + }, profileDir); + restartManager(); + + prepare_test({}, [ + "onNewInstall", + "onDownloadStarted", + "onDownloadEnded" + ], continue_test_20); + + AddonManagerPrivate.backgroundUpdateCheck(); +} + +function continue_test_20(install) { + do_check_neq(install.existingAddon, null); + do_check_eq(install.existingAddon.id, "addon12@tests.mozilla.org"); + + prepare_test({ + "addon12@tests.mozilla.org": [ + "onInstalling" + ] + }, [ + "onInstallStarted", + "onInstallEnded", + ], callback_soon(check_test_20)); +} + +function check_test_20(install) { + do_check_eq(install.existingAddon.pendingUpgrade.install, install); + + restartManager(); + AddonManager.getAddonByID("addon12@tests.mozilla.org", function(a12) { + do_check_neq(a12, null); + do_check_eq(a12.version, "2.0"); + do_check_eq(a12.type, "extension"); + a12.uninstall(); + + do_execute_soon(() => { + restartManager(); + end_test(); + }); }); - run_next_test(); -}); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_updateCancel.js b/toolkit/mozapps/extensions/test/xpcshell/test_updateCancel.js index b50fd4a55..d513f4adf 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_updateCancel.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_updateCancel.js @@ -50,8 +50,9 @@ function makeCancelListener() { } // Set up the HTTP server so that we can control when it responds -var httpReceived = Promise.defer(); +let httpReceived = Promise.defer(); function dataHandler(aRequest, aResponse) { + asyncResponse = aResponse; aResponse.processAsync(); httpReceived.resolve([aRequest, aResponse]); } @@ -74,7 +75,7 @@ writeInstallRDFForExtension({ name: "Test Addon 1", }, profileDir); -add_task(function* cancel_during_check() { +add_task(function cancel_during_check() { startupManager(); let a1 = yield promiseAddonByID("addon1@tests.mozilla.org"); @@ -108,7 +109,7 @@ add_task(function* cancel_during_check() { // Test that update check is cancelled if the XPI provider shuts down while // the update check is in progress -add_task(function* shutdown_during_check() { +add_task(function shutdown_during_check() { // Reset our HTTP listener httpReceived = Promise.defer(); @@ -134,5 +135,8 @@ add_task(function* shutdown_during_check() { response.write(data); response.finish(); + // trying to cancel again should return false, i.e. nothing to cancel + do_check_false(a1.cancelUpdate()); + yield testserver.stop(Promise.defer().resolve); }); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_update_compatmode.js b/toolkit/mozapps/extensions/test/xpcshell/test_update_compatmode.js index a1d872009..6043b1792 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_update_compatmode.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_update_compatmode.js @@ -98,7 +98,7 @@ function run_test_1() { do_throw("Should have seen an available update"); }, - onUpdateAvailable: function(unused, install) { + onUpdateAvailable: function(addon, install) { do_check_eq(install.version, "2.0") }, @@ -124,7 +124,7 @@ function run_test_2() { do_throw("Should have seen an available update"); }, - onUpdateAvailable: function(unused, install) { + onUpdateAvailable: function(addon, install) { do_check_eq(install.version, "2.0") }, @@ -146,7 +146,7 @@ function run_test_3() { do_throw("Should have not have seen compatibility information"); }, - onUpdateAvailable: function() { + onUpdateAvailable: function(addon, install) { do_throw("Should not have seen an available update"); }, @@ -172,7 +172,7 @@ function run_test_4() { do_throw("Should have seen an available update"); }, - onUpdateAvailable: function(unused, install) { + onUpdateAvailable: function(addon, install) { do_check_eq(install.version, "2.0") }, diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_update_ignorecompat.js b/toolkit/mozapps/extensions/test/xpcshell/test_update_ignorecompat.js index e899619d6..672594088 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_update_ignorecompat.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_update_ignorecompat.js @@ -9,12 +9,12 @@ const PREF_GETADDONS_CACHE_ENABLED = "extensions.getAddons.cache.enabled"; // The test extension uses an insecure update url. Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false); -Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, false); -var testserver = createHttpServer(); +Components.utils.import("resource://testing-common/httpd.js"); +var testserver = new HttpServer(); +testserver.start(-1); gPort = testserver.identity.primaryPort; mapFile("/data/test_update.rdf", testserver); -mapFile("/data/test_update.json", testserver); mapFile("/data/test_update.xml", testserver); testserver.registerDirectory("/addons/", do_get_file("addons")); @@ -22,86 +22,77 @@ const profileDir = gProfD.clone(); profileDir.append("extensions"); -createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1"); - -let testParams = [ - { updateFile: "test_update.rdf", - appId: "xpcshell@tests.mozilla.org" }, - { updateFile: "test_update.json", - appId: "toolkit@mozilla.org" }, -]; - -for (let test of testParams) { - let { updateFile, appId } = test; - - // Test that the update check correctly observes the - // extensions.strictCompatibility pref and compatibility overrides. - add_test(function () { - writeInstallRDFForExtension({ - id: "addon9@tests.mozilla.org", - version: "1.0", - updateURL: "http://localhost:" + gPort + "/data/" + updateFile, - targetApplications: [{ - id: appId, - minVersion: "0.1", - maxVersion: "0.2" - }], - name: "Test Addon 9", - }, profileDir); - - restartManager(); - - AddonManager.addInstallListener({ - onNewInstall: function(aInstall) { - if (aInstall.existingAddon.id != "addon9@tests.mozilla.org") - do_throw("Saw unexpected onNewInstall for " + aInstall.existingAddon.id); - do_check_eq(aInstall.version, "4.0"); - }, - onDownloadFailed: function(aInstall) { - run_next_test(); - } - }); +function run_test() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); - Services.prefs.setCharPref(PREF_GETADDONS_BYIDS_PERFORMANCE, - "http://localhost:" + gPort + "/data/" + updateFile); - Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true); + run_test_1(); +} - AddonManagerInternal.backgroundUpdateCheck(); +// Test that the update check correctly observes the +// extensions.strictCompatibility pref and compatibility overrides. +function run_test_1() { + writeInstallRDFForExtension({ + id: "addon9@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "0.1", + maxVersion: "0.2" + }], + name: "Test Addon 9", + }, profileDir); + restartManager(); + + AddonManager.addInstallListener({ + onNewInstall: function(aInstall) { + if (aInstall.existingAddon.id != "addon9@tests.mozilla.org") + do_throw("Saw unexpected onNewInstall for " + aInstall.existingAddon.id); + do_check_eq(aInstall.version, "4.0"); + }, + onDownloadFailed: function(aInstall) { + do_execute_soon(run_test_2); + } }); - // Test that the update check correctly observes when an addon opts-in to - // strict compatibility checking. - add_test(function () { - writeInstallRDFForExtension({ - id: "addon11@tests.mozilla.org", - version: "1.0", - updateURL: "http://localhost:" + gPort + "/data/" + updateFile, - targetApplications: [{ - id: appId, - minVersion: "0.1", - maxVersion: "0.2" - }], - name: "Test Addon 11", - }, profileDir); - - restartManager(); - - AddonManager.getAddonByID("addon11@tests.mozilla.org", function(a11) { - do_check_neq(a11, null); - - a11.findUpdates({ - onCompatibilityUpdateAvailable: function() { - do_throw("Should not have seen compatibility information"); - }, - - onUpdateAvailable: function() { - do_throw("Should not have seen an available update"); - }, - - onUpdateFinished: function() { - run_next_test(); - } - }, AddonManager.UPDATE_WHEN_USER_REQUESTED); - }); + Services.prefs.setCharPref(PREF_GETADDONS_BYIDS_PERFORMANCE, + "http://localhost:" + gPort + "/data/test_update.xml"); + Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true); + + AddonManagerInternal.backgroundUpdateCheck(); +} + +// Test that the update check correctly observes when an addon opts-in to +// strict compatibility checking. +function run_test_2() { + writeInstallRDFForExtension({ + id: "addon11@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "0.1", + maxVersion: "0.2" + }], + name: "Test Addon 11", + }, profileDir); + restartManager(); + + AddonManager.getAddonByID("addon11@tests.mozilla.org", function(a11) { + do_check_neq(a11, null); + + a11.findUpdates({ + onCompatibilityUpdateAvailable: function() { + do_throw("Should have not have seen compatibility information"); + }, + + onNoUpdateAvailable: function() { + do_throw("Should have seen an available update"); + }, + + onUpdateFinished: function() { + end_test(); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); }); } diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_update_strictcompat.js b/toolkit/mozapps/extensions/test/xpcshell/test_update_strictcompat.js index 2b1f65a9f..0474535f1 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_update_strictcompat.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_update_strictcompat.js @@ -9,8 +9,7 @@ const PREF_SELECTED_LOCALE = "general.useragent.locale"; const PREF_GETADDONS_CACHE_ENABLED = "extensions.getAddons.cache.enabled"; // The test extension uses an insecure update url. -Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false); -Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, true); +Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); // This test requires lightweight themes update to be enabled even if the app // doesn't support lightweight themes. Services.prefs.setBoolPref("lightweightThemes.update.enabled", true); @@ -23,10 +22,11 @@ const PARAMS = "?%REQ_VERSION%/%ITEM_ID%/%ITEM_VERSION%/%ITEM_MAXAPPVERSION%/" + var gInstallDate; -var testserver = createHttpServer(); +Components.utils.import("resource://testing-common/httpd.js"); +var testserver = new HttpServer(); +testserver.start(-1); gPort = testserver.identity.primaryPort; mapFile("/data/test_update.rdf", testserver); -mapFile("/data/test_update.json", testserver); mapFile("/data/test_update.xml", testserver); testserver.registerDirectory("/addons/", do_get_file("addons")); @@ -34,1013 +34,383 @@ const profileDir = gProfD.clone(); profileDir.append("extensions"); function run_test() { - createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1"); - + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); Services.prefs.setBoolPref(PREF_MATCH_OS_LOCALE, false); Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "fr-FR"); + Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, true); + + writeInstallRDFForExtension({ + id: "addon1@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 1", + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon2@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "0", + maxVersion: "0" + }], + name: "Test Addon 2", + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon3@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "5", + maxVersion: "5" + }], + name: "Test Addon 3", + }, profileDir); - run_next_test(); -} - -let testParams = [ - { updateFile: "test_update.rdf", - appId: "xpcshell@tests.mozilla.org" }, - { updateFile: "test_update.json", - appId: "toolkit@mozilla.org" }, -]; - -for (let test of testParams) { - let { updateFile, appId } = test; - - add_test(function() { - writeInstallRDFForExtension({ - id: "addon1@tests.mozilla.org", - version: "1.0", - updateURL: "http://localhost:" + gPort + "/data/" + updateFile, - targetApplications: [{ - id: appId, - minVersion: "1", - maxVersion: "1" - }], - name: "Test Addon 1", - }, profileDir); - - writeInstallRDFForExtension({ - id: "addon2@tests.mozilla.org", - version: "1.0", - updateURL: "http://localhost:" + gPort + "/data/" + updateFile, - targetApplications: [{ - id: appId, - minVersion: "0", - maxVersion: "0" - }], - name: "Test Addon 2", - }, profileDir); - - writeInstallRDFForExtension({ - id: "addon3@tests.mozilla.org", - version: "1.0", - updateURL: "http://localhost:" + gPort + "/data/" + updateFile, - targetApplications: [{ - id: appId, - minVersion: "5", - maxVersion: "5" - }], - name: "Test Addon 3", - }, profileDir); - - startupManager(); - - run_next_test(); - }); - - // Verify that an update is available and can be installed. - let check_test_1; - add_test(function run_test_1() { - AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { - do_check_neq(a1, null); - do_check_eq(a1.version, "1.0"); - do_check_eq(a1.applyBackgroundUpdates, AddonManager.AUTOUPDATE_DEFAULT); - do_check_eq(a1.releaseNotesURI, null); - - a1.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DEFAULT; + startupManager(); - prepare_test({ - "addon1@tests.mozilla.org": [ - ["onPropertyChanged", ["applyBackgroundUpdates"]] - ] - }); - a1.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DISABLE; - check_test_completed(); + do_test_pending(); + run_test_1(); +} - a1.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DISABLE; +function end_test() { + Services.prefs.clearUserPref(PREF_EM_STRICT_COMPATIBILITY); - prepare_test({}, [ - "onNewInstall", - ]); + testserver.stop(do_test_finished); +} - a1.findUpdates({ - onNoCompatibilityUpdateAvailable: function(addon) { - ok(false, "Should not have seen onNoCompatibilityUpdateAvailable notification"); - }, +// Verify that an update is available and can be installed. +function run_test_1() { + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.version, "1.0"); + do_check_eq(a1.applyBackgroundUpdates, AddonManager.AUTOUPDATE_DEFAULT); + do_check_eq(a1.releaseNotesURI, null); - onUpdateAvailable: function(addon, install) { - ensure_test_completed(); - - AddonManager.getAllInstalls(function(aInstalls) { - do_check_eq(aInstalls.length, 1); - do_check_eq(aInstalls[0], install); - - do_check_eq(addon, a1); - do_check_eq(install.name, addon.name); - do_check_eq(install.version, "2.0"); - do_check_eq(install.state, AddonManager.STATE_AVAILABLE); - do_check_eq(install.existingAddon, addon); - do_check_eq(install.releaseNotesURI.spec, "http://example.com/updateInfo.xhtml"); - - // Verify that another update check returns the same AddonInstall - a1.findUpdates({ - onNoCompatibilityUpdateAvailable: function() { - ok(false, "Should not have seen onNoCompatibilityUpdateAvailable notification"); - }, - - onUpdateAvailable: function(newAddon, newInstall) { - AddonManager.getAllInstalls(function(aInstalls2) { - do_check_eq(aInstalls2.length, 1); - do_check_eq(aInstalls2[0], install); - do_check_eq(newAddon, addon); - do_check_eq(newInstall, install); - - prepare_test({}, [ - "onDownloadStarted", - "onDownloadEnded", - ], check_test_1); - install.install(); - }); - }, - - onNoUpdateAvailable: function() { - ok(false, "Should not have seen onNoUpdateAvailable notification"); - } - }, AddonManager.UPDATE_WHEN_USER_REQUESTED); - }); - }, + a1.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DEFAULT; - onNoUpdateAvailable: function(addon) { - ok(false, "Should not have seen onNoUpdateAvailable notification"); - } - }, AddonManager.UPDATE_WHEN_USER_REQUESTED); + prepare_test({ + "addon1@tests.mozilla.org": [ + ["onPropertyChanged", ["applyBackgroundUpdates"]] + ] }); - }); + a1.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DISABLE; + check_test_completed(); - let run_test_2; - check_test_1 = (install) => { - ensure_test_completed(); - do_check_eq(install.state, AddonManager.STATE_DOWNLOADED); - run_test_2(install); - return false; - }; + a1.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DISABLE; + + prepare_test({}, [ + "onNewInstall", + ]); - // Continue installing the update. - let check_test_2; - run_test_2 = (install) => { - // Verify that another update check returns no new update - install.existingAddon.findUpdates({ + a1.findUpdates({ onNoCompatibilityUpdateAvailable: function(addon) { - ok(false, "Should not have seen onNoCompatibilityUpdateAvailable notification"); + do_throw("Should not have seen onNoCompatibilityUpdateAvailable notification"); }, - onUpdateAvailable: function() { - ok(false, "Should find no available update when one is already downloading"); - }, + onUpdateAvailable: function(addon, install) { + ensure_test_completed(); - onNoUpdateAvailable: function(addon) { AddonManager.getAllInstalls(function(aInstalls) { do_check_eq(aInstalls.length, 1); do_check_eq(aInstalls[0], install); - prepare_test({ - "addon1@tests.mozilla.org": [ - "onInstalling" - ] - }, [ - "onInstallStarted", - "onInstallEnded", - ], check_test_2); - install.install(); + do_check_eq(addon, a1); + do_check_eq(install.name, addon.name); + do_check_eq(install.version, "2.0"); + do_check_eq(install.state, AddonManager.STATE_AVAILABLE); + do_check_eq(install.existingAddon, addon); + do_check_eq(install.releaseNotesURI.spec, "http://example.com/updateInfo.xhtml"); + + // Verify that another update check returns the same AddonInstall + a1.findUpdates({ + onNoCompatibilityUpdateAvailable: function(addon) { + do_throw("Should not have seen onNoCompatibilityUpdateAvailable notification"); + }, + + onUpdateAvailable: function(newAddon, newInstall) { + AddonManager.getAllInstalls(function(aInstalls) { + do_check_eq(aInstalls.length, 1); + do_check_eq(aInstalls[0], install); + do_check_eq(newAddon, addon); + do_check_eq(newInstall, install); + + prepare_test({}, [ + "onDownloadStarted", + "onDownloadEnded", + ], check_test_1); + install.install(); + }); + }, + + onNoUpdateAvailable: function(addon) { + do_throw("Should not have seen onNoUpdateAvailable notification"); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); }); + }, + + onNoUpdateAvailable: function(addon) { + do_throw("Should not have seen onNoUpdateAvailable notification"); } }, AddonManager.UPDATE_WHEN_USER_REQUESTED); - }; - - check_test_2 = () => { - ensure_test_completed(); - - AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(olda1) { - do_check_neq(olda1, null); - do_check_eq(olda1.version, "1.0"); - do_check_true(isExtensionInAddonsList(profileDir, olda1.id)); - - shutdownManager(); - - startupManager(); - - do_check_true(isExtensionInAddonsList(profileDir, "addon1@tests.mozilla.org")); - - AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { - do_check_neq(a1, null); - do_check_eq(a1.version, "2.0"); - do_check_true(isExtensionInAddonsList(profileDir, a1.id)); - do_check_eq(a1.applyBackgroundUpdates, AddonManager.AUTOUPDATE_DISABLE); - do_check_eq(a1.releaseNotesURI.spec, "http://example.com/updateInfo.xhtml"); - - a1.uninstall(); - run_next_test(); - }); - })); - }; - - - // Check that an update check finds compatibility updates and applies them - let check_test_3; - add_test(function run_test_3() { - restartManager(); - - AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { - do_check_neq(a2, null); - do_check_false(a2.isActive); - do_check_false(a2.isCompatible); - do_check_true(a2.appDisabled); - do_check_true(a2.isCompatibleWith("0", "0")); - - a2.findUpdates({ - onCompatibilityUpdateAvailable: function(addon) { - do_check_true(a2.isCompatible); - do_check_false(a2.appDisabled); - do_check_false(a2.isActive); - }, - - onUpdateAvailable: function(addon, install) { - ok(false, "Should not have seen an available update"); - }, - - onNoUpdateAvailable: function(addon) { - do_check_eq(addon, a2); - do_execute_soon(check_test_3); - } - }, AddonManager.UPDATE_WHEN_USER_REQUESTED); - }); - }); - - check_test_3 = () => { - restartManager(); - AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { - do_check_neq(a2, null); - do_check_true(a2.isActive); - do_check_true(a2.isCompatible); - do_check_false(a2.appDisabled); - a2.uninstall(); - - run_next_test(); - }); - } - - // Checks that we see no compatibility information when there is none. - add_test(function run_test_4() { - AddonManager.getAddonByID("addon3@tests.mozilla.org", function(a3) { - do_check_neq(a3, null); - do_check_false(a3.isActive); - do_check_false(a3.isCompatible); - do_check_true(a3.appDisabled); - do_check_true(a3.isCompatibleWith("5", "5")); - do_check_false(a3.isCompatibleWith("2", "2")); - - a3.findUpdates({ - sawUpdate: false, - onCompatibilityUpdateAvailable: function(addon) { - ok(false, "Should not have seen compatibility information"); - }, - - onNoCompatibilityUpdateAvailable: function(addon) { - this.sawUpdate = true; - }, - - onUpdateAvailable: function(addon, install) { - ok(false, "Should not have seen an available update"); - }, - - onNoUpdateAvailable: function(addon) { - do_check_true(this.sawUpdate); - run_next_test(); - } - }, AddonManager.UPDATE_WHEN_USER_REQUESTED); - }); - }); - - // Checks that compatibility info for future apps are detected but don't make - // the item compatibile. - let check_test_5; - add_test(function run_test_5() { - AddonManager.getAddonByID("addon3@tests.mozilla.org", function(a3) { - do_check_neq(a3, null); - do_check_false(a3.isActive); - do_check_false(a3.isCompatible); - do_check_true(a3.appDisabled); - do_check_true(a3.isCompatibleWith("5", "5")); - do_check_false(a3.isCompatibleWith("2", "2")); - - a3.findUpdates({ - sawUpdate: false, - onCompatibilityUpdateAvailable: function(addon) { - do_check_false(a3.isCompatible); - do_check_true(a3.appDisabled); - do_check_false(a3.isActive); - this.sawUpdate = true; - }, - - onNoCompatibilityUpdateAvailable: function(addon) { - ok(false, "Should have seen some compatibility information"); - }, - - onUpdateAvailable: function(addon, install) { - ok(false, "Should not have seen an available update"); - }, - - onNoUpdateAvailable: function(addon) { - do_check_true(this.sawUpdate); - do_execute_soon(check_test_5); - } - }, AddonManager.UPDATE_WHEN_USER_REQUESTED, "3.0", "3.0"); - }); }); +} - check_test_5 = () => { - restartManager(); - AddonManager.getAddonByID("addon3@tests.mozilla.org", function(a3) { - do_check_neq(a3, null); - do_check_false(a3.isActive); - do_check_false(a3.isCompatible); - do_check_true(a3.appDisabled); - - a3.uninstall(); - run_next_test(); - }); - } - - // Test that background update checks work - let continue_test_6; - add_test(function run_test_6() { - restartManager(); +function check_test_1(install) { + ensure_test_completed(); + do_check_eq(install.state, AddonManager.STATE_DOWNLOADED); + run_test_2(install); + return false; +} - writeInstallRDFForExtension({ - id: "addon1@tests.mozilla.org", - version: "1.0", - updateURL: "http://localhost:" + gPort + "/data/" + updateFile, - targetApplications: [{ - id: appId, - minVersion: "1", - maxVersion: "1" - }], - name: "Test Addon 1", - }, profileDir); - restartManager(); +// Continue installing the update. +function run_test_2(install) { + // Verify that another update check returns no new update + install.existingAddon.findUpdates({ + onNoCompatibilityUpdateAvailable: function(addon) { + do_throw("Should not have seen onNoCompatibilityUpdateAvailable notification"); + }, + + onUpdateAvailable: function(addon, install) { + do_throw("Should find no available update when one is already downloading"); + }, + + onNoUpdateAvailable: function(addon) { + AddonManager.getAllInstalls(function(aInstalls) { + do_check_eq(aInstalls.length, 1); + do_check_eq(aInstalls[0], install); + + prepare_test({ + "addon1@tests.mozilla.org": [ + "onInstalling" + ] + }, [ + "onInstallStarted", + "onInstallEnded", + ], check_test_2); + install.install(); + }); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); +} - prepare_test({}, [ - "onNewInstall", - "onDownloadStarted", - "onDownloadEnded" - ], continue_test_6); +function check_test_2() { + ensure_test_completed(); - AddonManagerInternal.backgroundUpdateCheck(); - }); + AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(olda1) { + do_check_neq(olda1, null); + do_check_eq(olda1.version, "1.0"); + do_check_true(isExtensionInAddonsList(profileDir, olda1.id)); - let check_test_6; - continue_test_6 = (install) => { - do_check_neq(install.existingAddon, null); - do_check_eq(install.existingAddon.id, "addon1@tests.mozilla.org"); + shutdownManager(); - prepare_test({ - "addon1@tests.mozilla.org": [ - "onInstalling" - ] - }, [ - "onInstallStarted", - "onInstallEnded", - ], callback_soon(check_test_6)); - } + startupManager(); - check_test_6 = (install) => { - do_check_eq(install.existingAddon.pendingUpgrade.install, install); + do_check_true(isExtensionInAddonsList(profileDir, olda1.id)); - restartManager(); AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { do_check_neq(a1, null); do_check_eq(a1.version, "2.0"); + do_check_true(isExtensionInAddonsList(profileDir, a1.id)); + do_check_eq(a1.applyBackgroundUpdates, AddonManager.AUTOUPDATE_DISABLE); do_check_eq(a1.releaseNotesURI.spec, "http://example.com/updateInfo.xhtml"); - a1.uninstall(); - run_next_test(); - }); - } - - // Verify the parameter escaping in update urls. - add_test(function run_test_8() { - restartManager(); - - writeInstallRDFForExtension({ - id: "addon1@tests.mozilla.org", - version: "5.0", - updateURL: "http://localhost:" + gPort + "/data/param_test.rdf" + PARAMS, - targetApplications: [{ - id: appId, - minVersion: "1", - maxVersion: "2" - }], - name: "Test Addon 1", - }, profileDir); - - writeInstallRDFForExtension({ - id: "addon2@tests.mozilla.org", - version: "67.0.5b1", - updateURL: "http://localhost:" + gPort + "/data/param_test.rdf" + PARAMS, - targetApplications: [{ - id: "toolkit@mozilla.org", - minVersion: "0", - maxVersion: "3" - }], - name: "Test Addon 2", - }, profileDir); - - writeInstallRDFForExtension({ - id: "addon3@tests.mozilla.org", - version: "1.3+", - updateURL: "http://localhost:" + gPort + "/data/param_test.rdf" + PARAMS, - targetApplications: [{ - id: appId, - minVersion: "0", - maxVersion: "0" - }, { - id: "toolkit@mozilla.org", - minVersion: "0", - maxVersion: "3" - }], - name: "Test Addon 3", - }, profileDir); - - writeInstallRDFForExtension({ - id: "addon4@tests.mozilla.org", - version: "0.5ab6", - updateURL: "http://localhost:" + gPort + "/data/param_test.rdf" + PARAMS, - targetApplications: [{ - id: appId, - minVersion: "1", - maxVersion: "5" - }], - name: "Test Addon 4", - }, profileDir); - - writeInstallRDFForExtension({ - id: "addon5@tests.mozilla.org", - version: "1.0", - updateURL: "http://localhost:" + gPort + "/data/param_test.rdf" + PARAMS, - targetApplications: [{ - id: appId, - minVersion: "1", - maxVersion: "1" - }], - name: "Test Addon 5", - }, profileDir); - - writeInstallRDFForExtension({ - id: "addon6@tests.mozilla.org", - version: "1.0", - updateURL: "http://localhost:" + gPort + "/data/param_test.rdf" + PARAMS, - targetApplications: [{ - id: appId, - minVersion: "1", - maxVersion: "1" - }], - name: "Test Addon 6", - }, profileDir); - - restartManager(); - - AddonManager.getAddonByID("addon2@tests.mozilla.org", callback_soon(function(a2) { - a2.userDisabled = true; - restartManager(); - - testserver.registerPathHandler("/data/param_test.rdf", function(request, response) { - do_check_neq(request.queryString, ""); - let [req_version, item_id, item_version, - item_maxappversion, item_status, - app_id, app_version, current_app_version, - app_os, app_abi, app_locale, update_type] = - request.queryString.split("/").map(a => decodeURIComponent(a)); - - do_check_eq(req_version, "2"); - - switch (item_id) { - case "addon1@tests.mozilla.org": - do_check_eq(item_version, "5.0"); - do_check_eq(item_maxappversion, "2"); - do_check_eq(item_status, "userEnabled"); - do_check_eq(app_version, "1"); - do_check_eq(update_type, "97"); - break; - case "addon2@tests.mozilla.org": - do_check_eq(item_version, "67.0.5b1"); - do_check_eq(item_maxappversion, "3"); - do_check_eq(item_status, "userDisabled"); - do_check_eq(app_version, "1"); - do_check_eq(update_type, "49"); - break; - case "addon3@tests.mozilla.org": - do_check_eq(item_version, "1.3+"); - do_check_eq(item_maxappversion, "0"); - do_check_eq(item_status, "userEnabled,incompatible"); - do_check_eq(app_version, "1"); - do_check_eq(update_type, "112"); - break; - case "addon4@tests.mozilla.org": - do_check_eq(item_version, "0.5ab6"); - do_check_eq(item_maxappversion, "5"); - do_check_eq(item_status, "userEnabled"); - do_check_eq(app_version, "2"); - do_check_eq(update_type, "98"); - break; - case "addon5@tests.mozilla.org": - do_check_eq(item_version, "1.0"); - do_check_eq(item_maxappversion, "1"); - do_check_eq(item_status, "userEnabled"); - do_check_eq(app_version, "1"); - do_check_eq(update_type, "35"); - break; - case "addon6@tests.mozilla.org": - do_check_eq(item_version, "1.0"); - do_check_eq(item_maxappversion, "1"); - do_check_eq(item_status, "userEnabled"); - do_check_eq(app_version, "1"); - do_check_eq(update_type, "99"); - break; - default: - ok(false, "Update request for unexpected add-on " + item_id); - } - - do_check_eq(app_id, "xpcshell@tests.mozilla.org"); - do_check_eq(current_app_version, "1"); - do_check_eq(app_os, "XPCShell"); - do_check_eq(app_abi, "noarch-spidermonkey"); - do_check_eq(app_locale, "fr-FR"); - - request.setStatusLine(null, 500, "Server Error"); - }); - - AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", - "addon2@tests.mozilla.org", - "addon3@tests.mozilla.org", - "addon4@tests.mozilla.org", - "addon5@tests.mozilla.org", - "addon6@tests.mozilla.org"], - function([a1_2, a2_2, a3_2, a4_2, a5_2, a6_2]) { - let count = 6; - - function next_test() { - a1_2.uninstall(); - a2_2.uninstall(); - a3_2.uninstall(); - a4_2.uninstall(); - a5_2.uninstall(); - a6_2.uninstall(); - - restartManager(); - run_next_test(); - } - - let compatListener = { - onUpdateFinished: function(addon, error) { - if (--count == 0) - do_execute_soon(next_test); - } - }; - - let updateListener = { - onUpdateAvailable: function(addon, update) { - // Dummy so the update checker knows we care about new versions - }, - - onUpdateFinished: function(addon, error) { - if (--count == 0) - do_execute_soon(next_test); - } - }; - - a1_2.findUpdates(updateListener, AddonManager.UPDATE_WHEN_USER_REQUESTED); - a2_2.findUpdates(compatListener, AddonManager.UPDATE_WHEN_ADDON_INSTALLED); - a3_2.findUpdates(updateListener, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE); - a4_2.findUpdates(updateListener, AddonManager.UPDATE_WHEN_NEW_APP_DETECTED, "2"); - a5_2.findUpdates(compatListener, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED); - a6_2.findUpdates(updateListener, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED); - }); - })); - }); - - // Tests that if an install.rdf claims compatibility then the add-on will be - // seen as compatible regardless of what the update.rdf says. - add_test(function run_test_9() { - writeInstallRDFForExtension({ - id: "addon4@tests.mozilla.org", - version: "5.0", - updateURL: "http://localhost:" + gPort + "/data/" + updateFile, - targetApplications: [{ - id: appId, - minVersion: "0", - maxVersion: "1" - }], - name: "Test Addon 1", - }, profileDir); - - restartManager(); - - AddonManager.getAddonByID("addon4@tests.mozilla.org", function(a4) { - do_check_true(a4.isActive, "addon4 is active"); - do_check_true(a4.isCompatible, "addon4 is compatible"); - - run_next_test(); - }); - }); - - // Tests that a normal update check won't decrease a targetApplication's - // maxVersion. - add_test(function run_test_10() { - AddonManager.getAddonByID("addon4@tests.mozilla.org", function(a4) { - a4.findUpdates({ - onUpdateFinished: function(addon) { - do_check_true(addon.isCompatible, "addon4 is compatible"); - - run_next_test(); - } - }, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE); - }); - }); - // Tests that an update check for a new application will decrease a - // targetApplication's maxVersion. - add_test(function run_test_11() { - AddonManager.getAddonByID("addon4@tests.mozilla.org", function(a4) { - a4.findUpdates({ - onUpdateFinished: function(addon) { - do_check_false(addon.isCompatible, "addon4 is compatible"); - - run_next_test(); - } - }, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED); + a1.uninstall(); + do_execute_soon(run_test_3); }); - }); - - // Check that the decreased maxVersion applied and disables the add-on - add_test(function run_test_12() { - restartManager(); - - AddonManager.getAddonByID("addon4@tests.mozilla.org", function(a4) { - do_check_false(a4.isActive, "addon4 is active"); - do_check_false(a4.isCompatible, "addon4 is compatible"); + })); +} - a4.uninstall(); - run_next_test(); - }); - }); - // Tests that no compatibility update is passed to the listener when there is - // compatibility info for the current version of the app but not for the - // version of the app that the caller requested an update check for. - let check_test_13; - add_test(function run_test_13() { - restartManager(); +// Check that an update check finds compatibility updates and applies them +function run_test_3() { + restartManager(); - // Not initially compatible but the update check will make it compatible - writeInstallRDFForExtension({ - id: "addon7@tests.mozilla.org", - version: "1.0", - updateURL: "http://localhost:" + gPort + "/data/" + updateFile, - targetApplications: [{ - id: appId, - minVersion: "0", - maxVersion: "0" - }], - name: "Test Addon 7", - }, profileDir); - restartManager(); + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { + do_check_neq(a2, null); + do_check_false(a2.isActive); + do_check_false(a2.isCompatible); + do_check_true(a2.appDisabled); + do_check_true(a2.isCompatibleWith("0")); - AddonManager.getAddonByID("addon7@tests.mozilla.org", function(a7) { - do_check_neq(a7, null); - do_check_false(a7.isActive); - do_check_false(a7.isCompatible); - do_check_true(a7.appDisabled); - do_check_true(a7.isCompatibleWith("0", "0")); - - a7.findUpdates({ - sawUpdate: false, - onCompatibilityUpdateAvailable: function(addon) { - ok(false, "Should not have seen compatibility information"); - }, + a2.findUpdates({ + onCompatibilityUpdateAvailable: function(addon) { + do_check_true(a2.isCompatible); + do_check_false(a2.appDisabled); + do_check_false(a2.isActive); + }, - onUpdateAvailable: function(addon, install) { - ok(false, "Should not have seen an available update"); - }, + onUpdateAvailable: function(addon, install) { + do_throw("Should not have seen an available update"); + }, - onUpdateFinished: function(addon) { - do_check_true(addon.isCompatible); - do_execute_soon(check_test_13); - } - }, AddonManager.UPDATE_WHEN_NEW_APP_DETECTED, "3.0", "3.0"); - }); + onNoUpdateAvailable: function(addon) { + do_check_eq(addon, a2); + do_execute_soon(check_test_3); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); }); +} - check_test_13 = () => { - restartManager(); - AddonManager.getAddonByID("addon7@tests.mozilla.org", function(a7) { - do_check_neq(a7, null); - do_check_true(a7.isActive); - do_check_true(a7.isCompatible); - do_check_false(a7.appDisabled); - - a7.uninstall(); - run_next_test(); - }); - } - - // Test that background update checks doesn't update an add-on that isn't - // allowed to update automatically. - let check_test_14; - add_test(function run_test_14() { - restartManager(); - - // Have an add-on there that will be updated so we see some events from it - writeInstallRDFForExtension({ - id: "addon1@tests.mozilla.org", - version: "1.0", - updateURL: "http://localhost:" + gPort + "/data/" + updateFile, - targetApplications: [{ - id: appId, - minVersion: "1", - maxVersion: "1" - }], - name: "Test Addon 1", - }, profileDir); - - writeInstallRDFForExtension({ - id: "addon8@tests.mozilla.org", - version: "1.0", - updateURL: "http://localhost:" + gPort + "/data/" + updateFile, - targetApplications: [{ - id: appId, - minVersion: "1", - maxVersion: "1" - }], - name: "Test Addon 8", - }, profileDir); - restartManager(); - - AddonManager.getAddonByID("addon8@tests.mozilla.org", function(a8) { - a8.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DISABLE; - - // The background update check will find updates for both add-ons but only - // proceed to install one of them. - AddonManager.addInstallListener({ - onNewInstall: function(aInstall) { - let id = aInstall.existingAddon.id; - ok((id == "addon1@tests.mozilla.org" || id == "addon8@tests.mozilla.org"), - "Saw unexpected onNewInstall for " + id); - }, - - onDownloadStarted: function(aInstall) { - do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); - }, - - onDownloadEnded: function(aInstall) { - do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); - }, - - onDownloadFailed: function(aInstall) { - ok(false, "Should not have seen onDownloadFailed event"); - }, - - onDownloadCancelled: function(aInstall) { - ok(false, "Should not have seen onDownloadCancelled event"); - }, - - onInstallStarted: function(aInstall) { - do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); - }, - - onInstallEnded: function(aInstall) { - do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); - do_check_eq(aInstall.existingAddon.pendingUpgrade.install, aInstall); - - do_execute_soon(check_test_14); - }, - - onInstallFailed: function(aInstall) { - ok(false, "Should not have seen onInstallFailed event"); - }, - - onInstallCancelled: function(aInstall) { - ok(false, "Should not have seen onInstallCancelled event"); - }, - }); +function check_test_3() { + restartManager(); + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { + do_check_neq(a2, null); + do_check_true(a2.isActive); + do_check_true(a2.isCompatible); + do_check_false(a2.appDisabled); + a2.uninstall(); - AddonManagerInternal.backgroundUpdateCheck(); - }); + run_test_4(); }); +} - check_test_14 = () => { - restartManager(); - AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", - "addon8@tests.mozilla.org"], function([a1, a8]) { - do_check_neq(a1, null); - do_check_eq(a1.version, "2.0"); - a1.uninstall(); - - do_check_neq(a8, null); - do_check_eq(a8.version, "1.0"); - a8.uninstall(); - - run_next_test(); - }); - } - - // Test that background update checks doesn't update an add-on that is - // pending uninstall - let check_test_15; - add_test(function run_test_15() { - restartManager(); - - // Have an add-on there that will be updated so we see some events from it - writeInstallRDFForExtension({ - id: "addon1@tests.mozilla.org", - version: "1.0", - updateURL: "http://localhost:" + gPort + "/data/" + updateFile, - targetApplications: [{ - id: appId, - minVersion: "1", - maxVersion: "1" - }], - name: "Test Addon 1", - }, profileDir); - - writeInstallRDFForExtension({ - id: "addon8@tests.mozilla.org", - version: "1.0", - updateURL: "http://localhost:" + gPort + "/data/" + updateFile, - targetApplications: [{ - id: appId, - minVersion: "1", - maxVersion: "1" - }], - name: "Test Addon 8", - }, profileDir); - restartManager(); - - AddonManager.getAddonByID("addon8@tests.mozilla.org", function(a8) { - a8.uninstall(); - do_check_false(hasFlag(a8.permissions, AddonManager.PERM_CAN_UPGRADE)); - - // The background update check will find updates for both add-ons but only - // proceed to install one of them. - AddonManager.addInstallListener({ - onNewInstall: function(aInstall) { - let id = aInstall.existingAddon.id; - ok((id == "addon1@tests.mozilla.org" || id == "addon8@tests.mozilla.org"), - "Saw unexpected onNewInstall for " + id); - }, - - onDownloadStarted: function(aInstall) { - do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); - }, - - onDownloadEnded: function(aInstall) { - do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); - }, - - onDownloadFailed: function(aInstall) { - ok(false, "Should not have seen onDownloadFailed event"); - }, - - onDownloadCancelled: function(aInstall) { - ok(false, "Should not have seen onDownloadCancelled event"); - }, - - onInstallStarted: function(aInstall) { - do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); - }, - - onInstallEnded: function(aInstall) { - do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); - do_execute_soon(check_test_15); - }, +// Checks that we see no compatibility information when there is none. +function run_test_4() { + AddonManager.getAddonByID("addon3@tests.mozilla.org", function(a3) { + do_check_neq(a3, null); + do_check_false(a3.isActive); + do_check_false(a3.isCompatible); + do_check_true(a3.appDisabled); + do_check_true(a3.isCompatibleWith("5")); + do_check_false(a3.isCompatibleWith("2")); + + a3.findUpdates({ + sawUpdate: false, + onCompatibilityUpdateAvailable: function(addon) { + do_throw("Should not have seen compatibility information"); + }, - onInstallFailed: function(aInstall) { - ok(false, "Should not have seen onInstallFailed event"); - }, + onNoCompatibilityUpdateAvailable: function(addon) { + this.sawUpdate = true; + }, - onInstallCancelled: function(aInstall) { - ok(false, "Should not have seen onInstallCancelled event"); - }, - }); + onUpdateAvailable: function(addon, install) { + do_throw("Should not have seen an available update"); + }, - AddonManagerInternal.backgroundUpdateCheck(); - }); + onNoUpdateAvailable: function(addon) { + do_check_true(this.sawUpdate); + run_test_5(); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); }); +} - check_test_15 = () => { - restartManager(); - AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", - "addon8@tests.mozilla.org"], function([a1, a8]) { - do_check_neq(a1, null); - do_check_eq(a1.version, "2.0"); - a1.uninstall(); - - do_check_eq(a8, null); - - run_next_test(); - }); - } - - // Test that the update check correctly observes the - // extensions.strictCompatibility pref and compatibility overrides. - add_test(function run_test_17() { - restartManager(); - - writeInstallRDFForExtension({ - id: "addon9@tests.mozilla.org", - version: "1.0", - updateURL: "http://localhost:" + gPort + "/data/" + updateFile, - targetApplications: [{ - id: appId, - minVersion: "0.1", - maxVersion: "0.2" - }], - name: "Test Addon 9", - }, profileDir); - restartManager(); +// Checks that compatibility info for future apps are detected but don't make +// the item compatibile. +function run_test_5() { + AddonManager.getAddonByID("addon3@tests.mozilla.org", function(a3) { + do_check_neq(a3, null); + do_check_false(a3.isActive); + do_check_false(a3.isCompatible); + do_check_true(a3.appDisabled); + do_check_true(a3.isCompatibleWith("5")); + do_check_false(a3.isCompatibleWith("2")); + + a3.findUpdates({ + sawUpdate: false, + onCompatibilityUpdateAvailable: function(addon) { + do_check_false(a3.isCompatible); + do_check_true(a3.appDisabled); + do_check_false(a3.isActive); + this.sawUpdate = true; + }, - AddonManager.addInstallListener({ - onNewInstall: function(aInstall) { - equal(aInstall.existingAddon.id, "addon9@tests.mozilla.org", - "Saw unexpected onNewInstall for " + aInstall.existingAddon.id); - do_check_eq(aInstall.version, "2.0"); + onNoCompatibilityUpdateAvailable: function(addon) { + do_throw("Should have seen some compatibility information"); }, - onDownloadFailed: function(aInstall) { - AddonManager.getAddonByID("addon9@tests.mozilla.org", function(a9) { - a9.uninstall(); - run_next_test(); - }); - } - }); - Services.prefs.setCharPref(PREF_GETADDONS_BYIDS, - "http://localhost:" + gPort + "/data/test_update.xml"); - Services.prefs.setCharPref(PREF_GETADDONS_BYIDS_PERFORMANCE, - "http://localhost:" + gPort + "/data/test_update.xml"); - Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true); + onUpdateAvailable: function(addon, install) { + do_throw("Should not have seen an available update"); + }, - AddonManagerInternal.backgroundUpdateCheck(); + onNoUpdateAvailable: function(addon) { + do_check_true(this.sawUpdate); + do_execute_soon(check_test_5); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED, "3.0"); }); +} - // Test that the update check correctly observes when an addon opts-in to - // strict compatibility checking. - add_test(function run_test_19() { - restartManager(); - writeInstallRDFForExtension({ - id: "addon11@tests.mozilla.org", - version: "1.0", - updateURL: "http://localhost:" + gPort + "/data/" + updateFile, - targetApplications: [{ - id: appId, - minVersion: "0.1", - maxVersion: "0.2" - }], - name: "Test Addon 11", - }, profileDir); - restartManager(); - - AddonManager.getAddonByID("addon11@tests.mozilla.org", function(a11) { - do_check_neq(a11, null); - - a11.findUpdates({ - onCompatibilityUpdateAvailable: function() { - ok(false, "Should have not have seen compatibility information"); - }, - - onUpdateAvailable: function() { - ok(false, "Should not have seen an available update"); - }, +function check_test_5() { + restartManager(); + AddonManager.getAddonByID("addon3@tests.mozilla.org", function(a3) { + do_check_neq(a3, null); + do_check_false(a3.isActive); + do_check_false(a3.isCompatible); + do_check_true(a3.appDisabled); - onUpdateFinished: function() { - run_next_test(); - } - }, AddonManager.UPDATE_WHEN_USER_REQUESTED); - }); + a3.uninstall(); + do_execute_soon(run_test_6); }); +} - add_task(function* cleanup() { - let addons = yield new Promise(resolve => { - AddonManager.getAddonsByTypes(["extension"], resolve); - }); - - for (let addon of addons) - addon.uninstall(); +// Test that background update checks work +function run_test_6() { + restartManager(); + + writeInstallRDFForExtension({ + id: "addon1@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 1", + }, profileDir); + restartManager(); + + prepare_test({}, [ + "onNewInstall", + "onDownloadStarted", + "onDownloadEnded" + ], continue_test_6); + + AddonManagerInternal.backgroundUpdateCheck(); +} - yield promiseRestartManager(); +function continue_test_6(install) { + do_check_neq(install.existingAddon, null); + do_check_eq(install.existingAddon.id, "addon1@tests.mozilla.org"); + + prepare_test({ + "addon1@tests.mozilla.org": [ + "onInstalling" + ] + }, [ + "onInstallStarted", + "onInstallEnded", + ], callback_soon(check_test_6)); +} - shutdownManager(); +function check_test_6(install) { + do_check_eq(install.existingAddon.pendingUpgrade.install, install); - yield new Promise(do_execute_soon); + restartManager(); + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.version, "2.0"); + do_check_eq(a1.releaseNotesURI.spec, "http://example.com/updateInfo.xhtml"); + a1.uninstall(); + do_execute_soon(run_test_7); }); } // Test that background update checks work for lightweight themes -add_test(function run_test_7() { - startupManager(); +function run_test_7() { + restartManager(); LightweightThemeManager.currentTheme = { id: "1", @@ -1104,7 +474,7 @@ add_test(function run_test_7() { AddonManagerInternal.backgroundUpdateCheck(); }); -}); +} function check_test_7() { AddonManager.getAddonByID("1@personas.mozilla.org", function(p1) { @@ -1121,6 +491,595 @@ function check_test_7() { gInstallDate = p1.installDate.getTime(); - run_next_test(); + do_execute_soon(run_test_8); + }); +} + +// Verify the parameter escaping in update urls. +function run_test_8() { + writeInstallRDFForExtension({ + id: "addon1@tests.mozilla.org", + version: "5.0", + updateURL: "http://localhost:" + gPort + "/data/param_test.rdf" + PARAMS, + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "2" + }], + name: "Test Addon 1", + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon2@tests.mozilla.org", + version: "67.0.5b1", + updateURL: "http://localhost:" + gPort + "/data/param_test.rdf" + PARAMS, + targetApplications: [{ + id: "toolkit@mozilla.org", + minVersion: "0", + maxVersion: "3" + }], + name: "Test Addon 2", + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon3@tests.mozilla.org", + version: "1.3+", + updateURL: "http://localhost:" + gPort + "/data/param_test.rdf" + PARAMS, + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "0", + maxVersion: "0" + }, { + id: "toolkit@mozilla.org", + minVersion: "0", + maxVersion: "3" + }], + name: "Test Addon 3", + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon4@tests.mozilla.org", + version: "0.5ab6", + updateURL: "http://localhost:" + gPort + "/data/param_test.rdf" + PARAMS, + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "5" + }], + name: "Test Addon 4", + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon5@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/param_test.rdf" + PARAMS, + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 5", + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon6@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/param_test.rdf" + PARAMS, + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 6", + }, profileDir); + + restartManager(); + + AddonManager.getAddonByID("addon2@tests.mozilla.org", callback_soon(function(a2) { + a2.userDisabled = true; + restartManager(); + + testserver.registerPathHandler("/data/param_test.rdf", function(request, response) { + do_check_neq(request.queryString, ""); + let [req_version, item_id, item_version, + item_maxappversion, item_status, + app_id, app_version, current_app_version, + app_os, app_abi, app_locale, update_type] = + [decodeURIComponent(a) for each (a in request.queryString.split("/"))]; + + do_check_eq(req_version, "2"); + + switch(item_id) { + case "addon1@tests.mozilla.org": + do_check_eq(item_version, "5.0"); + do_check_eq(item_maxappversion, "2"); + do_check_eq(item_status, "userEnabled"); + do_check_eq(app_version, "1"); + do_check_eq(update_type, "97"); + break; + case "addon2@tests.mozilla.org": + do_check_eq(item_version, "67.0.5b1"); + do_check_eq(item_maxappversion, "3"); + do_check_eq(item_status, "userDisabled"); + do_check_eq(app_version, "1"); + do_check_eq(update_type, "49"); + break; + case "addon3@tests.mozilla.org": + do_check_eq(item_version, "1.3+"); + do_check_eq(item_maxappversion, "0"); + do_check_eq(item_status, "userEnabled,incompatible"); + do_check_eq(app_version, "1"); + do_check_eq(update_type, "112"); + break; + case "addon4@tests.mozilla.org": + do_check_eq(item_version, "0.5ab6"); + do_check_eq(item_maxappversion, "5"); + do_check_eq(item_status, "userEnabled"); + do_check_eq(app_version, "2"); + do_check_eq(update_type, "98"); + break; + case "addon5@tests.mozilla.org": + do_check_eq(item_version, "1.0"); + do_check_eq(item_maxappversion, "1"); + do_check_eq(item_status, "userEnabled"); + do_check_eq(app_version, "1"); + do_check_eq(update_type, "35"); + break; + case "addon6@tests.mozilla.org": + do_check_eq(item_version, "1.0"); + do_check_eq(item_maxappversion, "1"); + do_check_eq(item_status, "userEnabled"); + do_check_eq(app_version, "1"); + do_check_eq(update_type, "99"); + break; + default: + do_throw("Update request for unexpected add-on " + item_id); + } + + do_check_eq(app_id, "xpcshell@tests.mozilla.org"); + do_check_eq(current_app_version, "1"); + do_check_eq(app_os, "XPCShell"); + do_check_eq(app_abi, "noarch-spidermonkey"); + do_check_eq(app_locale, "fr-FR"); + + request.setStatusLine(null, 500, "Server Error"); + }); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org", + "addon5@tests.mozilla.org", + "addon6@tests.mozilla.org"], + function([a1, a2, a3, a4, a5, a6]) { + let count = 6; + + function run_next_test() { + a1.uninstall(); + a2.uninstall(); + a3.uninstall(); + a4.uninstall(); + a5.uninstall(); + a6.uninstall(); + + restartManager(); + run_test_9(); + } + + let compatListener = { + onUpdateFinished: function(addon, error) { + if (--count == 0) + do_execute_soon(run_next_test); + } + }; + + let updateListener = { + onUpdateAvailable: function(addon, update) { + // Dummy so the update checker knows we care about new versions + }, + + onUpdateFinished: function(addon, error) { + if (--count == 0) + do_execute_soon(run_next_test); + } + }; + + a1.findUpdates(updateListener, AddonManager.UPDATE_WHEN_USER_REQUESTED); + a2.findUpdates(compatListener, AddonManager.UPDATE_WHEN_ADDON_INSTALLED); + a3.findUpdates(updateListener, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE); + a4.findUpdates(updateListener, AddonManager.UPDATE_WHEN_NEW_APP_DETECTED, "2"); + a5.findUpdates(compatListener, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED); + a6.findUpdates(updateListener, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED); + }); + })); +} + +// Tests that if an install.rdf claims compatibility then the add-on will be +// seen as compatible regardless of what the update.rdf says. +function run_test_9() { + writeInstallRDFForExtension({ + id: "addon4@tests.mozilla.org", + version: "5.0", + updateURL: "http://localhost:" + gPort + "/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "0", + maxVersion: "1" + }], + name: "Test Addon 1", + }, profileDir); + + restartManager(); + + AddonManager.getAddonByID("addon4@tests.mozilla.org", function(a4) { + do_check_true(a4.isActive); + do_check_true(a4.isCompatible); + + run_test_10(); + }); +} + +// Tests that a normal update check won't decrease a targetApplication's +// maxVersion. +function run_test_10() { + AddonManager.getAddonByID("addon4@tests.mozilla.org", function(a4) { + a4.findUpdates({ + onUpdateFinished: function(addon) { + do_check_true(addon.isCompatible); + + run_test_11(); + } + }, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE); + }); +} + +// Tests that an update check for a new application will decrease a +// targetApplication's maxVersion. +function run_test_11() { + AddonManager.getAddonByID("addon4@tests.mozilla.org", function(a4) { + a4.findUpdates({ + onUpdateFinished: function(addon) { + do_check_false(addon.isCompatible); + + do_execute_soon(run_test_12); + } + }, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED); + }); +} + +// Check that the decreased maxVersion applied and disables the add-on +function run_test_12() { + restartManager(); + + AddonManager.getAddonByID("addon4@tests.mozilla.org", function(a4) { + do_check_false(a4.isActive); + do_check_false(a4.isCompatible); + + a4.uninstall(); + do_execute_soon(run_test_13); + }); +} + +// Tests that no compatibility update is passed to the listener when there is +// compatibility info for the current version of the app but not for the +// version of the app that the caller requested an update check for. +function run_test_13() { + restartManager(); + + // Not initially compatible but the update check will make it compatible + writeInstallRDFForExtension({ + id: "addon7@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "0", + maxVersion: "0" + }], + name: "Test Addon 7", + }, profileDir); + restartManager(); + + AddonManager.getAddonByID("addon7@tests.mozilla.org", function(a7) { + do_check_neq(a7, null); + do_check_false(a7.isActive); + do_check_false(a7.isCompatible); + do_check_true(a7.appDisabled); + do_check_true(a7.isCompatibleWith("0")); + + a7.findUpdates({ + sawUpdate: false, + onCompatibilityUpdateAvailable: function(addon) { + do_throw("Should have not have seen compatibility information"); + }, + + onUpdateAvailable: function(addon, install) { + do_throw("Should not have seen an available update"); + }, + + onUpdateFinished: function(addon) { + do_check_true(addon.isCompatible); + do_execute_soon(check_test_13); + } + }, AddonManager.UPDATE_WHEN_NEW_APP_DETECTED, "3.0"); + }); +} + +function check_test_13() { + restartManager(); + AddonManager.getAddonByID("addon7@tests.mozilla.org", function(a7) { + do_check_neq(a7, null); + do_check_true(a7.isActive); + do_check_true(a7.isCompatible); + do_check_false(a7.appDisabled); + + a7.uninstall(); + do_execute_soon(run_test_14); + }); +} + +// Test that background update checks doesn't update an add-on that isn't +// allowed to update automatically. +function run_test_14() { + restartManager(); + + // Have an add-on there that will be updated so we see some events from it + writeInstallRDFForExtension({ + id: "addon1@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 1", + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon8@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 8", + }, profileDir); + restartManager(); + + AddonManager.getAddonByID("addon8@tests.mozilla.org", function(a8) { + a8.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DISABLE; + + // The background update check will find updates for both add-ons but only + // proceed to install one of them. + AddonManager.addInstallListener({ + onNewInstall: function(aInstall) { + if (aInstall.existingAddon.id != "addon1@tests.mozilla.org" && + aInstall.existingAddon.id != "addon8@tests.mozilla.org") + do_throw("Saw unexpected onNewInstall for " + aInstall.existingAddon.id); + }, + + onDownloadStarted: function(aInstall) { + do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); + }, + + onDownloadEnded: function(aInstall) { + do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); + }, + + onDownloadFailed: function(aInstall) { + do_throw("Should not have seen onDownloadFailed event"); + }, + + onDownloadCancelled: function(aInstall) { + do_throw("Should not have seen onDownloadCancelled event"); + }, + + onInstallStarted: function(aInstall) { + do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); + }, + + onInstallEnded: function(aInstall) { + do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); + do_check_eq(aInstall.existingAddon.pendingUpgrade.install, aInstall); + do_execute_soon(check_test_14); + }, + + onInstallFailed: function(aInstall) { + do_throw("Should not have seen onInstallFailed event"); + }, + + onInstallCancelled: function(aInstall) { + do_throw("Should not have seen onInstallCancelled event"); + }, + }); + + AddonManagerInternal.backgroundUpdateCheck(); + }); +} + +function check_test_14() { + restartManager(); + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon8@tests.mozilla.org"], function([a1, a8]) { + do_check_neq(a1, null); + do_check_eq(a1.version, "2.0"); + a1.uninstall(); + + do_check_neq(a8, null); + do_check_eq(a8.version, "1.0"); + a8.uninstall(); + + do_execute_soon(run_test_15); + }); +} + +// Test that background update checks doesn't update an add-on that is +// pending uninstall +function run_test_15() { + restartManager(); + + // Have an add-on there that will be updated so we see some events from it + writeInstallRDFForExtension({ + id: "addon1@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 1", + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon8@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 8", + }, profileDir); + restartManager(); + + AddonManager.getAddonByID("addon8@tests.mozilla.org", function(a8) { + a8.uninstall(); + do_check_false(hasFlag(a8.permissions, AddonManager.PERM_CAN_UPGRADE)); + + // The background update check will find updates for both add-ons but only + // proceed to install one of them. + AddonManager.addInstallListener({ + onNewInstall: function(aInstall) { + if (aInstall.existingAddon.id != "addon1@tests.mozilla.org" && + aInstall.existingAddon.id != "addon8@tests.mozilla.org") + do_throw("Saw unexpected onNewInstall for " + aInstall.existingAddon.id); + }, + + onDownloadStarted: function(aInstall) { + do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); + }, + + onDownloadEnded: function(aInstall) { + do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); + }, + + onDownloadFailed: function(aInstall) { + do_throw("Should not have seen onDownloadFailed event"); + }, + + onDownloadCancelled: function(aInstall) { + do_throw("Should not have seen onDownloadCancelled event"); + }, + + onInstallStarted: function(aInstall) { + do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); + }, + + onInstallEnded: function(aInstall) { + do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); + do_execute_soon(check_test_15); + }, + + onInstallFailed: function(aInstall) { + do_throw("Should not have seen onInstallFailed event"); + }, + + onInstallCancelled: function(aInstall) { + do_throw("Should not have seen onInstallCancelled event"); + }, + }); + + AddonManagerInternal.backgroundUpdateCheck(); + }); +} + +function check_test_15() { + restartManager(); + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon8@tests.mozilla.org"], function([a1, a8]) { + do_check_neq(a1, null); + do_check_eq(a1.version, "2.0"); + a1.uninstall(); + + do_check_eq(a8, null); + + do_execute_soon(run_test_16); + }); +} + +// Test that the update check correctly observes the +// extensions.strictCompatibility pref and compatibility overrides. +function run_test_16() { + restartManager(); + + writeInstallRDFForExtension({ + id: "addon9@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "0.1", + maxVersion: "0.2" + }], + name: "Test Addon 9", + }, profileDir); + restartManager(); + + AddonManager.addInstallListener({ + onNewInstall: function(aInstall) { + if (aInstall.existingAddon.id != "addon9@tests.mozilla.org") + do_throw("Saw unexpected onNewInstall for " + aInstall.existingAddon.id); + do_check_eq(aInstall.version, "2.0"); + }, + onDownloadFailed: function(aInstall) { + do_execute_soon(run_test_17); + } + }); + + Services.prefs.setCharPref(PREF_GETADDONS_BYIDS_PERFORMANCE, + "http://localhost:" + gPort + "/data/test_update.xml"); + Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true); + + AddonManagerInternal.backgroundUpdateCheck(); +} + +// Test that the update check correctly observes when an addon opts-in to +// strict compatibility checking. +function run_test_17() { + + writeInstallRDFForExtension({ + id: "addon11@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "0.1", + maxVersion: "0.2" + }], + name: "Test Addon 11", + }, profileDir); + restartManager(); + + AddonManager.getAddonByID("addon11@tests.mozilla.org", function(a11) { + do_check_neq(a11, null); + + a11.findUpdates({ + onCompatibilityUpdateAvailable: function() { + do_throw("Should have not have seen compatibility information"); + }, + + onUpdateAvailable: function() { + do_throw("Should not have seen an available update"); + }, + + onUpdateFinished: function() { + do_execute_soon(end_test); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); }); } diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_update_webextensions.js b/toolkit/mozapps/extensions/test/xpcshell/test_update_webextensions.js deleted file mode 100644 index ff5d5d321..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_update_webextensions.js +++ /dev/null @@ -1,248 +0,0 @@ -"use strict"; - -const TOOLKIT_ID = "toolkit@mozilla.org"; - -// We don't have an easy way to serve update manifests from a secure URL. -Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false); - -var testserver = createHttpServer(); -gPort = testserver.identity.primaryPort; - -const uuidGenerator = AM_Cc["@mozilla.org/uuid-generator;1"].getService(AM_Ci.nsIUUIDGenerator); - -const extensionsDir = gProfD.clone(); -extensionsDir.append("extensions"); - -const addonsDir = gTmpD.clone(); -addonsDir.append("addons"); -addonsDir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0o755); - -do_register_cleanup(() => addonsDir.remove(true)); - -testserver.registerDirectory("/addons/", addonsDir); - - -let gUpdateManifests = {}; - -function mapManifest(aPath, aManifestData) { - gUpdateManifests[aPath] = aManifestData; - testserver.registerPathHandler(aPath, serveManifest); -} - -function serveManifest(request, response) { - let manifest = gUpdateManifests[request.path]; - - response.setHeader("Content-Type", manifest.contentType, false); - response.write(manifest.data); -} - - -function promiseInstallWebExtension(aData) { - let addonFile = createTempWebExtensionFile(aData); - - return promiseInstallAllFiles([addonFile]).then(() => { - Services.obs.notifyObservers(addonFile, "flush-cache-entry", null); - return promiseAddonByID(aData.id); - }); -} - -var checkUpdates = Task.async(function* (aData, aReason = AddonManager.UPDATE_WHEN_PERIODIC_UPDATE) { - function provide(obj, path, value) { - path = path.split("."); - let prop = path.pop(); - - for (let key of path) { - if (!(key in obj)) - obj[key] = {}; - obj = obj[key]; - } - - if (!(prop in obj)) - obj[prop] = value; - } - - let id = uuidGenerator.generateUUID().number; - provide(aData, "addon.id", id); - provide(aData, "addon.manifest.applications.gecko.id", id); - - let updatePath = `/updates/${id}.json`.replace(/[{}]/g, ""); - let updateUrl = `http://localhost:${gPort}${updatePath}` - - let addonData = { updates: [] }; - let manifestJSON = { - addons: { [id]: addonData } - }; - - - provide(aData, "addon.manifest.applications.gecko.update_url", updateUrl); - let awaitInstall = promiseInstallWebExtension(aData.addon); - - - for (let version of Object.keys(aData.updates)) { - let update = aData.updates[version]; - update.version = version; - - provide(update, "addon.id", id); - provide(update, "addon.manifest.applications.gecko.id", id); - let addon = update.addon; - - delete update.addon; - - let file; - if (addon.rdf) { - provide(addon, "version", version); - provide(addon, "targetApplications", [{id: TOOLKIT_ID, - minVersion: "42", - maxVersion: "*"}]); - - file = createTempXPIFile(addon); - } else { - provide(addon, "manifest.version", version); - file = createTempWebExtensionFile(addon); - } - file.moveTo(addonsDir, `${id}-${version}.xpi`.replace(/[{}]/g, "")); - - let path = `/addons/${file.leafName}`; - provide(update, "update_link", `http://localhost:${gPort}${path}`); - - addonData.updates.push(update); - } - - mapManifest(updatePath, { data: JSON.stringify(manifestJSON), - contentType: "application/json" }); - - - let addon = yield awaitInstall; - - let updates = yield promiseFindAddonUpdates(addon, aReason); - updates.addon = addon; - - return updates; -}); - - -function run_test() { - createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "42.0", "42.0"); - - startupManager(); - do_register_cleanup(promiseShutdownManager); - - run_next_test(); -} - - -// Check that compatibility updates are applied. -add_task(function* checkUpdateMetadata() { - let update = yield checkUpdates({ - addon: { - manifest: { - version: "1.0", - applications: { gecko: { strict_max_version: "45" } }, - } - }, - updates: { - "1.0": { - applications: { gecko: { strict_min_version: "40", - strict_max_version: "48" } }, - } - } - }); - - ok(update.compatibilityUpdate, "have compat update"); - ok(!update.updateAvailable, "have no add-on update"); - - ok(update.addon.isCompatibleWith("40", "40"), "compatible min"); - ok(update.addon.isCompatibleWith("48", "48"), "compatible max"); - ok(!update.addon.isCompatibleWith("49", "49"), "not compatible max"); - - update.addon.uninstall(); -}); - - -// Check that updates from web extensions to web extensions succeed. -add_task(function* checkUpdateToWebExt() { - let update = yield checkUpdates({ - addon: { manifest: { version: "1.0" } }, - updates: { - "1.1": { }, - "1.2": { }, - "1.3": { "applications": { "gecko": { "strict_min_version": "48" } } }, - } - }); - - ok(!update.compatibilityUpdate, "have no compat update"); - ok(update.updateAvailable, "have add-on update"); - - equal(update.addon.version, "1.0", "add-on version"); - - yield promiseCompleteAllInstalls([update.updateAvailable]); - - let addon = yield promiseAddonByID(update.addon.id); - equal(addon.version, "1.2", "new add-on version"); - - addon.uninstall(); -}); - - -// Check that updates from web extensions to XUL extensions fail. -add_task(function* checkUpdateToRDF() { - let update = yield checkUpdates({ - addon: { manifest: { version: "1.0" } }, - updates: { - "1.1": { addon: { rdf: true } }, - } - }); - - ok(!update.compatibilityUpdate, "have no compat update"); - ok(update.updateAvailable, "have add-on update"); - - equal(update.addon.version, "1.0", "add-on version"); - - let result = yield new Promise((resolve, reject) => { - update.updateAvailable.addListener({ - onDownloadFailed: resolve, - onDownloadEnded: reject, - onInstalling: reject, - onInstallStarted: reject, - onInstallEnded: reject, - }); - update.updateAvailable.install(); - }); - - equal(result.error, AddonManager.ERROR_UNEXPECTED_ADDON_TYPE, "error: unexpected add-on type"); - - let addon = yield promiseAddonByID(update.addon.id); - equal(addon.version, "1.0", "new add-on version"); - - addon.uninstall(); -}); - - -// Check that illegal update URLs are rejected. -add_task(function* checkIllegalUpdateURL() { - const URLS = ["chrome://browser/content/", - "data:text/json,...", - "javascript:;", - "/"]; - - for (let url of URLS) { - let { messages } = yield promiseConsoleOutput(() => { - return new Promise((resolve, reject) => { - let addonFile = createTempWebExtensionFile({ - manifest: { applications: { gecko: { update_url: url } } }, - }); - - AddonManager.getInstallForFile(addonFile, install => { - Services.obs.notifyObservers(addonFile, "flush-cache-entry", null); - - if (install && install.state == AddonManager.STATE_DOWNLOAD_FAILED) - resolve(); - reject(new Error("Unexpected state: " + (install && install.state))) - }); - }); - }); - - ok(messages.some(msg => /Access denied for URL|may not load or link to|is not a valid URL/.test(msg)), - "Got checkLoadURI error"); - } -}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_updatecheck.js b/toolkit/mozapps/extensions/test/xpcshell/test_updatecheck.js index e8529bb2c..d2e15103b 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_updatecheck.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_updatecheck.js @@ -7,46 +7,51 @@ Components.utils.import("resource://gre/modules/addons/AddonUpdateChecker.jsm"); Components.utils.import("resource://testing-common/httpd.js"); +var testserver; -var testserver = createHttpServer(4444); -testserver.registerDirectory("/data/", do_get_file("data")); +function run_test() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); -function checkUpdates(aId, aUpdateKey, aUpdateFile) { - return new Promise((resolve, reject) => { - AddonUpdateChecker.checkForUpdates(aId, aUpdateKey, `http://localhost:4444/data/${aUpdateFile}`, { - onUpdateCheckComplete: resolve, + // Create and configure the HTTP server. + testserver = new HttpServer(); + testserver.registerDirectory("/data/", do_get_file("data")); + testserver.start(4444); - onUpdateCheckError: function(status) { - let error = new Error("Update check failed with status " + status); - error.status = status; - reject(error); - } - }); - }); + do_test_pending(); + run_test_1(); } -function run_test() { - createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1"); - - run_next_test(); +function end_test() { + testserver.stop(do_test_finished); } // Test that a basic update check returns the expected available updates -add_task(function* () { - for (let file of ["test_updatecheck.rdf", "test_updatecheck.json"]) { - let updates = yield checkUpdates("updatecheck1@tests.mozilla.org", null, file); - - equal(updates.length, 5); - let update = AddonUpdateChecker.getNewestCompatibleUpdate(updates); - notEqual(update, null); - equal(update.version, "3.0"); - update = AddonUpdateChecker.getCompatibilityUpdate(updates, "2"); - notEqual(update, null); - equal(update.version, "2.0"); - equal(update.targetApplications[0].minVersion, "1"); - equal(update.targetApplications[0].maxVersion, "2"); - } -}); +function run_test_1() { + AddonUpdateChecker.checkForUpdates("updatecheck1@tests.mozilla.org", null, + "http://localhost:4444/data/test_updatecheck.rdf", { + onUpdateCheckComplete: function(updates) { + check_test_1(updates); + }, + + onUpdateCheckError: function(status) { + do_throw("Update check failed with status " + status); + } + }); +} + +function check_test_1(updates) { + do_check_eq(updates.length, 5); + let update = AddonUpdateChecker.getNewestCompatibleUpdate(updates); + do_check_neq(update, null); + do_check_eq(update.version, 3); + update = AddonUpdateChecker.getCompatibilityUpdate(updates, "2"); + do_check_neq(update, null); + do_check_eq(update.version, 2); + do_check_eq(update.targetApplications[0].minVersion, 1); + do_check_eq(update.targetApplications[0].maxVersion, 2); + + run_test_2(); +} /* * Tests that the security checks are applied correctly @@ -63,174 +68,245 @@ add_task(function* () { * 9 corrent md2 https update */ -var updateKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDK426erD/H3XtsjvaB5+PJqbhj" + +let updateKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDK426erD/H3XtsjvaB5+PJqbhj" + "Zc9EDI5OCJS8R3FIObJ9ZHJK1TXeaE7JWqt9WUmBWTEFvwS+FI9vWu8058N9CHhD" + "NyeP6i4LuUYjTURnn7Yw/IgzyIJ2oKsYa32RuxAyteqAWqPT/J63wBixIeCxmysf" + "awB/zH4KaPiY3vnrzQIDAQAB"; -add_task(function* () { - for (let file of ["test_updatecheck.rdf", "test_updatecheck.json"]) { - try { - yield checkUpdates("test_bug378216_5@tests.mozilla.org", - updateKey, file); - throw "Expected the update check to fail"; - } catch (e) {} - } -}); - -add_task(function* () { - for (let file of ["test_updatecheck.rdf", "test_updatecheck.json"]) { - try { - yield checkUpdates("test_bug378216_7@tests.mozilla.org", - updateKey, file); - - throw "Expected the update check to fail"; - } catch (e) {} - } -}); - -add_task(function* () { - // Make sure that the JSON manifest is rejected when an update key is - // required, but perform the remaining tests which aren't expected to fail - // because of the update key, without requiring one for the JSON variant. - - try { - let updates = yield checkUpdates("test_bug378216_8@tests.mozilla.org", - updateKey, "test_updatecheck.json"); - - throw "Expected the update check to fail"; - } catch (e) {} - - for (let [file, key] of [["test_updatecheck.rdf", updateKey], - ["test_updatecheck.json", null]]) { - let updates = yield checkUpdates("test_bug378216_8@tests.mozilla.org", - key, file); - equal(updates.length, 1); - ok(!("updateURL" in updates[0])); - } -}); - -add_task(function* () { - for (let [file, key] of [["test_updatecheck.rdf", updateKey], - ["test_updatecheck.json", null]]) { - let updates = yield checkUpdates("test_bug378216_9@tests.mozilla.org", - key, file); - equal(updates.length, 1); - equal(updates[0].version, "2.0"); - ok("updateURL" in updates[0]); - } -}); - -add_task(function* () { - for (let [file, key] of [["test_updatecheck.rdf", updateKey], - ["test_updatecheck.json", null]]) { - let updates = yield checkUpdates("test_bug378216_10@tests.mozilla.org", - key, file); - equal(updates.length, 1); - equal(updates[0].version, "2.0"); - ok("updateURL" in updates[0]); - } -}); - -add_task(function* () { - for (let [file, key] of [["test_updatecheck.rdf", updateKey], - ["test_updatecheck.json", null]]) { - let updates = yield checkUpdates("test_bug378216_11@tests.mozilla.org", - key, file); - equal(updates.length, 1); - equal(updates[0].version, "2.0"); - ok("updateURL" in updates[0]); - } -}); - -add_task(function* () { - for (let [file, key] of [["test_updatecheck.rdf", updateKey], - ["test_updatecheck.json", null]]) { - let updates = yield checkUpdates("test_bug378216_12@tests.mozilla.org", - key, file); - equal(updates.length, 1); - do_check_false("updateURL" in updates[0]); - } -}); - -add_task(function* () { - for (let [file, key] of [["test_updatecheck.rdf", updateKey], - ["test_updatecheck.json", null]]) { - let updates = yield checkUpdates("test_bug378216_13@tests.mozilla.org", - key, file); - equal(updates.length, 1); - equal(updates[0].version, "2.0"); - ok("updateURL" in updates[0]); - } -}); - -add_task(function* () { - for (let file of ["test_updatecheck.rdf", "test_updatecheck.json"]) { - let updates = yield checkUpdates("test_bug378216_14@tests.mozilla.org", - null, file); - equal(updates.length, 0); - } -}); - -add_task(function* () { - for (let file of ["test_updatecheck.rdf", "test_updatecheck.json"]) { - try { - yield checkUpdates("test_bug378216_15@tests.mozilla.org", - null, file); - - throw "Update check should have failed"; - } catch (e) { - equal(e.status, AddonUpdateChecker.ERROR_PARSE_ERROR); +function run_test_2() { + AddonUpdateChecker.checkForUpdates("test_bug378216_5@tests.mozilla.org", + updateKey, + "http://localhost:4444/data/test_updatecheck.rdf", { + onUpdateCheckComplete: function(updates) { + do_throw("Expected the update check to fail"); + }, + + onUpdateCheckError: function(status) { + run_test_3(); + } + }); +} + +function run_test_3() { + AddonUpdateChecker.checkForUpdates("test_bug378216_7@tests.mozilla.org", + updateKey, + "http://localhost:4444/data/test_updatecheck.rdf", { + onUpdateCheckComplete: function(updates) { + do_throw("Expected the update check to fail"); + }, + + onUpdateCheckError: function(status) { + run_test_4(); + } + }); +} + +function run_test_4() { + AddonUpdateChecker.checkForUpdates("test_bug378216_8@tests.mozilla.org", + updateKey, + "http://localhost:4444/data/test_updatecheck.rdf", { + onUpdateCheckComplete: function(updates) { + do_check_eq(updates.length, 1); + do_check_false("updateURL" in updates[0]); + run_test_5(); + }, + + onUpdateCheckError: function(status) { + do_throw("Update check failed with status " + status); + } + }); +} + +function run_test_5() { + AddonUpdateChecker.checkForUpdates("test_bug378216_9@tests.mozilla.org", + updateKey, + "http://localhost:4444/data/test_updatecheck.rdf", { + onUpdateCheckComplete: function(updates) { + do_check_eq(updates.length, 1); + do_check_eq(updates[0].version, "2.0"); + do_check_true("updateURL" in updates[0]); + run_test_6(); + }, + + onUpdateCheckError: function(status) { + do_throw("Update check failed with status " + status); + } + }); +} + +function run_test_6() { + AddonUpdateChecker.checkForUpdates("test_bug378216_10@tests.mozilla.org", + updateKey, + "http://localhost:4444/data/test_updatecheck.rdf", { + onUpdateCheckComplete: function(updates) { + do_check_eq(updates.length, 1); + do_check_eq(updates[0].version, "2.0"); + do_check_true("updateURL" in updates[0]); + run_test_7(); + }, + + onUpdateCheckError: function(status) { + do_throw("Update check failed with status " + status); + } + }); +} + +function run_test_7() { + AddonUpdateChecker.checkForUpdates("test_bug378216_11@tests.mozilla.org", + updateKey, + "http://localhost:4444/data/test_updatecheck.rdf", { + onUpdateCheckComplete: function(updates) { + do_check_eq(updates.length, 1); + do_check_eq(updates[0].version, "2.0"); + do_check_true("updateURL" in updates[0]); + run_test_8(); + }, + + onUpdateCheckError: function(status) { + do_throw("Update check failed with status " + status); } - } -}); - -add_task(function* () { - for (let file of ["test_updatecheck.rdf", "test_updatecheck.json"]) { - let updates = yield checkUpdates("ignore-compat@tests.mozilla.org", - null, file); - equal(updates.length, 3); - let update = AddonUpdateChecker.getNewestCompatibleUpdate( - updates, null, null, true); - notEqual(update, null); - equal(update.version, 2); - } -}); - -add_task(function* () { - for (let file of ["test_updatecheck.rdf", "test_updatecheck.json"]) { - let updates = yield checkUpdates("compat-override@tests.mozilla.org", - null, file); - equal(updates.length, 3); - let overrides = [{ - type: "incompatible", - minVersion: 1, - maxVersion: 2, - appID: "xpcshell@tests.mozilla.org", - appMinVersion: 0.1, - appMaxVersion: 0.2 - }, { - type: "incompatible", - minVersion: 2, - maxVersion: 2, - appID: "xpcshell@tests.mozilla.org", - appMinVersion: 1, - appMaxVersion: 2 - }]; - let update = AddonUpdateChecker.getNewestCompatibleUpdate( - updates, null, null, true, false, overrides); - notEqual(update, null); - equal(update.version, 1); - } -}); - -add_task(function* () { - for (let file of ["test_updatecheck.rdf", "test_updatecheck.json"]) { - let updates = yield checkUpdates("compat-strict-optin@tests.mozilla.org", - null, file); - equal(updates.length, 1); - let update = AddonUpdateChecker.getNewestCompatibleUpdate( - updates, null, null, true, false); - equal(update, null); - } -}); + }); +} + +function run_test_8() { + AddonUpdateChecker.checkForUpdates("test_bug378216_12@tests.mozilla.org", + updateKey, + "http://localhost:4444/data/test_updatecheck.rdf", { + onUpdateCheckComplete: function(updates) { + do_check_eq(updates.length, 1); + do_check_false("updateURL" in updates[0]); + run_test_9(); + }, + + onUpdateCheckError: function(status) { + do_throw("Update check failed with status " + status); + } + }); +} + +function run_test_9() { + AddonUpdateChecker.checkForUpdates("test_bug378216_13@tests.mozilla.org", + updateKey, + "http://localhost:4444/data/test_updatecheck.rdf", { + onUpdateCheckComplete: function(updates) { + do_check_eq(updates.length, 1); + do_check_eq(updates[0].version, "2.0"); + do_check_true("updateURL" in updates[0]); + run_test_10(); + }, + + onUpdateCheckError: function(status) { + do_throw("Update check failed with status " + status); + } + }); +} + +function run_test_10() { + AddonUpdateChecker.checkForUpdates("test_bug378216_14@tests.mozilla.org", + null, + "http://localhost:4444/data/test_updatecheck.rdf", { + onUpdateCheckComplete: function(updates) { + do_check_eq(updates.length, 0); + run_test_11(); + }, + + onUpdateCheckError: function(status) { + do_throw("Update check failed with status " + status); + } + }); +} + +function run_test_11() { + AddonUpdateChecker.checkForUpdates("test_bug378216_15@tests.mozilla.org", + null, + "http://localhost:4444/data/test_updatecheck.rdf", { + onUpdateCheckComplete: function(updates) { + do_throw("Update check should have failed"); + }, + + onUpdateCheckError: function(status) { + do_check_eq(status, AddonUpdateChecker.ERROR_PARSE_ERROR); + run_test_12(); + } + }); +} + +function run_test_12() { + AddonUpdateChecker.checkForUpdates("ignore-compat@tests.mozilla.org", + null, + "http://localhost:4444/data/test_updatecheck.rdf", { + onUpdateCheckComplete: function(updates) { + do_check_eq(updates.length, 3); + let update = AddonUpdateChecker.getNewestCompatibleUpdate(updates, + null, + null, + true); + do_check_neq(update, null); + do_check_eq(update.version, 2); + run_test_13(); + }, + + onUpdateCheckError: function(status) { + do_throw("Update check failed with status " + status); + } + }); +} + +function run_test_13() { + AddonUpdateChecker.checkForUpdates("compat-override@tests.mozilla.org", + null, + "http://localhost:4444/data/test_updatecheck.rdf", { + onUpdateCheckComplete: function(updates) { + do_check_eq(updates.length, 3); + let overrides = [{ + type: "incompatible", + minVersion: 1, + maxVersion: 2, + appID: "xpcshell@tests.mozilla.org", + appMinVersion: 0.1, + appMaxVersion: 0.2 + }, { + type: "incompatible", + minVersion: 2, + maxVersion: 2, + appID: "xpcshell@tests.mozilla.org", + appMinVersion: 1, + appMaxVersion: 2 + }]; + let update = AddonUpdateChecker.getNewestCompatibleUpdate(updates, + null, + null, + true, + false, + overrides); + do_check_neq(update, null); + do_check_eq(update.version, 1); + run_test_14(); + }, + + onUpdateCheckError: function(status) { + do_throw("Update check failed with status " + status); + } + }); +} + +function run_test_14() { + AddonUpdateChecker.checkForUpdates("compat-strict-optin@tests.mozilla.org", + null, + "http://localhost:4444/data/test_updatecheck.rdf", { + onUpdateCheckComplete: function(updates) { + do_check_eq(updates.length, 1); + let update = AddonUpdateChecker.getNewestCompatibleUpdate(updates, + null, + null, + true, + false); + do_check_eq(update, null); + end_test(); + }, + + onUpdateCheckError: function(status) { + do_throw("Update check failed with status " + status); + } + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_updateid.js b/toolkit/mozapps/extensions/test/xpcshell/test_updateid.js index f7e3e21e5..e8aea0301 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_updateid.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_updateid.js @@ -7,80 +7,416 @@ // The test extension uses an insecure update url. Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); +Components.utils.import("resource://testing-common/httpd.js"); +var testserver; const profileDir = gProfD.clone(); profileDir.append("extensions"); -function promiseInstallUpdate(install) { - return new Promise((resolve, reject) => { - install.addListener({ - onDownloadFailed: () => { - let err = new Error("download error"); - err.code = install.error; - reject(err); - }, - onInstallFailed: () => { - let err = new Error("install error"); - err.code = install.error; - reject(err); - }, - onInstallEnded: resolve, - }); +function resetPrefs() { + Services.prefs.setIntPref("bootstraptest.active_version", -1); + Services.prefs.setIntPref("bootstraptest.installed_version", -1); + Services.prefs.setIntPref("bootstraptest.startup_reason", -1); + Services.prefs.setIntPref("bootstraptest.shutdown_reason", -1); + Services.prefs.setIntPref("bootstraptest.install_reason", -1); + Services.prefs.setIntPref("bootstraptest.uninstall_reason", -1); +} - install.install(); - }); +function getActiveVersion() { + return Services.prefs.getIntPref("bootstraptest.active_version"); } -// Create and configure the HTTP server. -let testserver = createHttpServer(4444); -testserver.registerDirectory("/data/", do_get_file("data")); -testserver.registerDirectory("/addons/", do_get_file("addons")); +function getInstalledVersion() { + return Services.prefs.getIntPref("bootstraptest.installed_version"); +} function run_test() { createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + + // Create and configure the HTTP server. + testserver = new HttpServer(); + testserver.registerDirectory("/data/", do_get_file("data")); + testserver.registerDirectory("/addons/", do_get_file("addons")); + testserver.start(4444); + + do_test_pending(); + run_test_1(); +} + +function end_test() { + testserver.stop(do_test_finished); +} + +function installUpdate(aInstall, aCallback) { + aInstall.addListener({ + onInstallEnded: function(aInstall) { + // give the startup time to run + do_execute_soon(function() { + aCallback(aInstall); + }); + } + }); + + aInstall.install(); +} + +// Verify that an update to an add-on with a new ID uninstalls the old add-on +function run_test_1() { + writeInstallRDFForExtension({ + id: "addon1@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:4444/data/test_updateid.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 1", + }, profileDir); + + startupManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.version, "1.0"); + + a1.findUpdates({ + onUpdateAvailable: function(addon, install) { + do_check_eq(install.name, addon.name); + do_check_eq(install.version, "2.0"); + do_check_eq(install.state, AddonManager.STATE_AVAILABLE); + do_check_eq(install.existingAddon, a1); + + installUpdate(install, check_test_1); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); + }); +} + +function check_test_1(install) { + AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) { + // Existing add-on should have a pending upgrade + do_check_neq(a1.pendingUpgrade, null); + do_check_eq(a1.pendingUpgrade.id, "addon2@tests.mozilla.org"); + do_check_eq(a1.pendingUpgrade.install.existingAddon, a1); + do_check_neq(a1.syncGUID); + + let a1SyncGUID = a1.syncGUID; + + restartManager(); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org"], function([a1, a2]) { + // Should have uninstalled the old and installed the new + do_check_eq(a1, null); + do_check_neq(a2, null); + do_check_neq(a2.syncGUID, null); + + // The Sync GUID should change when the ID changes + do_check_neq(a1SyncGUID, a2.syncGUID); + + a2.uninstall(); + + do_execute_soon(run_test_2); + }); + })); +} + +// Test that when the new add-on already exists we just upgrade that +function run_test_2() { + restartManager(); + shutdownManager(); + + writeInstallRDFForExtension({ + id: "addon1@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:4444/data/test_updateid.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 1", + }, profileDir); + writeInstallRDFForExtension({ + id: "addon2@tests.mozilla.org", + version: "1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 2", + }, profileDir); + + startupManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.version, "1.0"); + + a1.findUpdates({ + onUpdateAvailable: function(addon, install) { + installUpdate(install, check_test_2); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); + }); +} + +function check_test_2(install) { + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org"], + callback_soon(function([a1, a2]) { + do_check_eq(a1.pendingUpgrade, null); + // Existing add-on should have a pending upgrade + do_check_neq(a2.pendingUpgrade, null); + do_check_eq(a2.pendingUpgrade.id, "addon2@tests.mozilla.org"); + do_check_eq(a2.pendingUpgrade.install.existingAddon, a2); + + restartManager(); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org"], function([a1, a2]) { + // Should have uninstalled the old and installed the new + do_check_neq(a1, null); + do_check_neq(a2, null); + + a1.uninstall(); + a2.uninstall(); + + do_execute_soon(run_test_3); + }); + })); +} + +// Test that we rollback correctly when removing the old add-on fails +function run_test_3() { + restartManager(); + shutdownManager(); + + // This test only works on Windows + if (!("nsIWindowsRegKey" in AM_Ci)) { + run_test_4(); + return; + } + + writeInstallRDFForExtension({ + id: "addon1@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:4444/data/test_updateid.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 1", + }, profileDir); + + startupManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.version, "1.0"); + + a1.findUpdates({ + onUpdateAvailable: function(addon, install) { + installUpdate(install, check_test_3); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); + }); +} + +function check_test_3(install) { + AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) { + // Existing add-on should have a pending upgrade + do_check_neq(a1.pendingUpgrade, null); + do_check_eq(a1.pendingUpgrade.id, "addon2@tests.mozilla.org"); + do_check_eq(a1.pendingUpgrade.install.existingAddon, a1); + + // Lock the old add-on open so it can't be uninstalled + var file = profileDir.clone(); + file.append("addon1@tests.mozilla.org"); + if (!file.exists()) + file.leafName += ".xpi"; + else + file.append("install.rdf"); + + var fstream = AM_Cc["@mozilla.org/network/file-output-stream;1"]. + createInstance(AM_Ci.nsIFileOutputStream); + fstream.init(file, FileUtils.MODE_APPEND | FileUtils.MODE_WRONLY, FileUtils.PERMS_FILE, 0); + + restartManager(); + + fstream.close(); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org"], + callback_soon(function([a1, a2]) { + // Should not have installed the new add-on but it should still be + // pending install + do_check_neq(a1, null); + do_check_eq(a2, null); + + restartManager(); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org"], function([a1, a2]) { + // Should have installed the new add-on + do_check_eq(a1, null); + do_check_neq(a2, null); + + a2.uninstall(); + + do_execute_soon(run_test_4); + }); + })); + })); +} + +// Tests that upgrading to a bootstrapped add-on works but requires a restart +function run_test_4() { + restartManager(); + shutdownManager(); + + writeInstallRDFForExtension({ + id: "addon2@tests.mozilla.org", + version: "2.0", + updateURL: "http://localhost:4444/data/test_updateid.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 2", + }, profileDir); + startupManager(); - run_next_test(); + + resetPrefs(); + + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { + do_check_neq(a2, null); + do_check_neq(a2.syncGUID, null); + do_check_eq(a2.version, "2.0"); + + a2.findUpdates({ + onUpdateAvailable: function(addon, install) { + installUpdate(install, check_test_4); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); + }); } -// Verify that an update to an add-on with a new ID fails -add_task(function* test_update_new_id() { - yield promiseInstallFile(do_get_addon("test_updateid1")); +function check_test_4() { + AddonManager.getAddonsByIDs(["addon2@tests.mozilla.org", + "addon3@tests.mozilla.org"], + callback_soon(function([a2, a3]) { + // Should still be pending install even though the new add-on is restartless + do_check_neq(a2, null); + do_check_eq(a3, null); - let addon = yield promiseAddonByID("addon1@tests.mozilla.org"); - do_check_neq(addon, null); - do_check_eq(addon.version, "1.0"); + do_check_neq(a2.pendingUpgrade, null); + do_check_eq(a2.pendingUpgrade.id, "addon3@tests.mozilla.org"); - let update = yield promiseFindAddonUpdates(addon, AddonManager.UPDATE_WHEN_USER_REQUESTED); - let install = update.updateAvailable; - do_check_eq(install.name, addon.name); - do_check_eq(install.version, "2.0"); - do_check_eq(install.state, AddonManager.STATE_AVAILABLE); - do_check_eq(install.existingAddon, addon); + do_check_eq(getInstalledVersion(), -1); + do_check_eq(getActiveVersion(), -1); - yield Assert.rejects(promiseInstallUpdate(install), - function(err) { return err.code == AddonManager.ERROR_INCORRECT_ID }, - "Upgrade to a different ID fails"); + restartManager(); - addon.uninstall(); -}); + AddonManager.getAddonsByIDs(["addon2@tests.mozilla.org", + "addon3@tests.mozilla.org"], function([a2, a3]) { + // Should have updated + do_check_eq(a2, null); + do_check_neq(a3, null); -// Verify that an update to a multi-package xpi fails -add_task(function* test_update_new_id() { - yield promiseInstallFile(do_get_addon("test_update_multi1")); + do_check_eq(getInstalledVersion(), 3); + do_check_eq(getActiveVersion(), 3); - let addon = yield promiseAddonByID("updatemulti@tests.mozilla.org"); - do_check_neq(addon, null); - do_check_eq(addon.version, "1.0"); + do_execute_soon(run_test_5); + }); + })); +} + +// Tests that upgrading to another bootstrapped add-on works without a restart +function run_test_5() { + AddonManager.getAddonByID("addon3@tests.mozilla.org", function(a3) { + do_check_neq(a3, null); + do_check_eq(a3.version, "3.0"); + + a3.findUpdates({ + onUpdateAvailable: function(addon, install) { + installUpdate(install, check_test_5); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); + }); +} + +function check_test_5() { + AddonManager.getAddonsByIDs(["addon3@tests.mozilla.org", + "addon4@tests.mozilla.org"], + callback_soon(function([a3, a4]) { + // Should have updated + do_check_eq(a3, null); + do_check_neq(a4, null); + + do_check_eq(getInstalledVersion(), 4); + do_check_eq(getActiveVersion(), 4); + + restartManager(); + + AddonManager.getAddonsByIDs(["addon3@tests.mozilla.org", + "addon4@tests.mozilla.org"], function([a3, a4]) { + // Should still be gone + do_check_eq(a3, null); + do_check_neq(a4, null); + + do_check_eq(getInstalledVersion(), 4); + do_check_eq(getActiveVersion(), 4); + + run_test_6(); + }); + })); +} + +// Tests that upgrading to a non-bootstrapped add-on works but requires a restart +function run_test_6() { + AddonManager.getAddonByID("addon4@tests.mozilla.org", function(a4) { + do_check_neq(a4, null); + do_check_eq(a4.version, "4.0"); + + a4.findUpdates({ + onUpdateAvailable: function(addon, install) { + installUpdate(install, check_test_6); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); + }); +} - let update = yield promiseFindAddonUpdates(addon, AddonManager.UPDATE_WHEN_USER_REQUESTED); - let install = update.updateAvailable; - do_check_eq(install.name, addon.name); - do_check_eq(install.version, "2.0"); - do_check_eq(install.state, AddonManager.STATE_AVAILABLE); - do_check_eq(install.existingAddon, addon); +function check_test_6() { + AddonManager.getAddonsByIDs(["addon4@tests.mozilla.org", + "addon2@tests.mozilla.org"], + callback_soon(function([a4, a2]) { + // Should still be pending install even though the old add-on is restartless + do_check_neq(a4, null); + do_check_eq(a2, null); - yield Assert.rejects(promiseInstallUpdate(install), - function(err) { return err.code == AddonManager.ERROR_UNEXPECTED_ADDON_TYPE }, - "Upgrade to a multipackage xpi fails"); + do_check_neq(a4.pendingUpgrade, null); + do_check_eq(a4.pendingUpgrade.id, "addon2@tests.mozilla.org"); - addon.uninstall(); -}); + do_check_eq(getInstalledVersion(), 4); + do_check_eq(getActiveVersion(), 4); + + restartManager(); + + AddonManager.getAddonsByIDs(["addon4@tests.mozilla.org", + "addon2@tests.mozilla.org"], function([a4, a2]) { + // Should have updated + do_check_eq(a4, null); + do_check_neq(a2, null); + + do_check_eq(getInstalledVersion(), 0); + do_check_eq(getActiveVersion(), 0); + + end_test(); + }); + })); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_upgrade.js b/toolkit/mozapps/extensions/test/xpcshell/test_upgrade.js index dc3d9438a..f79789b68 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_upgrade.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_upgrade.js @@ -15,7 +15,7 @@ Services.prefs.setIntPref("extensions.enabledScopes", const profileDir = gProfD.clone(); profileDir.append("extensions"); -const globalDir = Services.dirsvc.get("XREAddonAppDir", AM_Ci.nsIFile); +const globalDir = Services.dirsvc.get("XCurProcD", AM_Ci.nsIFile); globalDir.append("extensions"); var gGlobalExisted = globalDir.exists(); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_upgrade_strictcompat.js b/toolkit/mozapps/extensions/test/xpcshell/test_upgrade_strictcompat.js index c2203d097..69383166e 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_upgrade_strictcompat.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_upgrade_strictcompat.js @@ -13,7 +13,7 @@ Services.prefs.setIntPref("extensions.enabledScopes", const profileDir = gProfD.clone(); profileDir.append("extensions"); -const globalDir = Services.dirsvc.get("XREAddonAppDir", AM_Ci.nsIFile); +const globalDir = Services.dirsvc.get("XCurProcD", AM_Ci.nsIFile); globalDir.append("extensions"); var gGlobalExisted = globalDir.exists(); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_webextension.js b/toolkit/mozapps/extensions/test/xpcshell/test_webextension.js deleted file mode 100644 index b51f47977..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_webextension.js +++ /dev/null @@ -1,421 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -Components.utils.import("resource://gre/modules/AppConstants.jsm"); - -const ID = "webextension1@tests.mozilla.org"; - -const PREF_SELECTED_LOCALE = "general.useragent.locale"; - -const profileDir = gProfD.clone(); -profileDir.append("extensions"); - -createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "42"); -startupManager(); - -const { GlobalManager, Management } = Components.utils.import("resource://gre/modules/Extension.jsm", {}); - -function promiseAddonStartup() { - return new Promise(resolve => { - let listener = (evt, extension) => { - Management.off("ready", listener); - resolve(extension); - }; - - Management.on("ready", listener); - }); -} - -function promiseInstallWebExtension(aData) { - let addonFile = createTempWebExtensionFile(aData); - - return promiseInstallAllFiles([addonFile]).then(() => { - Services.obs.notifyObservers(addonFile, "flush-cache-entry", null); - return promiseAddonStartup(); - }); -} - -add_task(function*() { - equal(GlobalManager.extensionMap.size, 0); - - yield Promise.all([ - promiseInstallAllFiles([do_get_addon("webextension_1")], true), - promiseAddonStartup() - ]); - - equal(GlobalManager.extensionMap.size, 1); - ok(GlobalManager.extensionMap.has(ID)); - - let chromeReg = AM_Cc["@mozilla.org/chrome/chrome-registry;1"]. - getService(AM_Ci.nsIChromeRegistry); - try { - chromeReg.convertChromeURL(NetUtil.newURI("chrome://webex/content/webex.xul")); - do_throw("Chrome manifest should not have been registered"); - } - catch (e) { - // Expected the chrome url to not be registered - } - - let addon = yield promiseAddonByID(ID); - do_check_neq(addon, null); - do_check_eq(addon.version, "1.0"); - do_check_eq(addon.name, "Web Extension Name"); - do_check_true(addon.isCompatible); - do_check_false(addon.appDisabled); - do_check_true(addon.isActive); - do_check_false(addon.isSystem); - do_check_eq(addon.type, "extension"); - do_check_true(addon.isWebExtension); - do_check_eq(addon.signedState, mozinfo.addon_signing ? AddonManager.SIGNEDSTATE_SIGNED : AddonManager.SIGNEDSTATE_NOT_REQUIRED); - - let uri = do_get_addon_root_uri(profileDir, ID); - - do_check_eq(addon.iconURL, uri + "icon48.png"); - do_check_eq(addon.icon64URL, uri + "icon64.png"); - - // Should persist through a restart - yield promiseShutdownManager(); - - equal(GlobalManager.extensionMap.size, 0); - - startupManager(); - yield promiseAddonStartup(); - - equal(GlobalManager.extensionMap.size, 1); - ok(GlobalManager.extensionMap.has(ID)); - - addon = yield promiseAddonByID(ID); - do_check_neq(addon, null); - do_check_eq(addon.version, "1.0"); - do_check_eq(addon.name, "Web Extension Name"); - do_check_true(addon.isCompatible); - do_check_false(addon.appDisabled); - do_check_true(addon.isActive); - do_check_false(addon.isSystem); - do_check_eq(addon.type, "extension"); - do_check_eq(addon.signedState, mozinfo.addon_signing ? AddonManager.SIGNEDSTATE_SIGNED : AddonManager.SIGNEDSTATE_NOT_REQUIRED); - - let file = getFileForAddon(profileDir, ID); - do_check_true(file.exists()); - - uri = do_get_addon_root_uri(profileDir, ID); - - do_check_eq(addon.iconURL, uri + "icon48.png"); - do_check_eq(addon.icon64URL, uri + "icon64.png"); - - addon.userDisabled = true; - - equal(GlobalManager.extensionMap.size, 0); - - addon.userDisabled = false; - yield promiseAddonStartup(); - - equal(GlobalManager.extensionMap.size, 1); - ok(GlobalManager.extensionMap.has(ID)); - - addon.uninstall(); - - equal(GlobalManager.extensionMap.size, 0); - do_check_false(GlobalManager.extensionMap.has(ID)); - - yield promiseShutdownManager(); -}); - -// Writing the manifest direct to the profile should work -add_task(function*() { - yield promiseWriteWebManifestForExtension({ - name: "Web Extension Name", - version: "1.0", - manifest_version: 2, - applications: { - gecko: { - id: ID - } - } - }, profileDir); - - startupManager(); - yield promiseAddonStartup(); - - let addon = yield promiseAddonByID(ID); - do_check_neq(addon, null); - do_check_eq(addon.version, "1.0"); - do_check_eq(addon.name, "Web Extension Name"); - do_check_true(addon.isCompatible); - do_check_false(addon.appDisabled); - do_check_true(addon.isActive); - do_check_false(addon.isSystem); - do_check_eq(addon.type, "extension"); - do_check_eq(addon.signedState, mozinfo.addon_signing ? AddonManager.SIGNEDSTATE_SIGNED : AddonManager.SIGNEDSTATE_NOT_REQUIRED); - - let file = getFileForAddon(profileDir, ID); - do_check_true(file.exists()); - - addon.uninstall(); - - yield promiseRestartManager(); -}); - -add_task(function* test_manifest_localization() { - const extensionId = "webextension3@tests.mozilla.org"; - - yield promiseInstallAllFiles([do_get_addon("webextension_3")], true); - yield promiseAddonStartup(); - - let addon = yield promiseAddonByID(extensionId); - addon.userDisabled = true; - - equal(addon.name, "Web Extensiøn foo ☹"); - equal(addon.description, "Descriptïon bar ☹ of add-on"); - - Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "fr-FR"); - yield promiseRestartManager(); - - addon = yield promiseAddonByID(extensionId); - - equal(addon.name, "Web Extensiøn le foo ☺"); - equal(addon.description, "Descriptïon le bar ☺ of add-on"); - - Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "de"); - yield promiseRestartManager(); - - addon = yield promiseAddonByID(extensionId); - - equal(addon.name, "Web Extensiøn foo ☹"); - equal(addon.description, "Descriptïon bar ☹ of add-on"); - - addon.uninstall(); -}); - -// Missing version should cause a failure -add_task(function*() { - yield promiseWriteWebManifestForExtension({ - name: "Web Extension Name", - manifest_version: 2, - applications: { - gecko: { - id: ID - } - } - }, profileDir); - - yield promiseRestartManager(); - - let addon = yield promiseAddonByID(ID); - do_check_eq(addon, null); - - let file = getFileForAddon(profileDir, ID); - do_check_false(file.exists()); - - yield promiseRestartManager(); -}); - -// Incorrect manifest version should cause a failure -add_task(function*() { - yield promiseWriteWebManifestForExtension({ - name: "Web Extension Name", - version: "1.0", - manifest_version: 1, - applications: { - gecko: { - id: ID - } - } - }, profileDir); - - yield promiseRestartManager(); - - let addon = yield promiseAddonByID(ID); - do_check_eq(addon, null); - - let file = getFileForAddon(profileDir, ID); - do_check_false(file.exists()); - - yield promiseRestartManager(); -}); - -// install.rdf should be read before manifest.json -add_task(function*() { - - yield Promise.all([ - promiseInstallAllFiles([do_get_addon("webextension_2")], true) - ]); - - yield promiseRestartManager(); - - let installrdf_id = "first-webextension2@tests.mozilla.org"; - let first_addon = yield promiseAddonByID(installrdf_id); - do_check_neq(first_addon, null); - do_check_false(first_addon.appDisabled); - do_check_true(first_addon.isActive); - do_check_false(first_addon.isSystem); - - let manifestjson_id= "last-webextension2@tests.mozilla.org"; - let last_addon = yield promiseAddonByID(manifestjson_id); - do_check_eq(last_addon, null); - - yield promiseRestartManager(); -}); - -// Test that the "options_ui" manifest section is processed correctly. -add_task(function* test_options_ui() { - let OPTIONS_RE = /^moz-extension:\/\/[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}\/options\.html$/; - - const extensionId = "webextension@tests.mozilla.org"; - yield promiseInstallWebExtension({ - manifest: { - applications: {gecko: {id: extensionId}}, - "options_ui": { - "page": "options.html", - }, - }, - }); - - let addon = yield promiseAddonByID(extensionId); - equal(addon.optionsType, AddonManager.OPTIONS_TYPE_INLINE_BROWSER, - "Addon should have an INLINE_BROWSER options type"); - - ok(OPTIONS_RE.test(addon.optionsURL), - "Addon should have a moz-extension: options URL for /options.html"); - - addon.uninstall(); - - const ID2 = "webextension2@tests.mozilla.org"; - yield promiseInstallWebExtension({ - manifest: { - applications: {gecko: {id: ID2}}, - "options_ui": { - "page": "options.html", - "open_in_tab": true, - }, - }, - }); - - addon = yield promiseAddonByID(ID2); - equal(addon.optionsType, AddonManager.OPTIONS_TYPE_TAB, - "Addon should have a TAB options type"); - - ok(OPTIONS_RE.test(addon.optionsURL), - "Addon should have a moz-extension: options URL for /options.html"); - - addon.uninstall(); -}); - -// Test that experiments permissions add the appropriate dependencies. -add_task(function* test_experiments_dependencies() { - if (AppConstants.RELEASE_OR_BETA) - // Experiments are not enabled on release builds. - return; - - let addonFile = createTempWebExtensionFile({ - manifest: { - applications: {gecko: {id: "meh@experiment"}}, - "permissions": ["experiments.meh"], - }, - }); - - yield promiseInstallAllFiles([addonFile]); - - let addon = yield new Promise(resolve => AddonManager.getAddonByID("meh@experiment", resolve)); - - deepEqual(addon.dependencies, ["meh@experiments.addons.mozilla.org"], - "Addon should have the expected dependencies"); - - equal(addon.appDisabled, true, "Add-on should be app disabled due to missing dependencies"); - - addon.uninstall(); -}); - -// Test that experiments API extensions install correctly. -add_task(function* test_experiments_api() { - if (AppConstants.RELEASE_OR_BETA) - // Experiments are not enabled on release builds. - return; - - const extensionId = "meh@experiments.addons.mozilla.org"; - - let addonFile = createTempXPIFile({ - id: extensionId, - type: 256, - version: "0.1", - name: "Meh API", - }); - - yield promiseInstallAllFiles([addonFile]); - - let addons = yield new Promise(resolve => AddonManager.getAddonsByTypes(["apiextension"], resolve)); - let addon = addons.pop(); - equal(addon.id, extensionId, "Add-on should be installed as an API extension"); - - addons = yield new Promise(resolve => AddonManager.getAddonsByTypes(["extension"], resolve)); - equal(addons.pop().id, extensionId, "Add-on type should be aliased to extension"); - - addon.uninstall(); -}); - -add_task(function* developerShouldOverride() { - let addon = yield promiseInstallWebExtension({ - manifest: { - default_locale: "en", - developer: { - name: "__MSG_name__", - url: "__MSG_url__" - }, - author: "Will be overridden by developer", - homepage_url: "https://will.be.overridden", - }, - files: { - "_locales/en/messages.json": `{ - "name": { - "message": "en name" - }, - "url": { - "message": "https://example.net/en" - } - }` - } - }); - - addon = yield promiseAddonByID(addon.id); - equal(addon.creator, "en name"); - equal(addon.homepageURL, "https://example.net/en"); - addon.uninstall(); -}); - -add_task(function* developerEmpty() { - for (let developer of [{}, null, {name: null, url: null}]) { - let addon = yield promiseInstallWebExtension({ - manifest: { - author: "Some author", - developer: developer, - homepage_url: "https://example.net", - manifest_version: 2, - name: "Web Extension Name", - version: "1.0", - } - }); - - addon = yield promiseAddonByID(addon.id); - equal(addon.creator, "Some author"); - equal(addon.homepageURL, "https://example.net"); - addon.uninstall(); - } -}); - -add_task(function* authorNotString() { - for (let author of [{}, [], 42]) { - let addon = yield promiseInstallWebExtension({ - manifest: { - author: author, - manifest_version: 2, - name: "Web Extension Name", - version: "1.0", - } - }); - - addon = yield promiseAddonByID(addon.id); - equal(addon.creator, null); - addon.uninstall(); - } -}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_webextension_embedded.js b/toolkit/mozapps/extensions/test/xpcshell/test_webextension_embedded.js deleted file mode 100644 index 3bd8a2bd8..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_webextension_embedded.js +++ /dev/null @@ -1,306 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -BootstrapMonitor.init(); - -const profileDir = gProfD.clone(); -profileDir.append("extensions"); - -createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "49"); -startupManager(); - -// NOTE: the following import needs to be called after the `createAppInfo` -// or it will fail Extension.jsm internally imports AddonManager.jsm and -// AddonManager will raise a ReferenceError exception because it tried to -// access an undefined `Services.appinfo` object. -const { Management } = Components.utils.import("resource://gre/modules/Extension.jsm", {}); - -const { - EmbeddedExtensionManager, - LegacyExtensionsUtils, -} = Components.utils.import("resource://gre/modules/LegacyExtensionsUtils.jsm"); - -// Wait the startup of the embedded webextension. -function promiseWebExtensionStartup() { - return new Promise(resolve => { - let listener = (event, extension) => { - Management.off("startup", listener); - resolve(extension); - }; - - Management.on("startup", listener); - }); -} - -function promiseWebExtensionShutdown() { - return new Promise(resolve => { - let listener = (event, extension) => { - Management.off("shutdown", listener); - resolve(extension); - }; - - Management.on("shutdown", listener); - }); -} - -const BOOTSTRAP = String.raw` - Components.utils.import("resource://xpcshell-data/BootstrapMonitor.jsm").monitor(this); -`; - -const EMBEDDED_WEBEXT_MANIFEST = JSON.stringify({ - name: "embedded webextension addon", - manifest_version: 2, - version: "1.0", -}); - -/** - * This test case checks that an hasEmbeddedWebExtension addon property - * is persisted and restored correctly across restarts. - */ -add_task(function* has_embedded_webextension_persisted() { - const ID = "embedded-webextension-addon-persist@tests.mozilla.org"; - - const xpiFile = createTempXPIFile({ - id: ID, - name: "Test Add-on", - version: "1.0", - bootstrap: true, - hasEmbeddedWebExtension: true, - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "1", - maxVersion: "1.9.2" - }] - }, { - "bootstrap.js": BOOTSTRAP, - "webextension/manifest.json": EMBEDDED_WEBEXT_MANIFEST, - }); - - yield promiseInstallFile(xpiFile); - - let addon = yield promiseAddonByID(ID); - - notEqual(addon, null, "Got an addon object as expected"); - equal(addon.version, "1.0", "Got the expected version"); - equal(addon.hasEmbeddedWebExtension, true, - "Got the expected hasEmbeddedWebExtension value"); - - // Check that the addon has been installed and started. - BootstrapMonitor.checkAddonInstalled(ID, "1.0"); - BootstrapMonitor.checkAddonStarted(ID, "1.0"); - - let startupInfo = BootstrapMonitor.started.get(ID); - ok(("webExtension" in startupInfo.data), - "Got an webExtension property in the startup bootstrap method params"); - ok(("startup" in startupInfo.data.webExtension), - "Got the expected 'startup' property in the webExtension object"); - - // After restarting the manager, the add-on should still have the - // hasEmbeddedWebExtension property as expected. - yield promiseRestartManager(); - - let persisted = JSON.parse(Services.prefs.getCharPref("extensions.bootstrappedAddons")); - ok(ID in persisted, "Hybrid add-on persisted to bootstrappedAddons."); - equal(persisted[ID].hasEmbeddedWebExtension, true, - "hasEmbeddedWebExtension flag persisted to bootstrappedAddons."); - - // Check that the addon has been installed and started. - BootstrapMonitor.checkAddonInstalled(ID, "1.0"); - BootstrapMonitor.checkAddonStarted(ID, "1.0"); - - addon = yield promiseAddonByID(ID); - notEqual(addon, null, "Got an addon object as expected"); - equal(addon.hasEmbeddedWebExtension, true, "Got the expected hasEmbeddedWebExtension value"); - - // Check that the addon has been installed and started. - let newStartupInfo = BootstrapMonitor.started.get(ID); - ok(("webExtension" in newStartupInfo.data), - "Got an webExtension property in the startup bootstrap method params"); - ok(("startup" in newStartupInfo.data.webExtension), - "Got the expected 'startup' property in the webExtension object"); - - let waitUninstall = promiseAddonEvent("onUninstalled"); - addon.uninstall(); - yield waitUninstall; -}); - -/** - * This test case checks that an addon with hasEmbeddedWebExtension set to true - * in its install.rdf gets the expected `embeddedWebExtension` object in the - * parameters of its bootstrap methods. - */ -add_task(function* run_embedded_webext_bootstrap() { - const ID = "embedded-webextension-addon2@tests.mozilla.org"; - - const xpiFile = createTempXPIFile({ - id: ID, - name: "Test Add-on", - version: "1.0", - bootstrap: true, - hasEmbeddedWebExtension: true, - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "1", - maxVersion: "1.9.2" - }] - }, { - "bootstrap.js": BOOTSTRAP, - "webextension/manifest.json": EMBEDDED_WEBEXT_MANIFEST, - }); - - yield AddonManager.installTemporaryAddon(xpiFile); - - let addon = yield promiseAddonByID(ID); - - notEqual(addon, null, "Got an addon object as expected"); - equal(addon.version, "1.0", "Got the expected version"); - equal(addon.hasEmbeddedWebExtension, true, - "Got the expected hasEmbeddedWebExtension value"); - - // Check that the addon has been installed and started. - BootstrapMonitor.checkAddonInstalled(ID, "1.0"); - - let installInfo = BootstrapMonitor.installed.get(ID); - ok(!("webExtension" in installInfo.data), - "No webExtension property is expected in the install bootstrap method params"); - - BootstrapMonitor.checkAddonStarted(ID, "1.0"); - - let startupInfo = BootstrapMonitor.started.get(ID); - - ok(("webExtension" in startupInfo.data), - "Got an webExtension property in the startup bootstrap method params"); - - ok(("startup" in startupInfo.data.webExtension), - "Got the expected 'startup' property in the webExtension object"); - - const waitForWebExtensionStartup = promiseWebExtensionStartup(); - - const embeddedAPI = yield startupInfo.data.webExtension.startup(); - - // WebExtension startup should have been fully resolved. - yield waitForWebExtensionStartup; - - Assert.deepEqual( - Object.keys(embeddedAPI.browser.runtime).sort(), - ["onConnect", "onMessage"], - `Got the expected 'runtime' in the 'browser' API object` - ); - - // Uninstall the addon and wait that the embedded webextension has been stopped and - // test the params of the shutdown and uninstall bootstrap method. - let waitForWebExtensionShutdown = promiseWebExtensionShutdown(); - let waitUninstall = promiseAddonEvent("onUninstalled"); - addon.uninstall(); - yield waitForWebExtensionShutdown; - yield waitUninstall; - - BootstrapMonitor.checkAddonNotStarted(ID, "1.0"); - - let shutdownInfo = BootstrapMonitor.stopped.get(ID); - ok(!("webExtension" in shutdownInfo.data), - "No webExtension property is expected in the shutdown bootstrap method params"); - - let uninstallInfo = BootstrapMonitor.uninstalled.get(ID); - ok(!("webExtension" in uninstallInfo.data), - "No webExtension property is expected in the uninstall bootstrap method params"); -}); - -/** - * This test case checks that an addon with hasEmbeddedWebExtension can be reloaded - * without raising unexpected exceptions due to race conditions. - */ -add_task(function* reload_embedded_webext_bootstrap() { - const ID = "embedded-webextension-addon2@tests.mozilla.org"; - - // No embedded webextension should be currently around. - equal(EmbeddedExtensionManager.embeddedExtensionsByAddonId.size, 0, - "No embedded extension instance should be tracked here"); - - const xpiFile = createTempXPIFile({ - id: ID, - name: "Test Add-on", - version: "1.0", - bootstrap: true, - hasEmbeddedWebExtension: true, - targetApplications: [{ - id: "xpcshell@tests.mozilla.org", - minVersion: "1", - maxVersion: "1.9.2" - }] - }, { - "bootstrap.js": BOOTSTRAP, - "webextension/manifest.json": EMBEDDED_WEBEXT_MANIFEST, - }); - - yield AddonManager.installTemporaryAddon(xpiFile); - - let addon = yield promiseAddonByID(ID); - - notEqual(addon, null, "Got an addon object as expected"); - equal(addon.version, "1.0", "Got the expected version"); - equal(addon.isActive, true, "The Addon is active"); - equal(addon.appDisabled, false, "The addon is not app disabled"); - equal(addon.userDisabled, false, "The addon is not user disabled"); - - // Check that the addon has been installed and started. - BootstrapMonitor.checkAddonInstalled(ID, "1.0"); - BootstrapMonitor.checkAddonStarted(ID, "1.0"); - - // Only one embedded extension. - equal(EmbeddedExtensionManager.embeddedExtensionsByAddonId.size, 1, - "Got the expected number of tracked extension instances"); - - const embeddedWebExtension = EmbeddedExtensionManager.embeddedExtensionsByAddonId.get(ID); - - let startupInfo = BootstrapMonitor.started.get(ID); - yield startupInfo.data.webExtension.startup(); - - const waitForAddonDisabled = promiseAddonEvent("onDisabled"); - addon.userDisabled = true; - yield waitForAddonDisabled; - - // No embedded webextension should be currently around. - equal(EmbeddedExtensionManager.embeddedExtensionsByAddonId.size, 0, - "No embedded extension instance should be tracked here"); - - const waitForAddonEnabled = promiseAddonEvent("onEnabled"); - addon.userDisabled = false; - yield waitForAddonEnabled; - - // Only one embedded extension. - equal(EmbeddedExtensionManager.embeddedExtensionsByAddonId.size, 1, - "Got the expected number of tracked extension instances"); - - const embeddedWebExtensionAfterEnabled = EmbeddedExtensionManager.embeddedExtensionsByAddonId.get(ID); - notEqual(embeddedWebExtensionAfterEnabled, embeddedWebExtension, - "Got a new EmbeddedExtension instance after the addon has been disabled and then enabled"); - - startupInfo = BootstrapMonitor.started.get(ID); - yield startupInfo.data.webExtension.startup(); - - const waitForReinstalled = promiseAddonEvent("onInstalled"); - addon.reload(); - yield waitForReinstalled; - - // No leaked embedded extension after the previous reloads. - equal(EmbeddedExtensionManager.embeddedExtensionsByAddonId.size, 1, - "Got the expected number of tracked extension instances"); - - const embeddedWebExtensionAfterReload = EmbeddedExtensionManager.embeddedExtensionsByAddonId.get(ID); - notEqual(embeddedWebExtensionAfterReload, embeddedWebExtensionAfterEnabled, - "Got a new EmbeddedExtension instance after the addon has been reloaded"); - - startupInfo = BootstrapMonitor.started.get(ID); - yield startupInfo.data.webExtension.startup(); - - // Uninstall the test addon - let waitUninstalled = promiseAddonEvent("onUninstalled"); - addon.uninstall(); - yield waitUninstalled; - - // No leaked embedded extension after uninstalling. - equal(EmbeddedExtensionManager.embeddedExtensionsByAddonId.size, 0, - "No embedded extension instance should be tracked after the addon uninstall"); -}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_webextension_icons.js b/toolkit/mozapps/extensions/test/xpcshell/test_webextension_icons.js deleted file mode 100644 index 25fb4115f..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_webextension_icons.js +++ /dev/null @@ -1,169 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -const ID = "webextension1@tests.mozilla.org"; - -const profileDir = gProfD.clone(); -profileDir.append("extensions"); -profileDir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY); - -createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "42"); -startupManager(); - -const { Management } = Components.utils.import("resource://gre/modules/Extension.jsm", {}); - -function promiseAddonStartup() { - return new Promise(resolve => { - let listener = (evt, extension) => { - Management.off("startup", listener); - resolve(extension); - }; - - Management.on("startup", listener); - }); -} - -// Test simple icon set parsing -add_task(function*() { - yield promiseWriteWebManifestForExtension({ - name: "Web Extension Name", - version: "1.0", - manifest_version: 2, - applications: { - gecko: { - id: ID - } - }, - icons: { - 16: "icon16.png", - 32: "icon32.png", - 48: "icon48.png", - 64: "icon64.png" - } - }, profileDir); - - yield promiseRestartManager(); - yield promiseAddonStartup(); - - let uri = do_get_addon_root_uri(profileDir, ID); - - let addon = yield promiseAddonByID(ID); - do_check_neq(addon, null); - - function check_icons(addon_copy) { - deepEqual(addon_copy.icons, { - 16: uri + "icon16.png", - 32: uri + "icon32.png", - 48: uri + "icon48.png", - 64: uri + "icon64.png" - }); - - // iconURL should map to icons[48] and icons[64] - equal(addon.iconURL, uri + "icon48.png"); - equal(addon.icon64URL, uri + "icon64.png"); - - // AddonManager gets the correct icon sizes from addon.icons - equal(AddonManager.getPreferredIconURL(addon, 1), uri + "icon16.png"); - equal(AddonManager.getPreferredIconURL(addon, 16), uri + "icon16.png"); - equal(AddonManager.getPreferredIconURL(addon, 30), uri + "icon32.png"); - equal(AddonManager.getPreferredIconURL(addon, 48), uri + "icon48.png"); - equal(AddonManager.getPreferredIconURL(addon, 64), uri + "icon64.png"); - equal(AddonManager.getPreferredIconURL(addon, 128), uri + "icon64.png"); - } - - check_icons(addon); - - // check if icons are persisted through a restart - yield promiseRestartManager(); - yield promiseAddonStartup(); - - addon = yield promiseAddonByID(ID); - do_check_neq(addon, null); - - check_icons(addon); - - addon.uninstall(); - - yield promiseRestartManager(); -}); - -// Test AddonManager.getPreferredIconURL for retina screen sizes -add_task(function*() { - yield promiseWriteWebManifestForExtension({ - name: "Web Extension Name", - version: "1.0", - manifest_version: 2, - applications: { - gecko: { - id: ID - } - }, - icons: { - 32: "icon32.png", - 48: "icon48.png", - 64: "icon64.png", - 128: "icon128.png", - 256: "icon256.png" - } - }, profileDir); - - yield promiseRestartManager(); - yield promiseAddonStartup(); - - let addon = yield promiseAddonByID(ID); - do_check_neq(addon, null); - - let uri = do_get_addon_root_uri(profileDir, ID); - - // AddonManager displays larger icons for higher pixel density - equal(AddonManager.getPreferredIconURL(addon, 32, { - devicePixelRatio: 2 - }), uri + "icon64.png"); - - equal(AddonManager.getPreferredIconURL(addon, 48, { - devicePixelRatio: 2 - }), uri + "icon128.png"); - - equal(AddonManager.getPreferredIconURL(addon, 64, { - devicePixelRatio: 2 - }), uri + "icon128.png"); - - addon.uninstall(); - - yield promiseRestartManager(); -}); - -// Handles no icons gracefully -add_task(function*() { - yield promiseWriteWebManifestForExtension({ - name: "Web Extension Name", - version: "1.0", - manifest_version: 2, - applications: { - gecko: { - id: ID - } - } - }, profileDir); - - yield promiseRestartManager(); - yield promiseAddonStartup(); - - let addon = yield promiseAddonByID(ID); - do_check_neq(addon, null); - - let uri = do_get_addon_root_uri(profileDir, ID); - - deepEqual(addon.icons, {}); - - equal(addon.iconURL, null); - equal(addon.icon64URL, null); - - equal(AddonManager.getPreferredIconURL(addon, 128), null); - - addon.uninstall(); - - yield promiseRestartManager(); -}); - diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_webextension_install.js b/toolkit/mozapps/extensions/test/xpcshell/test_webextension_install.js deleted file mode 100644 index 1e7c9d9b7..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_webextension_install.js +++ /dev/null @@ -1,478 +0,0 @@ - -const {ADDON_SIGNING} = AM_Cu.import("resource://gre/modules/addons/AddonConstants.jsm", {}); - -function run_test() { - run_next_test(); -} - -let profileDir; -add_task(function* setup() { - profileDir = gProfD.clone(); - profileDir.append("extensions"); - - if (!profileDir.exists()) - profileDir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY); - - createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); - startupManager(); -}); - -const IMPLICIT_ID_XPI = "data/webext-implicit-id.xpi"; -const IMPLICIT_ID_ID = "webext_implicit_id@tests.mozilla.org"; - -// webext-implicit-id.xpi has a minimal manifest with no -// applications or browser_specific_settings, so its id comes -// from its signature, which should be the ID constant defined below. -add_task(function* test_implicit_id() { - // This test needs to read the xpi certificate which only works - // if signing is enabled. - ok(ADDON_SIGNING, "Add-on signing is enabled"); - - let addon = yield promiseAddonByID(IMPLICIT_ID_ID); - equal(addon, null, "Add-on is not installed"); - - let xpifile = do_get_file(IMPLICIT_ID_XPI); - yield promiseInstallAllFiles([xpifile]); - - addon = yield promiseAddonByID(IMPLICIT_ID_ID); - notEqual(addon, null, "Add-on is installed"); - - addon.uninstall(); -}); - -// We should also be able to install webext-implicit-id.xpi temporarily -// and it should look just like the regular install (ie, the ID should -// come from the signature) -add_task(function* test_implicit_id_temp() { - // This test needs to read the xpi certificate which only works - // if signing is enabled. - ok(ADDON_SIGNING, "Add-on signing is enabled"); - - let addon = yield promiseAddonByID(IMPLICIT_ID_ID); - equal(addon, null, "Add-on is not installed"); - - let xpifile = do_get_file(IMPLICIT_ID_XPI); - yield AddonManager.installTemporaryAddon(xpifile); - - addon = yield promiseAddonByID(IMPLICIT_ID_ID); - notEqual(addon, null, "Add-on is installed"); - - // The sourceURI of a temporary installed addon should be equal to the - // file url of the installed xpi file. - equal(addon.sourceURI && addon.sourceURI.spec, - Services.io.newFileURI(xpifile).spec, - "SourceURI of the add-on has the expected value"); - - addon.uninstall(); -}); - -// We should be able to temporarily install an unsigned web extension -// that does not have an ID in its manifest. -add_task(function* test_unsigned_no_id_temp_install() { - AddonTestUtils.useRealCertChecks = true; - const manifest = { - name: "no ID", - description: "extension without an ID", - manifest_version: 2, - version: "1.0" - }; - - const addonDir = yield promiseWriteWebManifestForExtension(manifest, gTmpD, - "the-addon-sub-dir"); - const addon = yield AddonManager.installTemporaryAddon(addonDir); - ok(addon.id, "ID should have been auto-generated"); - - // The sourceURI of a temporary installed addon should be equal to the - // file url of the installed source dir. - equal(addon.sourceURI && addon.sourceURI.spec, - Services.io.newFileURI(addonDir).spec, - "SourceURI of the add-on has the expected value"); - - // Install the same directory again, as if re-installing or reloading. - const secondAddon = yield AddonManager.installTemporaryAddon(addonDir); - // The IDs should be the same. - equal(secondAddon.id, addon.id, "Reinstalled add-on has the expected ID"); - - secondAddon.uninstall(); - Services.obs.notifyObservers(addonDir, "flush-cache-entry", null); - addonDir.remove(true); - AddonTestUtils.useRealCertChecks = false; -}); - -// We should be able to install two extensions from manifests without IDs -// at different locations and get two unique extensions. -add_task(function* test_multiple_no_id_extensions() { - AddonTestUtils.useRealCertChecks = true; - const manifest = { - name: "no ID", - description: "extension without an ID", - manifest_version: 2, - version: "1.0" - }; - - let extension1 = ExtensionTestUtils.loadExtension({ - manifest: manifest, - useAddonManager: "temporary", - }); - - let extension2 = ExtensionTestUtils.loadExtension({ - manifest: manifest, - useAddonManager: "temporary", - }); - - yield Promise.all([extension1.startup(), extension2.startup()]); - - const allAddons = yield new Promise(resolve => { - AddonManager.getAllAddons(addons => resolve(addons)); - }); - do_print(`Found these add-ons: ${allAddons.map(a => a.name).join(", ")}`); - const filtered = allAddons.filter(addon => addon.name === manifest.name); - // Make sure we have two add-ons by the same name. - equal(filtered.length, 2, "Two add-ons are installed with the same name"); - - yield extension1.unload(); - yield extension2.unload(); - AddonTestUtils.useRealCertChecks = false; -}); - -// Test that we can get the ID from browser_specific_settings -add_task(function* test_bss_id() { - const ID = "webext_bss_id@tests.mozilla.org"; - - let manifest = { - name: "bss test", - description: "test that ID may be in browser_specific_settings", - manifest_version: 2, - version: "1.0", - - browser_specific_settings: { - gecko: { - id: ID - } - } - }; - - let addon = yield promiseAddonByID(ID); - equal(addon, null, "Add-on is not installed"); - - let extension = ExtensionTestUtils.loadExtension({ - manifest: manifest, - useAddonManager: "temporary", - }); - yield extension.startup(); - - addon = yield promiseAddonByID(ID); - notEqual(addon, null, "Add-on is installed"); - - yield extension.unload(); -}); - -// Test that if we have IDs in both browser_specific_settings and applications, -// that we prefer the ID in browser_specific_settings. -add_task(function* test_two_ids() { - const GOOD_ID = "two_ids@tests.mozilla.org"; - const BAD_ID = "i_am_obsolete@tests.mozilla.org"; - - let manifest = { - name: "two id test", - description: "test a web extension with ids in both applications and browser_specific_settings", - manifest_version: 2, - version: "1.0", - - applications: { - gecko: { - id: BAD_ID - } - }, - - browser_specific_settings: { - gecko: { - id: GOOD_ID - } - } - } - - let extension = ExtensionTestUtils.loadExtension({ - manifest: manifest, - useAddonManager: "temporary", - }); - yield extension.startup(); - - let addon = yield promiseAddonByID(BAD_ID); - equal(addon, null, "Add-on is not found using bad ID"); - addon = yield promiseAddonByID(GOOD_ID); - notEqual(addon, null, "Add-on is found using good ID"); - - yield extension.unload(); -}); - -// Test that strict_min_version and strict_max_version are enforced for -// loading temporary extension. -add_task(function* test_strict_min_max() { - // the app version being compared to is 1.9.2 - const addonId = "strict_min_max@tests.mozilla.org"; - const MANIFEST = { - name: "strict min max test", - description: "test strict min and max with temporary loading", - manifest_version: 2, - version: "1.0", - }; - - // bad max good min - let apps = { - applications: { - gecko: { - id: addonId, - strict_min_version: "1", - strict_max_version: "1" - }, - }, - } - let testManifest = Object.assign(apps, MANIFEST); - - let extension = ExtensionTestUtils.loadExtension({ - manifest: testManifest, - useAddonManager: "temporary", - }); - - let expectedMsg = new RegExp("Add-on strict_min_max@tests.mozilla.org is not compatible with application version. " + - "add-on minVersion: 1. add-on maxVersion: 1."); - yield Assert.rejects(extension.startup(), - expectedMsg, - "Install rejects when specified maxVersion is not valid"); - - let addon = yield promiseAddonByID(addonId); - equal(addon, null, "Add-on is not installed"); - - // bad min good max - apps = { - applications: { - gecko: { - id: addonId, - strict_min_version: "2", - strict_max_version: "2" - }, - }, - } - testManifest = Object.assign(apps, MANIFEST); - - extension = ExtensionTestUtils.loadExtension({ - manifest: testManifest, - useAddonManager: "temporary", - }); - - expectedMsg = new RegExp("Add-on strict_min_max@tests.mozilla.org is not compatible with application version. " + - "add-on minVersion: 2. add-on maxVersion: 2."); - yield Assert.rejects(extension.startup(), - expectedMsg, - "Install rejects when specified minVersion is not valid"); - - addon = yield promiseAddonByID(addonId); - equal(addon, null, "Add-on is not installed"); - - // bad both - apps = { - applications: { - gecko: { - id: addonId, - strict_min_version: "2", - strict_max_version: "1" - }, - }, - } - testManifest = Object.assign(apps, MANIFEST); - - extension = ExtensionTestUtils.loadExtension({ - manifest: testManifest, - useAddonManager: "temporary", - }); - - expectedMsg = new RegExp("Add-on strict_min_max@tests.mozilla.org is not compatible with application version. " + - "add-on minVersion: 2. add-on maxVersion: 1."); - yield Assert.rejects(extension.startup(), - expectedMsg, - "Install rejects when specified minVersion and maxVersion are not valid"); - - addon = yield promiseAddonByID(addonId); - equal(addon, null, "Add-on is not installed"); - - // bad only min - apps = { - applications: { - gecko: { - id: addonId, - strict_min_version: "2" - }, - }, - } - testManifest = Object.assign(apps, MANIFEST); - - extension = ExtensionTestUtils.loadExtension({ - manifest: testManifest, - useAddonManager: "temporary", - }); - - expectedMsg = new RegExp("Add-on strict_min_max@tests.mozilla.org is not compatible with application version\. " + - "add-on minVersion: 2\."); - yield Assert.rejects(extension.startup(), - expectedMsg, - "Install rejects when specified minVersion and maxVersion are not valid"); - - addon = yield promiseAddonByID(addonId); - equal(addon, null, "Add-on is not installed"); - - // bad only max - apps = { - applications: { - gecko: { - id: addonId, - strict_max_version: "1" - }, - }, - } - testManifest = Object.assign(apps, MANIFEST); - - extension = ExtensionTestUtils.loadExtension({ - manifest: testManifest, - useAddonManager: "temporary", - }); - - expectedMsg = new RegExp("Add-on strict_min_max@tests.mozilla.org is not compatible with application version\. " + - "add-on maxVersion: 1\."); - yield Assert.rejects(extension.startup(), - expectedMsg, - "Install rejects when specified minVersion and maxVersion are not valid"); - - addon = yield promiseAddonByID(addonId); - equal(addon, null, "Add-on is not installed"); - - // good both - apps = { - applications: { - gecko: { - id: addonId, - strict_min_version: "1", - strict_max_version: "2" - }, - }, - } - testManifest = Object.assign(apps, MANIFEST); - - extension = ExtensionTestUtils.loadExtension({ - manifest: testManifest, - useAddonManager: "temporary", - }); - - yield extension.startup(); - addon = yield promiseAddonByID(addonId); - - notEqual(addon, null, "Add-on is installed"); - equal(addon.id, addonId, "Installed add-on has the expected ID"); - yield extension.unload(); - - // good only min - let newId = "strict_min_only@tests.mozilla.org"; - apps = { - applications: { - gecko: { - id: newId, - strict_min_version: "1", - }, - }, - } - testManifest = Object.assign(apps, MANIFEST); - - extension = ExtensionTestUtils.loadExtension({ - manifest: testManifest, - useAddonManager: "temporary", - }); - - yield extension.startup(); - addon = yield promiseAddonByID(newId); - - notEqual(addon, null, "Add-on is installed"); - equal(addon.id, newId, "Installed add-on has the expected ID"); - - yield extension.unload(); - - // good only max - newId = "strict_max_only@tests.mozilla.org"; - apps = { - applications: { - gecko: { - id: newId, - strict_max_version: "2", - }, - }, - } - testManifest = Object.assign(apps, MANIFEST); - - extension = ExtensionTestUtils.loadExtension({ - manifest: testManifest, - useAddonManager: "temporary", - }); - - yield extension.startup(); - addon = yield promiseAddonByID(newId); - - notEqual(addon, null, "Add-on is installed"); - equal(addon.id, newId, "Installed add-on has the expected ID"); - - yield extension.unload(); - - // * in min will throw an error - for (let version of ["0.*", "0.*.0"]) { - newId = "strict_min_star@tests.mozilla.org"; - let minStarApps = { - applications: { - gecko: { - id: newId, - strict_min_version: version, - }, - }, - } - - let minStarTestManifest = Object.assign(minStarApps, MANIFEST); - - let minStarExtension = ExtensionTestUtils.loadExtension({ - manifest: minStarTestManifest, - useAddonManager: "temporary", - }); - - yield Assert.rejects( - minStarExtension.startup(), - /The use of '\*' in strict_min_version is invalid/, - "loading an extension with a * in strict_min_version throws an exception"); - - let minStarAddon = yield promiseAddonByID(newId); - equal(minStarAddon, null, "Add-on is not installed"); - } - - // incompatible extension but with compatibility checking off - newId = "checkCompatibility@tests.mozilla.org"; - apps = { - applications: { - gecko: { - id: newId, - strict_max_version: "1", - }, - }, - } - testManifest = Object.assign(apps, MANIFEST); - - extension = ExtensionTestUtils.loadExtension({ - manifest: testManifest, - useAddonManager: "temporary", - }); - - let savedCheckCompatibilityValue = AddonManager.checkCompatibility; - AddonManager.checkCompatibility = false; - yield extension.startup(); - addon = yield promiseAddonByID(newId); - - notEqual(addon, null, "Add-on is installed"); - equal(addon.id, newId, "Installed add-on has the expected ID"); - - yield extension.unload(); - AddonManager.checkCompatibility = savedCheckCompatibilityValue; -}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_webextension_paths.js b/toolkit/mozapps/extensions/test/xpcshell/test_webextension_paths.js deleted file mode 100644 index 29a3dacf7..000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_webextension_paths.js +++ /dev/null @@ -1,55 +0,0 @@ -function run_test() { - run_next_test(); -} - -let profileDir; -add_task(function* setup() { - profileDir = gProfD.clone(); - profileDir.append("extensions"); - - createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); - startupManager(); -}); - -// When installing an unpacked addon we derive the ID from the -// directory name. Make sure that if the directoy name is not a valid -// addon ID that we reject it. -add_task(function* test_bad_unpacked_path() { - let MANIFEST_ID = "webext_bad_path@tests.mozilla.org"; - - let manifest = { - name: "path test", - description: "test of a bad directory name", - manifest_version: 2, - version: "1.0", - - browser_specific_settings: { - gecko: { - id: MANIFEST_ID - } - } - }; - - const directories = [ - "not a valid ID", - '"quotes"@tests.mozilla.org', - ]; - - for (let dir of directories) { - try { - yield promiseWriteWebManifestForExtension(manifest, profileDir, dir); - } catch (ex) { - // This can fail if the underlying filesystem (looking at you windows) - // doesn't handle some of the characters in the ID. In that case, - // just ignore this test on this platform. - continue; - } - yield promiseRestartManager(); - - let addon = yield promiseAddonByID(dir); - do_check_eq(addon, null); - addon = yield promiseAddonByID(MANIFEST_ID); - do_check_eq(addon, null); - } -}); - diff --git a/toolkit/mozapps/extensions/test/xpcshell/xpcshell-shared.ini b/toolkit/mozapps/extensions/test/xpcshell/xpcshell-shared.ini index 1e86e5861..2a12f147a 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/xpcshell-shared.ini +++ b/toolkit/mozapps/extensions/test/xpcshell/xpcshell-shared.ini @@ -1,14 +1,10 @@ # The file is shared between the two main xpcshell manifest files. [DEFAULT] -skip-if = toolkit == 'android' -tags = addons +skip-if = toolkit == 'android' || toolkit == 'gonk' [test_AddonRepository.js] -[test_reload.js] # Bug 676992: test consistently hangs on Android -# There's a problem removing a temp file without manually clearing the cache on Windows -skip-if = os == "android" || os == "win" -tags = webextensions +skip-if = os == "android" [test_AddonRepository_cache.js] # Bug 676992: test consistently hangs on Android # Bug 1026805: frequent hangs on OSX 10.8 @@ -116,7 +112,7 @@ skip-if = os == "android" skip-if = os == "android" [test_bug514327_2.js] # Bug 676992: test consistently hangs on Android -skip-if = os == "android" +skip-if = buildapp == "mulet" || os == "android" [test_bug514327_3.js] # Bug 676992: test consistently hangs on Android skip-if = os == "android" @@ -140,6 +136,7 @@ fail-if = os == "android" [test_bug594058.js] [test_bug595081.js] [test_bug595573.js] +[test_bug596343.js] [test_bug596607.js] [test_bug616841.js] # Bug 676992: test consistently fails on Android @@ -195,12 +192,8 @@ skip-if = os == "android" [test_gfxBlacklist_OSVersion_mismatch_OSVersion.js] [test_gfxBlacklist_OSVersion_mismatch_DriverVersion.js] [test_gfxBlacklist_Vendor.js] -[test_gfxBlacklist_Version.js] [test_gfxBlacklist_prefs.js] -# Bug 1248787 - consistently fails -skip-if = true [test_hasbinarycomponents.js] -[test_hotfix.js] [test_install.js] [test_install_icons.js] # Bug 676992: test consistently hangs on Android @@ -233,31 +226,16 @@ requesttimeoutfactor = 2 [test_permissions.js] [test_permissions_prefs.js] [test_plugins.js] +skip-if = buildapp == "mulet" [test_pluginchange.js] # PluginProvider.jsm is not shipped on Android skip-if = os == "android" [test_pluginBlocklistCtp.js] # Bug 676992: test consistently fails on Android -fail-if = os == "android" +fail-if = buildapp == "mulet" || os == "android" [test_pref_properties.js] [test_registry.js] [test_safemode.js] -[test_signed_updatepref.js] -run-if = addon_signing -skip-if = require_signing -[test_signed_verify.js] -run-if = addon_signing -[test_signed_inject.js] -run-if = addon_signing -[test_signed_install.js] -run-if = addon_signing -run-sequentially = Uses hardcoded ports in xpi files. -[test_signed_long.js] -run-if = addon_signing -[test_signed_migrate.js] -run-if = addon_signing -[test_signed_multi.js] -run-if = addon_signing [test_startup.js] # Bug 676992: test consistently fails on Android fail-if = os == "android" @@ -274,8 +252,6 @@ fail-if = os == "android" [test_update.js] # Bug 676992: test consistently hangs on Android skip-if = os == "android" -[test_update_webextensions.js] -tags = webextensions [test_updateCancel.js] [test_update_strictcompat.js] # Bug 676992: test consistently hangs on Android @@ -287,9 +263,6 @@ skip-if = os == "android" # Bug 676992: test consistently hangs on Android skip-if = os == "android" run-sequentially = Uses hardcoded ports in xpi files. -[test_json_updatecheck.js] -[test_seen.js] -[test_seen_newprofile.js] [test_updateid.js] # Bug 676992: test consistently hangs on Android skip-if = os == "android" @@ -306,29 +279,4 @@ run-sequentially = Uses global XCurProcD dir. [test_overrideblocklist.js] run-sequentially = Uses global XCurProcD dir. [test_sourceURI.js] -[test_webextension_icons.js] -skip-if = appname == "thunderbird" -tags = webextensions -[test_webextension.js] -skip-if = appname == "thunderbird" -tags = webextensions -[test_webextension_install.js] -skip-if = appname == "thunderbird" -tags = webextensions -[test_webextension_embedded.js] -skip-if = appname == "thunderbird" -tags = webextensions [test_bootstrap_globals.js] -[test_bug1180901_2.js] -skip-if = os != "win" -[test_bug1180901.js] -skip-if = os != "win" -[test_e10s_restartless.js] -[test_switch_os.js] -# Bug 1246231 -skip-if = os == "mac" && debug -[test_softblocked.js] -[test_ext_management.js] -skip-if = appname == "thunderbird" -tags = webextensions - diff --git a/toolkit/mozapps/extensions/test/xpcshell/xpcshell-unpack.ini b/toolkit/mozapps/extensions/test/xpcshell/xpcshell-unpack.ini index 42a0ca1ca..51520f888 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/xpcshell-unpack.ini +++ b/toolkit/mozapps/extensions/test/xpcshell/xpcshell-unpack.ini @@ -2,11 +2,7 @@ head = head_addons.js head_unpack.js tail = firefox-appdir = browser -skip-if = toolkit == 'android' +skip-if = toolkit == 'android' || toolkit == 'gonk' dupe-manifest = -tags = addons - -[test_webextension_paths.js] -tags = webextensions [include:xpcshell-shared.ini] diff --git a/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini b/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini index 2b95eb158..83ab77c74 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini +++ b/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini @@ -1,6 +1,5 @@ [DEFAULT] -skip-if = toolkit == 'android' -tags = addons +skip-if = buildapp == 'mulet' || toolkit == 'android' || toolkit == 'gonk' head = head_addons.js tail = firefox-appdir = browser @@ -11,14 +10,10 @@ support-files = [test_addon_path_service.js] [test_asyncBlocklistLoad.js] -[test_blocklist_gfx.js] -[test_cache_certdb.js] -run-if = addon_signing [test_cacheflush.js] [test_DeferredSave.js] [test_gmpProvider.js] -skip-if = appname != "firefox" -[test_hotfix_cert.js] +run-if = appname == "firefox" [test_isReady.js] [test_metadata_update.js] [test_pluginInfoURL.js] @@ -26,25 +21,8 @@ skip-if = appname != "firefox" [test_provider_shutdown.js] [test_provider_unsafe_access_shutdown.js] [test_provider_unsafe_access_startup.js] -[test_ProductAddonChecker.js] [test_shutdown.js] -[test_system_update.js] -[test_system_reset.js] [test_XPIcancel.js] [test_XPIStates.js] -[test_temporary.js] -tags = webextensions -[test_install_from_sources.js] -[test_proxies.js] -[test_proxy.js] -[test_pass_symbol.js] -[test_delay_update.js] -[test_nodisable_hidden.js] -[test_delay_update_webextension.js] -skip-if = appname == "thunderbird" -tags = webextensions -[test_dependencies.js] -[test_schema_change.js] -[test_system_delay_update.js] [include:xpcshell-shared.ini] diff --git a/toolkit/mozapps/extensions/test/xpinstall/.eslintrc.js b/toolkit/mozapps/extensions/test/xpinstall/.eslintrc.js deleted file mode 100644 index 2852eb81d..000000000 --- a/toolkit/mozapps/extensions/test/xpinstall/.eslintrc.js +++ /dev/null @@ -1,7 +0,0 @@ -"use strict"; - -module.exports = { // eslint-disable-line no-undef - "extends": [ - "../../../../../testing/mochitest/browser.eslintrc.js" - ] -}; diff --git a/toolkit/mozapps/extensions/test/xpinstall/amosigned.xpi b/toolkit/mozapps/extensions/test/xpinstall/amosigned.xpi Binary files differdeleted file mode 100644 index 4edf91e34..000000000 --- a/toolkit/mozapps/extensions/test/xpinstall/amosigned.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpinstall/amosigned2.xpi b/toolkit/mozapps/extensions/test/xpinstall/amosigned2.xpi Binary files differdeleted file mode 100644 index 74e877f26..000000000 --- a/toolkit/mozapps/extensions/test/xpinstall/amosigned2.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser.ini b/toolkit/mozapps/extensions/test/xpinstall/browser.ini index 5627f47a2..d6392cdc8 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser.ini +++ b/toolkit/mozapps/extensions/test/xpinstall/browser.ini @@ -1,7 +1,5 @@ [DEFAULT] support-files = - amosigned.xpi - amosigned2.xpi authRedirect.sjs bug540558.html bug638292.html @@ -21,8 +19,6 @@ support-files = navigate.html redirect.sjs restartless.xpi - restartless-unsigned.xpi - signed-multipackage.xpi signed-no-cn.xpi signed-no-o.xpi signed-tampered.xpi @@ -35,9 +31,6 @@ support-files = triggerredirect.html unsigned.xpi -[browser_amosigned_trigger.js] -[browser_amosigned_trigger_iframe.js] -[browser_amosigned_url.js] [browser_auth.js] [browser_auth2.js] [browser_auth3.js] @@ -49,9 +42,10 @@ support-files = [browser_bug540558.js] [browser_bug611242.js] [browser_bug638292.js] +skip-if = e10s # Bug 1083269 [browser_bug645699.js] -[browser_bug672485.js] -skip-if = true # disabled due to a leak. See bug 682410. +# [browser_bug672485.js] +# disabled due to a leak. See bug 682410. [browser_cancel.js] [browser_concurrent_installs.js] [browser_cookies.js] @@ -66,7 +60,6 @@ skip-if = true # Bug 1084646 [browser_enabled2.js] [browser_enabled3.js] [browser_hash.js] -[browser_hash2.js] [browser_httphash.js] [browser_httphash2.js] [browser_httphash3.js] @@ -82,34 +75,24 @@ skip-if = true # Bug 1084646 [browser_navigateaway.js] [browser_navigateaway2.js] [browser_navigateaway3.js] -skip-if = (os == "mac" || os == "win") # Bug 1198261 [browser_navigateaway4.js] [browser_offline.js] [browser_relative.js] -[browser_signed_multipackage.js] -skip-if = require_signing [browser_signed_multiple.js] -skip-if = require_signing [browser_signed_naming.js] -skip-if = require_signing [browser_signed_tampered.js] -skip-if = require_signing [browser_signed_trigger.js] -skip-if = require_signing [browser_signed_untrusted.js] -skip-if = require_signing [browser_signed_url.js] -skip-if = require_signing [browser_softwareupdate.js] [browser_switchtab.js] [browser_trigger_redirect.js] [browser_unsigned_trigger.js] -skip-if = require_signing [browser_unsigned_trigger_iframe.js] -skip-if = require_signing +skip-if = buildapp == "mulet" [browser_unsigned_trigger_xorigin.js] +skip-if = buildapp == "mulet" [browser_unsigned_url.js] -skip-if = require_signing [browser_whitelist.js] [browser_whitelist2.js] [browser_whitelist3.js] @@ -117,3 +100,4 @@ skip-if = require_signing [browser_whitelist5.js] [browser_whitelist6.js] [browser_whitelist7.js] +skip-if = (os == 'win' || os == 'mac') && debug # bug 986458 - leaked 1 docshell until shutdown on chunked debug bc diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_amosigned_trigger.js b/toolkit/mozapps/extensions/test/xpinstall/browser_amosigned_trigger.js deleted file mode 100644 index d61ef7362..000000000 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_amosigned_trigger.js +++ /dev/null @@ -1,56 +0,0 @@ -// ---------------------------------------------------------------------------- -// Tests installing an unsigned add-on through an InstallTrigger call in web -// content. -function test() { - Harness.installConfirmCallback = confirm_install; - Harness.installEndedCallback = install_ended; - Harness.installsCompletedCallback = finish_test; - Harness.finalContentEvent = "InstallComplete"; - Harness.setup(); - - var pm = Services.perms; - pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); - - var triggers = encodeURIComponent(JSON.stringify({ - "Unsigned XPI": { - URL: TESTROOT + "amosigned.xpi", - IconURL: TESTROOT + "icon.png", - toString: function() { return this.URL; } - } - })); - gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); -} - -function confirm_install(window) { - var items = window.document.getElementById("itemList").childNodes; - is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); - is(items[0].name, "XPI Test", "Should have seen the name"); - is(items[0].url, TESTROOT + "amosigned.xpi", "Should have listed the correct url for the item"); - is(items[0].icon, TESTROOT + "icon.png", "Should have listed the correct icon for the item"); - is(items[0].signed, "false", "Should have listed the item as unsigned"); - return true; -} - -function install_ended(install, addon) { - install.cancel(); -} - -const finish_test = Task.async(function*(count) { - is(count, 1, "1 Add-on should have been successfully installed"); - - Services.perms.remove(makeURI("http://example.com"), "install"); - - const results = yield ContentTask.spawn(gBrowser.selectedBrowser, null, () => { - return { - return: content.document.getElementById("return").textContent, - status: content.document.getElementById("status").textContent, - } - }) - - is(results.return, "true", "installTrigger should have claimed success"); - is(results.status, "0", "Callback should have seen a success"); - - gBrowser.removeCurrentTab(); - Harness.finish(); -}); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_amosigned_trigger_iframe.js b/toolkit/mozapps/extensions/test/xpinstall/browser_amosigned_trigger_iframe.js deleted file mode 100644 index 66564afaa..000000000 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_amosigned_trigger_iframe.js +++ /dev/null @@ -1,57 +0,0 @@ -// ---------------------------------------------------------------------------- -// Test for bug 589598 - Ensure that installing through InstallTrigger -// works in an iframe in web content. - -function test() { - Harness.installConfirmCallback = confirm_install; - Harness.installEndedCallback = install_ended; - Harness.installsCompletedCallback = finish_test; - Harness.finalContentEvent = "InstallComplete"; - Harness.setup(); - - var pm = Services.perms; - pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); - - var inner_url = encodeURIComponent(TESTROOT + "installtrigger.html?" + encodeURIComponent(JSON.stringify({ - "Unsigned XPI": { - URL: TESTROOT + "amosigned.xpi", - IconURL: TESTROOT + "icon.png", - toString: function() { return this.URL; } - } - }))); - gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.loadURI(TESTROOT + "installtrigger_frame.html?" + inner_url); -} - -function confirm_install(window) { - var items = window.document.getElementById("itemList").childNodes; - is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); - is(items[0].name, "XPI Test", "Should have seen the name"); - is(items[0].url, TESTROOT + "amosigned.xpi", "Should have listed the correct url for the item"); - is(items[0].icon, TESTROOT + "icon.png", "Should have listed the correct icon for the item"); - is(items[0].signed, "false", "Should have listed the item as unsigned"); - return true; -} - -function install_ended(install, addon) { - install.cancel(); -} - -const finish_test = Task.async(function*(count) { - is(count, 1, "1 Add-on should have been successfully installed"); - - Services.perms.remove(makeURI("http://example.com"), "install"); - - const results = yield ContentTask.spawn(gBrowser.selectedBrowser, null, () => { - return { - return: content.frames[0].document.getElementById("return").textContent, - status: content.frames[0].document.getElementById("status").textContent, - } - }) - - is(results.return, "true", "installTrigger in iframe should have claimed success"); - is(results.status, "0", "Callback in iframe should have seen a success"); - - gBrowser.removeCurrentTab(); - Harness.finish(); -}); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_amosigned_url.js b/toolkit/mozapps/extensions/test/xpinstall/browser_amosigned_url.js deleted file mode 100644 index f6c39b7bb..000000000 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_amosigned_url.js +++ /dev/null @@ -1,35 +0,0 @@ -// ---------------------------------------------------------------------------- -// Tests installing an unsigned add-on by navigating directly to the url -function test() { - Harness.installConfirmCallback = confirm_install; - Harness.installEndedCallback = install_ended; - Harness.installsCompletedCallback = finish_test; - Harness.setup(); - - gBrowser.selectedTab = gBrowser.addTab("about:blank"); - BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(() => { - gBrowser.loadURI(TESTROOT + "amosigned.xpi"); - }); -} - -function confirm_install(window) { - let items = window.document.getElementById("itemList").childNodes; - is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); - is(items[0].name, "XPI Test", "Should have had the filename for the item name"); - is(items[0].url, TESTROOT + "amosigned.xpi", "Should have listed the correct url for the item"); - is(items[0].icon, "", "Should have listed no icon for the item"); - is(items[0].signed, "false", "Should have listed the item as unsigned"); - return true; -} - -function install_ended(install, addon) { - install.cancel(); -} - -function finish_test(count) { - is(count, 1, "1 Add-on should have been successfully installed"); - - gBrowser.removeCurrentTab(); - Harness.finish(); -} -// ---------------------------------------------------------------------------- diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_auth.js b/toolkit/mozapps/extensions/test/xpinstall/browser_auth.js index 1bfa7696f..ee2913827 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_auth.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_auth.js @@ -8,15 +8,11 @@ function test() { Harness.installsCompletedCallback = finish_test; Harness.setup(); - var prefs = Cc["@mozilla.org/preferences-service;1"]. - getService(Ci.nsIPrefBranch); - prefs.setIntPref("network.auth.subresource-http-auth-allow", 2); - var pm = Services.perms; pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); var triggers = encodeURIComponent(JSON.stringify({ - "Unsigned XPI": TESTROOT + "authRedirect.sjs?" + TESTROOT + "amosigned.xpi" + "Unsigned XPI": TESTROOT + "authRedirect.sjs?" + TESTROOT + "unsigned.xpi" })); gBrowser.selectedTab = gBrowser.addTab(); gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); @@ -40,7 +36,7 @@ function finish_test(count) { .getService(Components.interfaces.nsIHttpAuthManager); authMgr.clearAll(); - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("example.com", "install"); gBrowser.removeCurrentTab(); Harness.finish(); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_auth2.js b/toolkit/mozapps/extensions/test/xpinstall/browser_auth2.js index 80942a9f4..d50ce941d 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_auth2.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_auth2.js @@ -14,7 +14,7 @@ function test() { pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); var triggers = encodeURIComponent(JSON.stringify({ - "Unsigned XPI": TESTROOT + "authRedirect.sjs?" + TESTROOT + "amosigned.xpi" + "Unsigned XPI": TESTROOT + "authRedirect.sjs?" + TESTROOT + "unsigned.xpi" })); gBrowser.selectedTab = gBrowser.addTab(); gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); @@ -39,7 +39,7 @@ function finish_test(count) { .getService(Components.interfaces.nsIHttpAuthManager); authMgr.clearAll(); - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("example.com", "install"); gBrowser.removeCurrentTab(); Harness.finish(); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_auth3.js b/toolkit/mozapps/extensions/test/xpinstall/browser_auth3.js index 4973a1b35..f06e97fa3 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_auth3.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_auth3.js @@ -3,6 +3,7 @@ // canceled // This verifies bug 312473 +/////////////////// // // Whitelisting this test. // As part of bug 1077403, the leaking uncaught rejection should be fixed. @@ -21,7 +22,7 @@ function test() { pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); var triggers = encodeURIComponent(JSON.stringify({ - "Unsigned XPI": TESTROOT + "authRedirect.sjs?" + TESTROOT + "amosigned.xpi" + "Unsigned XPI": TESTROOT + "authRedirect.sjs?" + TESTROOT + "unsigned.xpi" })); gBrowser.selectedTab = gBrowser.addTab(); gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); @@ -46,7 +47,7 @@ function finish_test(count) { .getService(Components.interfaces.nsIHttpAuthManager); authMgr.clearAll(); - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("example.com", "install"); gBrowser.removeCurrentTab(); Harness.finish(); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_auth4.js b/toolkit/mozapps/extensions/test/xpinstall/browser_auth4.js index a3157961d..abbc161f7 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_auth4.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_auth4.js @@ -1,3 +1,4 @@ +/////////////////// // // Whitelisting this test. // As part of bug 1077403, the leaking uncaught rejection should be fixed. @@ -20,7 +21,7 @@ function test() { pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); var triggers = encodeURIComponent(JSON.stringify({ - "Unsigned XPI": TESTROOT + "authRedirect.sjs?" + TESTROOT + "amosigned.xpi" + "Unsigned XPI": TESTROOT + "authRedirect.sjs?" + TESTROOT + "unsigned.xpi" })); gNewTab = gBrowser.addTab(); gBrowser.getBrowserForTab(gNewTab).loadURI(TESTROOT + "installtrigger.html?" + triggers); @@ -45,7 +46,7 @@ function finish_test(count) { .getService(Components.interfaces.nsIHttpAuthManager); authMgr.clearAll(); - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("example.com", "install"); gBrowser.removeTab(gNewTab); Harness.finish(); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_badargs.js b/toolkit/mozapps/extensions/test/xpinstall/browser_badargs.js index b4b1110b0..fb9c3d10c 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_badargs.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_badargs.js @@ -4,18 +4,15 @@ function test() { waitForExplicitFinish(); - var triggers = encodeURIComponent(JSON.stringify(TESTROOT + "amosigned.xpi")); + var triggers = encodeURIComponent(JSON.stringify(TESTROOT + "unsigned.xpi")); gBrowser.selectedTab = gBrowser.addTab(); - ContentTask.spawn(gBrowser.selectedBrowser, null, function() { - return new Promise(resolve => { - addEventListener("load", () => { - content.addEventListener("InstallTriggered", () => { - resolve(content.document.getElementById("return").textContent); - }); - }, true); - }); - }).then(page_loaded); + function loadListener() { + gBrowser.selectedBrowser.removeEventListener("load", loadListener, true); + gBrowser.contentWindow.addEventListener("InstallTriggered", page_loaded, false); + } + + gBrowser.selectedBrowser.addEventListener("load", loadListener, true); // In non-e10s the exception in the content page would trigger a test failure if (!gMultiProcessBrowser) @@ -24,8 +21,10 @@ function test() { gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); } -function page_loaded(result) { - is(result, "exception", "installTrigger should have failed"); +function page_loaded() { + gBrowser.contentWindow.removeEventListener("InstallTriggered", page_loaded, false); + var doc = gBrowser.contentDocument; + is(doc.getElementById("return").textContent, "exception", "installTrigger should have failed"); // In non-e10s the exception from the page is thrown after the event so we // have to spin the event loop to make sure it arrives so expectUncaughtException diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_badargs2.js b/toolkit/mozapps/extensions/test/xpinstall/browser_badargs2.js index 7137df318..25e1586c8 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_badargs2.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_badargs2.js @@ -11,15 +11,12 @@ function test() { })); gBrowser.selectedTab = gBrowser.addTab(); - ContentTask.spawn(gBrowser.selectedBrowser, null, function() { - return new Promise(resolve => { - addEventListener("load", () => { - content.addEventListener("InstallTriggered", () => { - resolve(content.document.getElementById("return").textContent); - }); - }, true); - }); - }).then(page_loaded); + function loadListener() { + gBrowser.selectedBrowser.removeEventListener("load", loadListener, true); + gBrowser.contentWindow.addEventListener("InstallTriggered", page_loaded, false); + } + + gBrowser.selectedBrowser.addEventListener("load", loadListener, true); // In non-e10s the exception in the content page would trigger a test failure if (!gMultiProcessBrowser) @@ -28,8 +25,10 @@ function test() { gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); } -function page_loaded(result) { - is(result, "exception", "installTrigger should have failed"); +function page_loaded() { + gBrowser.contentWindow.removeEventListener("InstallTriggered", page_loaded, false); + var doc = gBrowser.contentDocument; + is(doc.getElementById("return").textContent, "exception", "installTrigger should have failed"); // In non-e10s the exception from the page is thrown after the event so we // have to spin the event loop to make sure it arrives so expectUncaughtException diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_badhash.js b/toolkit/mozapps/extensions/test/xpinstall/browser_badhash.js index 9a26a77e4..d7bcedd90 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_badhash.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_badhash.js @@ -11,7 +11,7 @@ function test() { var triggers = encodeURIComponent(JSON.stringify({ "Unsigned XPI": { - URL: TESTROOT + "amosigned.xpi", + URL: TESTROOT + "unsigned.xpi", Hash: "sha1:643b08418599ddbd1ea8a511c90696578fb844b9", toString: function() { return this.URL; } } @@ -26,7 +26,7 @@ function download_failed(install) { function finish_test(count) { is(count, 0, "No add-ons should have been installed"); - Services.perms.remove(makeURI("http://example.com/"), "install"); + Services.perms.remove("example.com", "install"); gBrowser.removeCurrentTab(); Harness.finish(); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_badhashtype.js b/toolkit/mozapps/extensions/test/xpinstall/browser_badhashtype.js index a9de9e4f0..105ab681e 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_badhashtype.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_badhashtype.js @@ -11,7 +11,7 @@ function test() { var triggers = encodeURIComponent(JSON.stringify({ "Unsigned XPI": { - URL: TESTROOT + "amosigned.xpi", + URL: TESTROOT + "unsigned.xpi", Hash: "foo:3d0dc22e1f394e159b08aaf5f0f97de4d5c65f4f", toString: function() { return this.URL; } } @@ -26,7 +26,7 @@ function download_failed(install) { function finish_test(count) { is(count, 0, "No add-ons should have been installed"); - Services.perms.remove(makeURI("http://example.com/"), "install"); + Services.perms.remove("example.com", "install"); gBrowser.removeCurrentTab(); Harness.finish(); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_bug540558.js b/toolkit/mozapps/extensions/test/xpinstall/browser_bug540558.js index 4e7e20717..6a425c61a 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_bug540558.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_bug540558.js @@ -18,7 +18,7 @@ function check_xpi_install(install, addon) { function finish_test(count) { is(count, 1, "1 Add-on should have been successfully installed"); - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("example.com", "install"); gBrowser.removeCurrentTab(); Harness.finish(); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_bug611242.js b/toolkit/mozapps/extensions/test/xpinstall/browser_bug611242.js index 4f3cd087f..08af331bd 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_bug611242.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_bug611242.js @@ -1,17 +1,34 @@ // ---------------------------------------------------------------------------- // Test whether setting a new property in InstallTrigger then persists to other // page loads -add_task(function* test() { - yield BrowserTestUtils.withNewTab({ gBrowser, url: TESTROOT + "enabled.html" }, function* (browser) { - yield ContentTask.spawn(browser, null, () => { - content.wrappedJSObject.InstallTrigger.enabled.k = function() { }; - }); +function loadURI(aUri, aCallback) { + gBrowser.selectedBrowser.addEventListener("load", function() { + if (gBrowser.selectedBrowser.currentURI.spec != aUri) + return; + + gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true); + + aCallback(); + }, true); + + gBrowser.loadURI(aUri); +} + +function test() { + waitForExplicitFinish(); + + gBrowser.selectedTab = gBrowser.addTab(); + + loadURI(TESTROOT + "enabled.html", function() { + window.content.wrappedJSObject.InstallTrigger.enabled.k = function() { }; + + loadURI(TESTROOT2 + "enabled.html", function() { + is(window.content.wrappedJSObject.InstallTrigger.enabled.k, undefined, "Property should not be defined"); + + gBrowser.removeTab(gBrowser.selectedTab); - BrowserTestUtils.loadURI(browser, TESTROOT2 + "enabled.html"); - yield BrowserTestUtils.browserLoaded(browser); - yield ContentTask.spawn(browser, null, () => { - is(content.wrappedJSObject.InstallTrigger.enabled.k, undefined, "Property should not be defined"); + finish(); }); }); -}); +} // ---------------------------------------------------------------------------- diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_bug638292.js b/toolkit/mozapps/extensions/test/xpinstall/browser_bug638292.js index 0d96e7cbe..d5d590a3f 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_bug638292.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_bug638292.js @@ -1,40 +1,63 @@ // ---------------------------------------------------------------------------- // Test whether an InstallTrigger.enabled is working -add_task(function * () -{ - let testtab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, TESTROOT + "bug638292.html"); - - function* verify(link, button) - { - info("Clicking " + link); - - let waitForNewTabPromise = BrowserTestUtils.waitForNewTab(gBrowser); - - yield BrowserTestUtils.synthesizeMouseAtCenter("#" + link, { button: button }, - gBrowser.selectedBrowser); - - let newtab = yield waitForNewTabPromise; - - yield BrowserTestUtils.browserLoaded(newtab.linkedBrowser); - - let result = yield ContentTask.spawn(newtab.linkedBrowser, { }, function* () { - return (content.document.getElementById("enabled").textContent == "true"); - }); - - ok(result, "installTrigger for " + link + " should have been enabled"); - - // Focus the old tab (link3 is opened in the background) - if (link != "link3") { - yield BrowserTestUtils.switchTab(gBrowser, testtab); +function test() { + waitForExplicitFinish(); + + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.selectedBrowser.addEventListener("load", function() { + gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true); + waitForFocus(page_loaded, gBrowser.contentWindow); + }, true); + gBrowser.loadURI(TESTROOT + "bug638292.html"); +} + +function check_load(aCallback) { + gBrowser.addEventListener("load", function(aEvent) { + if (!gBrowser.browsers[2] || + aEvent.target != gBrowser.browsers[2].contentDocument) { + // SeaMonkey tabbrowser needs to deal with additional loads. + if (navigator.userAgent.match(/ SeaMonkey\//)) + info("Ignoring unrelated load on SeaMonkey. (Expected 2-3 times.)"); + else + ok(false, "Ignoring unrelated load on Firefox. (Should never happen!)"); + return; } - gBrowser.removeTab(newtab); - } - yield* verify("link1", 0); - yield* verify("link2", 0); - yield* verify("link3", 1); - - gBrowser.removeCurrentTab(); -}); + gBrowser.removeEventListener("load", arguments.callee, true); + // Let the load handler complete + executeSoon(function() { + var doc = gBrowser.browsers[2].contentDocument; + is(doc.getElementById("enabled").textContent, "true", "installTrigger should have been enabled"); + // Focus the old tab + gBrowser.selectedTab = gBrowser.tabs[1]; + waitForFocus(function() { + // Close the new tab + gBrowser.removeTab(gBrowser.tabs[2]); + aCallback(); + }, gBrowser.contentWindow); + }); + }, true); +} + +function page_loaded() { + var doc = gBrowser.contentDocument; + info("Clicking link 1"); + EventUtils.synthesizeMouseAtCenter(doc.getElementById("link1"), { }, gBrowser.contentWindow); + + check_load(function() { + info("Clicking link 2"); + EventUtils.synthesizeMouseAtCenter(doc.getElementById("link2"), { }, gBrowser.contentWindow); + + check_load(function() { + info("Clicking link 3"); + EventUtils.synthesizeMouseAtCenter(doc.getElementById("link3"), { button: 1 }, gBrowser.contentWindow); + + check_load(function() { + gBrowser.removeCurrentTab(); + finish(); + }); + }); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_bug645699.js b/toolkit/mozapps/extensions/test/xpinstall/browser_bug645699.js index f32d2c9d2..a5c188c03 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_bug645699.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_bug645699.js @@ -28,7 +28,7 @@ function confirm_install(window) { function finish_test(count) { is(count, 0, "0 Add-ons should have been successfully installed"); - Services.perms.remove(makeURI("http://addons.mozilla.org"), "install"); + Services.perms.remove("addons.mozilla.org", "install"); gBrowser.removeCurrentTab(); Harness.finish(); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_bug672485.js b/toolkit/mozapps/extensions/test/xpinstall/browser_bug672485.js index 81d89c025..36e9c5b3c 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_bug672485.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_bug672485.js @@ -2,7 +2,7 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -var gWindowWatcher = null; +gWindowWatcher = null; function test() { Harness.installConfirmCallback = confirm_install; @@ -19,7 +19,7 @@ function test() { pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); var triggers = encodeURIComponent(JSON.stringify({ - "Unsigned XPI": TESTROOT + "amosigned.xpi" + "Unsigned XPI": TESTROOT + "unsigned.xpi" })); gBrowser.selectedTab = gBrowser.addTab(); gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); @@ -46,7 +46,7 @@ function finish_test(count) { Services.ww = gWindowWatcher; - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("example.com", "install"); Harness.finish(); } diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_cancel.js b/toolkit/mozapps/extensions/test/xpinstall/browser_cancel.js index e30d7a0e5..8fb6efcb8 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_cancel.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_cancel.js @@ -14,8 +14,8 @@ function test() { pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); var triggers = encodeURIComponent(JSON.stringify({ - "Unsigned XPI": TESTROOT + "amosigned.xpi", - "Unsigned XPI 2": TESTROOT + "amosigned2.xpi", + "Signed XPI": TESTROOT + "signed.xpi", + "Signed XPI 2": TESTROOT + "signed2.xpi", })); gBrowser.selectedTab = gBrowser.addTab(); gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); @@ -33,15 +33,17 @@ function get_item(items, url) { function confirm_install(window) { let items = window.document.getElementById("itemList").childNodes; is(items.length, 2, "Should be 2 items listed in the confirmation dialog"); - let item = get_item(items, TESTROOT + "amosigned.xpi"); + let item = get_item(items, TESTROOT + "signed.xpi"); if (item) { - is(item.name, "XPI Test", "Should have seen the name from the trigger list"); - is(item.signed, "false", "Should have listed the item as signed"); + is(item.name, "Signed XPI Test", "Should have seen the name from the trigger list"); + is(item.cert, "(Object Signer)", "Should have seen the signer"); + is(item.signed, "true", "Should have listed the item as signed"); } - item = get_item(items, TESTROOT + "amosigned2.xpi"); + item = get_item(items, TESTROOT + "signed2.xpi"); if (item) { is(item.name, "Signed XPI Test", "Should have seen the name from the trigger list"); - is(item.signed, "false", "Should have listed the item as signed"); + is(item.cert, "(Object Signer)", "Should have seen the signer"); + is(item.signed, "true", "Should have listed the item as signed"); } return false; } @@ -53,7 +55,7 @@ function install_ended(install, addon) { function finish_test(count) { is(count, 0, "No add-ons should have been successfully installed"); - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("example.com", "install"); gBrowser.removeCurrentTab(); Harness.finish(); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_concurrent_installs.js b/toolkit/mozapps/extensions/test/xpinstall/browser_concurrent_installs.js index bf919d89c..3613e95b0 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_concurrent_installs.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_concurrent_installs.js @@ -1,12 +1,13 @@ // Test that having two frames that request installs at the same time doesn't // cause callback ID conflicts (discussed in bug 926712) -var gConcurrentTabs = []; -var gQueuedForInstall = []; -var gResults = []; +let {Promise} = Cu.import("resource://gre/modules/Promise.jsm"); + +let gConcurrentTabs = []; +let gQueuedForInstall = []; +let gResults = []; function frame_script() { - /* globals addMessageListener, sendAsyncMessage*/ addMessageListener("Test:StartInstall", () => { content.document.getElementById("installnow").click() }); @@ -20,7 +21,7 @@ function frame_script() { }, true); } -var gAddonAndWindowListener = { +let gAddonAndWindowListener = { onOpenWindow: function(win) { var window = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow); info("Window opened"); @@ -80,8 +81,8 @@ function test() { Services.prefs.clearUserPref(PREF_LOGGING_ENABLED); Services.prefs.clearUserPref(PREF_INSTALL_REQUIRESECUREORIGIN); - Services.perms.remove(makeURI("http://example.com"), "install"); - Services.perms.remove(makeURI("http://example.org"), "install"); + Services.perms.remove("example.com", "install"); + Services.perms.remove("example.org", "install"); while (gConcurrentTabs.length) { gBrowser.removeTab(gConcurrentTabs.shift()); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_cookies.js b/toolkit/mozapps/extensions/test/xpinstall/browser_cookies.js index 541ac8333..c0e7c11b5 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_cookies.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_cookies.js @@ -11,7 +11,7 @@ function test() { pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); var triggers = encodeURIComponent(JSON.stringify({ - "Cookie check": TESTROOT + "cookieRedirect.sjs?" + TESTROOT + "amosigned.xpi" + "Cookie check": TESTROOT + "cookieRedirect.sjs?" + TESTROOT + "unsigned.xpi" })); gBrowser.selectedTab = gBrowser.addTab(); gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); @@ -23,7 +23,7 @@ function download_failed(install) { function finish_test(count) { is(count, 0, "No add-ons should have been installed"); - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("example.com", "install"); gBrowser.removeCurrentTab(); Harness.finish(); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_cookies2.js b/toolkit/mozapps/extensions/test/xpinstall/browser_cookies2.js index 1ef2b482f..02ea8ff21 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_cookies2.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_cookies2.js @@ -10,13 +10,13 @@ function test() { var cm = Components.classes["@mozilla.org/cookiemanager;1"] .getService(Components.interfaces.nsICookieManager2); cm.add("example.com", "/browser/" + RELATIVE_DIR, "xpinstall", "true", false, - false, true, (Date.now() / 1000) + 60, {}); + false, true, (Date.now() / 1000) + 60); var pm = Services.perms; pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); var triggers = encodeURIComponent(JSON.stringify({ - "Cookie check": TESTROOT + "cookieRedirect.sjs?" + TESTROOT + "amosigned.xpi" + "Cookie check": TESTROOT + "cookieRedirect.sjs?" + TESTROOT + "unsigned.xpi" })); gBrowser.selectedTab = gBrowser.addTab(); gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); @@ -31,9 +31,9 @@ function finish_test(count) { var cm = Components.classes["@mozilla.org/cookiemanager;1"] .getService(Components.interfaces.nsICookieManager2); - cm.remove("example.com", "xpinstall", "/browser/" + RELATIVE_DIR, false, {}); + cm.remove("example.com", "xpinstall", "/browser/" + RELATIVE_DIR, false); - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("example.com", "install"); gBrowser.removeCurrentTab(); Harness.finish(); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_cookies3.js b/toolkit/mozapps/extensions/test/xpinstall/browser_cookies3.js index 833562d15..c23778dd0 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_cookies3.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_cookies3.js @@ -10,7 +10,7 @@ function test() { var cm = Components.classes["@mozilla.org/cookiemanager;1"] .getService(Components.interfaces.nsICookieManager2); cm.add("example.com", "/browser/" + RELATIVE_DIR, "xpinstall", "true", false, - false, true, (Date.now() / 1000) + 60, {}); + false, true, (Date.now() / 1000) + 60); var pm = Services.perms; pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); @@ -18,7 +18,7 @@ function test() { Services.prefs.setIntPref("network.cookie.cookieBehavior", 1); var triggers = encodeURIComponent(JSON.stringify({ - "Cookie check": TESTROOT + "cookieRedirect.sjs?" + TESTROOT + "amosigned.xpi" + "Cookie check": TESTROOT + "cookieRedirect.sjs?" + TESTROOT + "unsigned.xpi" })); gBrowser.selectedTab = gBrowser.addTab(); gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); @@ -33,11 +33,11 @@ function finish_test(count) { var cm = Components.classes["@mozilla.org/cookiemanager;1"] .getService(Components.interfaces.nsICookieManager2); - cm.remove("example.com", "xpinstall", "/browser/" + RELATIVE_DIR, false, {}); + cm.remove("example.com", "xpinstall", "/browser/" + RELATIVE_DIR, false); Services.prefs.clearUserPref("network.cookie.cookieBehavior"); - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("example.com", "install"); gBrowser.removeCurrentTab(); Harness.finish(); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_cookies4.js b/toolkit/mozapps/extensions/test/xpinstall/browser_cookies4.js index 792146c64..33347cdb7 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_cookies4.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_cookies4.js @@ -11,7 +11,7 @@ function test() { var cm = Components.classes["@mozilla.org/cookiemanager;1"] .getService(Components.interfaces.nsICookieManager2); cm.add("example.org", "/browser/" + RELATIVE_DIR, "xpinstall", "true", false, - false, true, (Date.now() / 1000) + 60, {}); + false, true, (Date.now() / 1000) + 60); var pm = Services.perms; pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); @@ -19,7 +19,7 @@ function test() { Services.prefs.setIntPref("network.cookie.cookieBehavior", 1); var triggers = encodeURIComponent(JSON.stringify({ - "Cookie check": TESTROOT2 + "cookieRedirect.sjs?" + TESTROOT + "amosigned.xpi" + "Cookie check": TESTROOT2 + "cookieRedirect.sjs?" + TESTROOT + "unsigned.xpi" })); gBrowser.selectedTab = gBrowser.addTab(); gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); @@ -33,10 +33,10 @@ function finish_test(count) { is(count, 0, "No add-ons should have been installed"); var cm = Components.classes["@mozilla.org/cookiemanager;1"] .getService(Components.interfaces.nsICookieManager2); - cm.remove("example.org", "xpinstall", "/browser/" + RELATIVE_DIR, false, {}); + cm.remove("example.org", "xpinstall", "/browser/" + RELATIVE_DIR, false); Services.prefs.clearUserPref("network.cookie.cookieBehavior"); - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("example.com", "install"); gBrowser.removeCurrentTab(); Harness.finish(); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_corrupt.js b/toolkit/mozapps/extensions/test/xpinstall/browser_corrupt.js index bd4d27fb0..8f0c3c66a 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_corrupt.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_corrupt.js @@ -20,19 +20,13 @@ function download_failed(install) { is(install.error, AddonManager.ERROR_CORRUPT_FILE, "Install should fail"); } -const finish_test = Task.async(function*(count) { +function finish_test(count) { is(count, 0, "No add-ons should have been installed"); - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("example.com", "install"); - const results = yield ContentTask.spawn(gBrowser.selectedBrowser, null, () => { - return { - return: content.document.getElementById("return").textContent, - status: content.document.getElementById("status").textContent, - } - }) - - is(results.status, "-207", "Callback should have seen the failure"); + var doc = gBrowser.contentDocument; + is(doc.getElementById("status").textContent, "-207", "Callback should have seen the failure"); gBrowser.removeCurrentTab(); Harness.finish(); -}); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_datauri.js b/toolkit/mozapps/extensions/test/xpinstall/browser_datauri.js index a8bdbde39..917f2465d 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_datauri.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_datauri.js @@ -18,7 +18,7 @@ function test() { Harness.setup(); setup_redirect({ - "Location": "data:text/html,<script>window.location.href='" + TESTROOT + "amosigned.xpi'</script>" + "Location": "data:text/html,<script>window.location.href='" + TESTROOT + "unsigned.xpi'</script>" }); gBrowser.selectedTab = gBrowser.addTab(); @@ -30,7 +30,6 @@ function install_blocked(installInfo) { function finish_test(count) { is(count, 0, "No add-ons should have been installed"); - Services.perms.remove(makeURI("http://example.com"), "install"); gBrowser.removeCurrentTab(); Harness.finish(); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_empty.js b/toolkit/mozapps/extensions/test/xpinstall/browser_empty.js index 64ca5e6b9..cbf9e48a7 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_empty.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_empty.js @@ -21,7 +21,7 @@ function download_failed(install) { function finish_test(count) { is(count, 0, "No add-ons should have been installed"); - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("example.com", "install"); gBrowser.removeCurrentTab(); Harness.finish(); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_enabled.js b/toolkit/mozapps/extensions/test/xpinstall/browser_enabled.js index adbec9499..56118c4e1 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_enabled.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_enabled.js @@ -5,25 +5,20 @@ function test() { gBrowser.selectedTab = gBrowser.addTab(); - ContentTask.spawn(gBrowser.selectedBrowser, TESTROOT + "enabled.html", function (url) { - return new Promise(resolve => { - function page_loaded() { - content.removeEventListener("PageLoaded", page_loaded, false); - resolve(content.document.getElementById("enabled").textContent); - } + function loadListener() { + gBrowser.selectedBrowser.removeEventListener("load", loadListener, true); + gBrowser.contentWindow.addEventListener("PageLoaded", page_loaded, false); + } - function load_listener() { - removeEventListener("load", load_listener, true); - content.addEventListener("PageLoaded", page_loaded, false); - } + gBrowser.selectedBrowser.addEventListener("load", loadListener, true); + gBrowser.loadURI(TESTROOT + "enabled.html"); +} - addEventListener("load", load_listener, true); +function page_loaded() { + gBrowser.contentWindow.removeEventListener("PageLoaded", page_loaded, false); - content.location.href = url; - }); - }).then(text => { - is(text, "true", "installTrigger should have been enabled"); - gBrowser.removeCurrentTab(); - finish(); - }); + var doc = gBrowser.contentDocument; + is(doc.getElementById("enabled").textContent, "true", "installTrigger should have been enabled"); + gBrowser.removeCurrentTab(); + finish(); } diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_enabled2.js b/toolkit/mozapps/extensions/test/xpinstall/browser_enabled2.js index cc1b8a8b2..290987bda 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_enabled2.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_enabled2.js @@ -7,26 +7,21 @@ function test() { gBrowser.selectedTab = gBrowser.addTab(); - ContentTask.spawn(gBrowser.selectedBrowser, TESTROOT + "enabled.html", function (url) { - return new Promise(resolve => { - function page_loaded() { - content.removeEventListener("PageLoaded", page_loaded, false); - resolve(content.document.getElementById("enabled").textContent); - } + function loadListener() { + gBrowser.selectedBrowser.removeEventListener("load", loadListener, true); + gBrowser.contentWindow.addEventListener("PageLoaded", page_loaded, false); + } - function load_listener() { - removeEventListener("load", load_listener, true); - content.addEventListener("PageLoaded", page_loaded, false); - } + gBrowser.selectedBrowser.addEventListener("load", loadListener, true); + gBrowser.loadURI(TESTROOT + "enabled.html"); +} - addEventListener("load", load_listener, true); +function page_loaded() { + gBrowser.contentWindow.removeEventListener("PageLoaded", page_loaded, false); + Services.prefs.clearUserPref("xpinstall.enabled"); - content.location.href = url; - }); - }).then(text => { - is(text, "false", "installTrigger should have not been enabled"); - Services.prefs.clearUserPref("xpinstall.enabled"); - gBrowser.removeCurrentTab(); - finish(); - }); + var doc = gBrowser.contentDocument; + is(doc.getElementById("enabled").textContent, "false", "installTrigger should have not been enabled"); + gBrowser.removeCurrentTab(); + finish(); } diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_enabled3.js b/toolkit/mozapps/extensions/test/xpinstall/browser_enabled3.js index 15bad4ba9..ea3eba530 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_enabled3.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_enabled3.js @@ -9,32 +9,17 @@ function test() { Services.prefs.setBoolPref("xpinstall.enabled", false); var triggers = encodeURIComponent(JSON.stringify({ - "Unsigned XPI": TESTROOT + "amosigned.xpi" + "Unsigned XPI": TESTROOT + "unsigned.xpi" })); gBrowser.selectedTab = gBrowser.addTab(); - ContentTask.spawn(gBrowser.selectedBrowser, TESTROOT + "installtrigger.html?" + triggers, url => { - return new Promise(resolve => { - function page_loaded() { - content.removeEventListener("PageLoaded", page_loaded, false); - resolve(content.document.getElementById("return").textContent); - } - - function load_listener() { - removeEventListener("load", load_listener, true); - content.addEventListener("InstallTriggered", page_loaded, false); - } - - addEventListener("load", load_listener, true); - - content.location.href = url; - }); - }).then(text => { - is(text, "false", "installTrigger should have not been enabled"); - Services.prefs.clearUserPref("xpinstall.enabled"); - gBrowser.removeCurrentTab(); - Harness.finish(); - }); + function loadListener() { + gBrowser.selectedBrowser.removeEventListener("load", loadListener, true); + gBrowser.contentWindow.addEventListener("InstallTriggered", page_loaded, false); + } + + gBrowser.selectedBrowser.addEventListener("load", loadListener, true); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); } function install_disabled(installInfo) { @@ -50,3 +35,14 @@ function confirm_install(window) { ok(false, "Should never see an install confirmation dialog"); return false; } + +function page_loaded() { + gBrowser.contentWindow.removeEventListener("InstallTriggered", page_loaded, false); + Services.prefs.clearUserPref("xpinstall.enabled"); + + var doc = gBrowser.contentDocument; + is(doc.getElementById("return").textContent, "false", "installTrigger should have not been enabled"); + gBrowser.removeCurrentTab(); + Harness.finish(); +} +// ---------------------------------------------------------------------------- diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_hash.js b/toolkit/mozapps/extensions/test/xpinstall/browser_hash.js index 4c45bd184..0af71fcb0 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_hash.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_hash.js @@ -11,8 +11,8 @@ function test() { var triggers = encodeURIComponent(JSON.stringify({ "Unsigned XPI": { - URL: TESTROOT + "amosigned.xpi", - Hash: "sha1:36ffb0acfd9c6e9682473aaebaab394d38b473c9", + URL: TESTROOT + "unsigned.xpi", + Hash: "sha1:3d0dc22e1f394e159b08aaf5f0f97de4d5c65f4f", toString: function() { return this.URL; } } })); @@ -27,7 +27,7 @@ function install_ended(install, addon) { function finish_test(count) { is(count, 1, "1 Add-on should have been successfully installed"); - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("example.com", "install"); gBrowser.removeCurrentTab(); Harness.finish(); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_hash2.js b/toolkit/mozapps/extensions/test/xpinstall/browser_hash2.js index 4c8e262c7..8d83e3cd3 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_hash2.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_hash2.js @@ -11,8 +11,8 @@ function test() { var triggers = encodeURIComponent(JSON.stringify({ "Unsigned XPI": { - URL: TESTROOT + "amosigned.xpi", - Hash: "sha1:36FFB0ACFD9C6E9682473AAEBAAB394D38B473C9", + URL: TESTROOT + "unsigned.xpi", + Hash: "sha1:3D0DC22E1F394E159B08AAF5F0F97DE4D5C65F4F", toString: function() { return this.URL; } } })); @@ -27,7 +27,7 @@ function install_ended(install, addon) { function finish_test(count) { is(count, 1, "1 Add-on should have been successfully installed"); - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("example.com", "install"); gBrowser.removeCurrentTab(); Harness.finish(); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_httphash.js b/toolkit/mozapps/extensions/test/xpinstall/browser_httphash.js index 6a1222797..b072db1f3 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_httphash.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_httphash.js @@ -12,7 +12,7 @@ function test() { Services.prefs.setBoolPref(PREF_INSTALL_REQUIREBUILTINCERTS, false); var url = "https://example.com/browser/" + RELATIVE_DIR + "hashRedirect.sjs"; - url += "?sha1:36ffb0acfd9c6e9682473aaebaab394d38b473c9|" + TESTROOT + "amosigned.xpi"; + url += "?sha1:3d0dc22e1f394e159b08aaf5f0f97de4d5c65f4f|" + TESTROOT + "unsigned.xpi"; var triggers = encodeURIComponent(JSON.stringify({ "Unsigned XPI": { @@ -31,7 +31,7 @@ function install_ended(install, addon) { function finish_test(count) { is(count, 1, "1 Add-on should have been successfully installed"); - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("example.com", "install"); Services.prefs.clearUserPref(PREF_INSTALL_REQUIREBUILTINCERTS); gBrowser.removeCurrentTab(); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_httphash2.js b/toolkit/mozapps/extensions/test/xpinstall/browser_httphash2.js index 2d930d221..93326af9f 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_httphash2.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_httphash2.js @@ -12,7 +12,7 @@ function test() { Services.prefs.setBoolPref(PREF_INSTALL_REQUIREBUILTINCERTS, false); var url = "https://example.com/browser/" + RELATIVE_DIR + "hashRedirect.sjs"; - url += "?sha1:foobar|" + TESTROOT + "amosigned.xpi"; + url += "?sha1:foobar|" + TESTROOT + "unsigned.xpi"; var triggers = encodeURIComponent(JSON.stringify({ "Unsigned XPI": { @@ -31,7 +31,7 @@ function download_failed(install) { function finish_test(count) { is(count, 0, "0 Add-ons should have been successfully installed"); - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("example.com", "install"); Services.prefs.clearUserPref(PREF_INSTALL_REQUIREBUILTINCERTS); gBrowser.removeCurrentTab(); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_httphash3.js b/toolkit/mozapps/extensions/test/xpinstall/browser_httphash3.js index 5f3ef23ca..76a6283fb 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_httphash3.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_httphash3.js @@ -11,12 +11,12 @@ function test() { Services.prefs.setBoolPref(PREF_INSTALL_REQUIREBUILTINCERTS, false); var url = "https://example.com/browser/" + RELATIVE_DIR + "hashRedirect.sjs"; - url += "?sha1:foobar|" + TESTROOT + "amosigned.xpi"; + url += "?sha1:foobar|" + TESTROOT + "unsigned.xpi"; var triggers = encodeURIComponent(JSON.stringify({ "Unsigned XPI": { URL: url, - Hash: "sha1:36ffb0acfd9c6e9682473aaebaab394d38b473c9", + Hash: "sha1:3d0dc22e1f394e159b08aaf5f0f97de4d5c65f4f", toString: function() { return this.URL; } } })); @@ -31,7 +31,7 @@ function install_ended(install, addon) { function finish_test(count) { is(count, 1, "1 Add-on should have been successfully installed"); - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("example.com", "install"); Services.prefs.clearUserPref(PREF_INSTALL_REQUIREBUILTINCERTS); gBrowser.removeCurrentTab(); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_httphash4.js b/toolkit/mozapps/extensions/test/xpinstall/browser_httphash4.js index 3983662af..97dc64d1f 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_httphash4.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_httphash4.js @@ -10,7 +10,7 @@ function test() { pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); var url = "http://example.com/browser/" + RELATIVE_DIR + "hashRedirect.sjs"; - url += "?sha1:foobar|" + TESTROOT + "amosigned.xpi"; + url += "?sha1:foobar|" + TESTROOT + "unsigned.xpi"; var triggers = encodeURIComponent(JSON.stringify({ "Unsigned XPI": { @@ -29,7 +29,7 @@ function install_ended(install, addon) { function finish_test(count) { is(count, 1, "1 Add-on should have been successfully installed"); - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("example.com", "install"); gBrowser.removeCurrentTab(); Harness.finish(); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_httphash5.js b/toolkit/mozapps/extensions/test/xpinstall/browser_httphash5.js index 407158e4f..1237989f6 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_httphash5.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_httphash5.js @@ -11,9 +11,9 @@ function test() { Services.prefs.setBoolPref(PREF_INSTALL_REQUIREBUILTINCERTS, false); var url = "https://example.com/browser/" + RELATIVE_DIR + "hashRedirect.sjs"; - url += "?sha1:36ffb0acfd9c6e9682473aaebaab394d38b473c9|"; + url += "?sha1:3d0dc22e1f394e159b08aaf5f0f97de4d5c65f4f|"; url += "https://example.com/browser/" + RELATIVE_DIR + "hashRedirect.sjs"; - url += "?sha1:foobar|" + TESTROOT + "amosigned.xpi"; + url += "?sha1:foobar|" + TESTROOT + "unsigned.xpi"; var triggers = encodeURIComponent(JSON.stringify({ "Unsigned XPI": { @@ -32,7 +32,7 @@ function install_ended(install, addon) { function finish_test(count) { is(count, 1, "1 Add-on should have been successfully installed"); - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("example.com", "install"); Services.prefs.clearUserPref(PREF_INSTALL_REQUIREBUILTINCERTS); gBrowser.removeCurrentTab(); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_httphash6.js b/toolkit/mozapps/extensions/test/xpinstall/browser_httphash6.js index 5e1da8175..9ab490235 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_httphash6.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_httphash6.js @@ -26,7 +26,7 @@ function test() { // Set up the redirect to give a bad hash setup_redirect({ "X-Target-Digest": "sha1:foo", - "Location": "http://example.com/browser/" + RELATIVE_DIR + "amosigned.xpi" + "Location": "http://example.com/browser/" + RELATIVE_DIR + "unsigned.xpi" }); var url = "https://example.com/browser/" + RELATIVE_DIR + "redirect.sjs?mode=redirect"; @@ -55,8 +55,8 @@ function finish_failed_download() { // Give it the right hash this time setup_redirect({ - "X-Target-Digest": "sha1:36ffb0acfd9c6e9682473aaebaab394d38b473c9", - "Location": "http://example.com/browser/" + RELATIVE_DIR + "amosigned.xpi" + "X-Target-Digest": "sha1:3d0dc22e1f394e159b08aaf5f0f97de4d5c65f4f", + "Location": "http://example.com/browser/" + RELATIVE_DIR + "unsigned.xpi" }); // The harness expects onNewInstall events for all installs that are about to start @@ -75,7 +75,7 @@ function install_ended(install, addon) { function finish_test(count) { is(count, 1, "1 Add-on should have been successfully installed"); - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("example.com", "install"); Services.prefs.clearUserPref(PREF_INSTALL_REQUIREBUILTINCERTS); gBrowser.removeCurrentTab(); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_installchrome.js b/toolkit/mozapps/extensions/test/xpinstall/browser_installchrome.js index 2380a4df2..c3be10ec9 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_installchrome.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_installchrome.js @@ -9,7 +9,7 @@ function test() { pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.loadURI(TESTROOT + "installchrome.html? " + encodeURIComponent(TESTROOT + "amosigned.xpi")); + gBrowser.loadURI(TESTROOT + "installchrome.html? " + encodeURIComponent(TESTROOT + "unsigned.xpi")); } function install_ended(install, addon) { @@ -18,7 +18,7 @@ function install_ended(install, addon) { function finish_test(count) { is(count, 1, "1 Add-on should have been successfully installed"); - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("example.com", "install"); gBrowser.removeCurrentTab(); Harness.finish(); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_localfile.js b/toolkit/mozapps/extensions/test/xpinstall/browser_localfile.js index 997f386a6..0e70e8177 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_localfile.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_localfile.js @@ -9,11 +9,10 @@ function test() { .getService(Components.interfaces.nsIChromeRegistry); var chromeroot = extractChromeRoot(gTestPath); - var xpipath = chromeroot + "unsigned.xpi"; try { - xpipath = cr.convertChromeURL(makeURI(chromeroot + "amosigned.xpi")).spec; + var xpipath = cr.convertChromeURL(makeURI(chromeroot + "unsigned.xpi")).spec; } catch (ex) { - // scenario where we are running from a .jar and already extracted + var xpipath = chromeroot + "unsigned.xpi"; //scenario where we are running from a .jar and already extracted } gBrowser.selectedTab = gBrowser.addTab("about:blank"); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_localfile2.js b/toolkit/mozapps/extensions/test/xpinstall/browser_localfile2.js index b0e3ffc42..253ed15b9 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_localfile2.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_localfile2.js @@ -1,38 +1,49 @@ // ---------------------------------------------------------------------------- // Test whether an install fails if the url is a local file when requested from // web content -add_task(function* test() { +function test() { + waitForExplicitFinish(); + var cr = Components.classes["@mozilla.org/chrome/chrome-registry;1"] .getService(Components.interfaces.nsIChromeRegistry); - - var chromeroot = getChromeRoot(gTestPath); - var xpipath = chromeroot + "amosigned.xpi"; + + var chromeroot = getChromeRoot(gTestPath); try { - xpipath = cr.convertChromeURL(makeURI(xpipath)).spec; + var xpipath = cr.convertChromeURL(makeURI(chromeroot + "unsigned.xpi")).spec; } catch (ex) { - // scenario where we are running from a .jar and already extracted + var xpipath = chromeroot + "unsigned.xpi"; //scenario where we are running from a .jar and already extracted } - + var triggers = encodeURIComponent(JSON.stringify({ "Unsigned XPI": xpipath })); + gBrowser.selectedTab = gBrowser.addTab(); + + function loadListener() { + gBrowser.selectedBrowser.removeEventListener("load", loadListener, true); + gBrowser.contentWindow.addEventListener("InstallTriggered", page_loaded, false); + } + + gBrowser.selectedBrowser.addEventListener("load", loadListener, true); // In non-e10s the exception in the content page would trigger a test failure if (!gMultiProcessBrowser) expectUncaughtException(); - let URI = TESTROOT + "installtrigger.html?" + triggers; - yield BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" }, function* (browser) { - yield ContentTask.spawn(browser, URI, function* (URI) { - content.location.href = URI; + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} - let loaded = ContentTaskUtils.waitForEvent(this, "load", true); - let installTriggered = ContentTaskUtils.waitForEvent(this, "InstallTriggered", true, null, true); - yield Promise.all([ loaded, installTriggered ]); +function page_loaded() { + gBrowser.contentWindow.removeEventListener("InstallTriggered", page_loaded, false); + var doc = gBrowser.contentDocument; + is(doc.getElementById("return").textContent, "exception", "installTrigger should have failed"); - let doc = content.document; - is(doc.getElementById("return").textContent, "exception", "installTrigger should have failed"); - }); + // In non-e10s the exception from the page is thrown after the event so we + // have to spin the event loop to make sure it arrives so expectUncaughtException + // sees it. + executeSoon(() => { + gBrowser.removeCurrentTab(); + finish(); }); -}); +} // ---------------------------------------------------------------------------- diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_localfile3.js b/toolkit/mozapps/extensions/test/xpinstall/browser_localfile3.js index 891b85ebc..f24f41cd6 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_localfile3.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_localfile3.js @@ -13,11 +13,10 @@ function test() { .getService(Components.interfaces.nsIChromeRegistry); var chromeroot = extractChromeRoot(gTestPath); - var xpipath = chromeroot + "amosigned.xpi"; try { - xpipath = cr.convertChromeURL(makeURI(xpipath)).spec; + var xpipath = cr.convertChromeURL(makeURI(chromeroot + "unsigned.xpi")).spec; } catch (ex) { - // scenario where we are running from a .jar and already extracted + var xpipath = chromeroot + "unsigned.xpi"; //scenario where we are running from a .jar and already extracted } gBrowser.selectedTab = gBrowser.addTab("about:blank"); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_localfile4.js b/toolkit/mozapps/extensions/test/xpinstall/browser_localfile4.js index 5203c3153..2e8263f19 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_localfile4.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_localfile4.js @@ -13,14 +13,13 @@ function test() { .getService(Components.interfaces.nsIChromeRegistry); var chromeroot = extractChromeRoot(gTestPath); - var xpipath = chromeroot; try { - xpipath = cr.convertChromeURL(makeURI(chromeroot)).spec; + var xpipath = cr.convertChromeURL(makeURI(chromeroot)).spec; } catch (ex) { - // scenario where we are running from a .jar and already extracted + var xpipath = chromeroot; //scenario where we are running from a .jar and already extracted } var triggers = encodeURIComponent(JSON.stringify({ - "Unsigned XPI": TESTROOT + "amosigned.xpi" + "Unsigned XPI": TESTROOT + "unsigned.xpi" })); gBrowser.selectedTab = gBrowser.addTab(); gBrowser.loadURI(xpipath + "installtrigger.html?" + triggers); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_multipackage.js b/toolkit/mozapps/extensions/test/xpinstall/browser_multipackage.js index d022d713a..c5e00008c 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_multipackage.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_multipackage.js @@ -33,7 +33,8 @@ function confirm_install(window) { item = get_item(items, "Signed XPI Test"); if (item) { - is(item.signed, "false", "Should have listed the item as signed"); + is(item.cert, "(Object Signer)", "Should have seen the signer"); + is(item.signed, "true", "Should have listed the item as signed"); is(item.icon, "", "Should have listed no icon for the item"); } diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_navigateaway.js b/toolkit/mozapps/extensions/test/xpinstall/browser_navigateaway.js index f092edb8c..a2ba85d53 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_navigateaway.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_navigateaway.js @@ -12,7 +12,7 @@ function test() { pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); var triggers = encodeURIComponent(JSON.stringify({ - "Unsigned XPI": TESTROOT + "amosigned.xpi" + "Unsigned XPI": TESTROOT + "unsigned.xpi" })); gBrowser.selectedTab = gBrowser.addTab(); gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); @@ -29,7 +29,7 @@ function install_ended(install, addon) { function finish_test(count) { is(count, 1, "1 Add-on should have been successfully installed"); - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("example.com", "install"); gBrowser.removeCurrentTab(); Harness.finish(); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_navigateaway2.js b/toolkit/mozapps/extensions/test/xpinstall/browser_navigateaway2.js index a41662e1e..46d4ffe1e 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_navigateaway2.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_navigateaway2.js @@ -11,7 +11,7 @@ function test() { pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); var triggers = encodeURIComponent(JSON.stringify({ - "Unsigned XPI": TESTROOT + "amosigned.xpi" + "Unsigned XPI": TESTROOT + "unsigned.xpi" })); gBrowser.selectedTab = gBrowser.addTab(); gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); @@ -28,7 +28,7 @@ function install_ended(install, addon) { function finish_test(count) { is(count, 0, "No add-ons should have been successfully installed"); - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("example.com", "install"); Harness.finish(); } diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_navigateaway3.js b/toolkit/mozapps/extensions/test/xpinstall/browser_navigateaway3.js index 3948d5649..7f55a65fe 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_navigateaway3.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_navigateaway3.js @@ -2,9 +2,46 @@ // Tests that navigating to a new origin cancels ongoing installs. // Block the modal install UI from showing. -Services.prefs.setBoolPref(PREF_CUSTOM_CONFIRMATION_UI, true); +let InstallPrompt = { + confirm: function(aBrowser, aUri, aInstalls, aCount) { + }, + + QueryInterface: XPCOMUtils.generateQI([Ci.amIWebInstallPrompt]), + + classID: Components.ID("{405f3c55-241f-40df-97f1-a6e60e250ec5}"), + + factory: { + registrar: Components.manager.QueryInterface(Ci.nsIComponentRegistrar), + + register: function() { + this.registrar.registerFactory(InstallPrompt.classID, "InstallPrompt", + "@mozilla.org/addons/web-install-prompt;1", + this); + }, + + unregister: function() { + this.registrar.unregisterFactory(InstallPrompt.classID, this); + }, + + // nsIFactory + createInstance: function(aOuter, aIID) { + if (aOuter) { + throw Components.Exception("Class does not allow aggregation", + Components.results.NS_ERROR_NO_AGGREGATION); + } + return InstallPrompt.QueryInterface(aIID); + }, + + QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory]) + } +}; function test() { + InstallPrompt.factory.register(); + registerCleanupFunction(() => { + InstallPrompt.factory.unregister(); + }); + Harness.downloadProgressCallback = download_progress; Harness.installEndedCallback = install_ended; Harness.installsCompletedCallback = finish_test; @@ -14,7 +51,7 @@ function test() { pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); var triggers = encodeURIComponent(JSON.stringify({ - "Unsigned XPI": TESTROOT + "amosigned.xpi" + "Unsigned XPI": TESTROOT + "unsigned.xpi" })); gBrowser.selectedTab = gBrowser.addTab(); gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); @@ -31,7 +68,7 @@ function install_ended(install, addon) { function finish_test(count) { is(count, 0, "No add-ons should have been successfully installed"); - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("http://example.com", "install"); gBrowser.removeCurrentTab(); Harness.finish(); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_navigateaway4.js b/toolkit/mozapps/extensions/test/xpinstall/browser_navigateaway4.js index 61844c5a1..61fc7d3ac 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_navigateaway4.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_navigateaway4.js @@ -1,7 +1,7 @@ // ---------------------------------------------------------------------------- // Tests that navigating to a new origin cancels ongoing installs and closes // the install UI. -var sawUnload = null; +let sawUnload = null; function test() { Harness.installConfirmCallback = confirm_install; @@ -13,7 +13,7 @@ function test() { pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); var triggers = encodeURIComponent(JSON.stringify({ - "Unsigned XPI": TESTROOT + "amosigned.xpi" + "Unsigned XPI": TESTROOT + "unsigned.xpi" })); gBrowser.selectedTab = gBrowser.addTab(); gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); @@ -34,7 +34,7 @@ function install_ended(install, addon) { function finish_test(count) { is(count, 0, "No add-ons should have been successfully installed"); - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("http://example.com", "install"); sawUnload.then(() => { ok(true, "The install UI should have closed itself."); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_offline.js b/toolkit/mozapps/extensions/test/xpinstall/browser_offline.js index eb4ac391f..28f3497d1 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_offline.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_offline.js @@ -1,4 +1,4 @@ -var proxyPrefValue; +let proxyPrefValue; // ---------------------------------------------------------------------------- // Tests that going offline cancels an in progress download. @@ -11,7 +11,7 @@ function test() { pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); var triggers = encodeURIComponent(JSON.stringify({ - "Unsigned XPI": TESTROOT + "amosigned.xpi" + "Unsigned XPI": TESTROOT + "unsigned.xpi" })); gBrowser.selectedTab = gBrowser.addTab(); gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); @@ -34,10 +34,9 @@ function finish_test(count) { info("Checking if the browser is still offline..."); let tab = gBrowser.selectedTab; - ContentTask.spawn(tab.linkedBrowser, null, function*() { - yield ContentTaskUtils.waitForEvent(this, "DOMContentLoaded", true); - return content.document.documentURI; - }).then(url => { + tab.linkedBrowser.addEventListener("DOMContentLoaded", function errorLoad() { + tab.linkedBrowser.removeEventListener("DOMContentLoaded", errorLoad, true); + let url = tab.linkedBrowser.contentDocument.documentURI; info("loaded: " + url); if (/^about:neterror\?e=netOffline/.test(url)) { wait_for_online(); @@ -45,7 +44,7 @@ function finish_test(count) { gBrowser.removeCurrentTab(); Harness.finish(); } - }); + }, true); tab.linkedBrowser.loadURI("http://example.com/"); } @@ -56,7 +55,7 @@ function finish_test(count) { } catch (ex) { } - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("example.com", "install"); wait_for_online(); } diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_relative.js b/toolkit/mozapps/extensions/test/xpinstall/browser_relative.js index 3599f47d1..dfd5a0898 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_relative.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_relative.js @@ -12,7 +12,7 @@ function test() { var triggers = encodeURIComponent(JSON.stringify({ "Unsigned XPI": { - URL: "amosigned.xpi", + URL: "unsigned.xpi", IconURL: "icon.png", toString: function() { return this.URL; } } @@ -25,7 +25,7 @@ function confirm_install(window) { var items = window.document.getElementById("itemList").childNodes; is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); is(items[0].name, "XPI Test", "Should have seen the name"); - is(items[0].url, TESTROOT + "amosigned.xpi", "Should have listed the correct url for the item"); + is(items[0].url, TESTROOT + "unsigned.xpi", "Should have listed the correct url for the item"); is(items[0].icon, TESTROOT + "icon.png", "Should have listed the correct icon for the item"); is(items[0].signed, "false", "Should have listed the item as unsigned"); return true; @@ -35,21 +35,15 @@ function install_ended(install, addon) { install.cancel(); } -const finish_test = Task.async(function*(count) { +function finish_test(count) { is(count, 1, "1 Add-on should have been successfully installed"); - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("example.com", "install"); - const results = yield ContentTask.spawn(gBrowser.selectedBrowser, null, () => { - return { - return: content.document.getElementById("return").textContent, - status: content.document.getElementById("status").textContent, - } - }) - - is(results.return, "true", "installTrigger should have claimed success"); - is(results.status, "0", "Callback should have seen a success"); + var doc = gBrowser.contentDocument; + is(doc.getElementById("return").textContent, "true", "installTrigger should have claimed success"); + is(doc.getElementById("status").textContent, "0", "Callback should have seen a success"); gBrowser.removeCurrentTab(); Harness.finish(); -}); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_signed_multipackage.js b/toolkit/mozapps/extensions/test/xpinstall/browser_signed_multipackage.js deleted file mode 100644 index 7341f3082..000000000 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_signed_multipackage.js +++ /dev/null @@ -1,53 +0,0 @@ -// ---------------------------------------------------------------------------- -// Tests installing an signed add-on by navigating directly to the url -function test() { - Harness.installConfirmCallback = confirm_install; - Harness.installEndedCallback = install_ended; - Harness.installsCompletedCallback = finish_test; - Harness.setup(); - - gBrowser.selectedTab = gBrowser.addTab("about:blank"); - BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(() => { - gBrowser.loadURI(TESTROOT + "signed-multipackage.xpi"); - }); -} - -function get_item(items, name) { - for (let item of items) { - if (item.name == name) - return item; - } - ok(false, "Item for " + name + " was not listed"); - return null; -} - -function confirm_install(window) { - let items = window.document.getElementById("itemList").childNodes; - is(items.length, 2, "Should be 2 items listed in the confirmation dialog"); - - let item = get_item(items, "XPI Test"); - if (item) { - is(item.signed, "false", "Should not have listed the item as signed"); - is(item.icon, "", "Should have listed no icon for the item"); - } - - item = get_item(items, "Signed XPI Test"); - if (item) { - is(item.cert, "(Object Signer)", "Should have seen the signer"); - is(item.signed, "true", "Should have listed the item as signed"); - is(item.icon, "", "Should have listed no icon for the item"); - } - - return true; -} - -function install_ended(install, addon) { - install.cancel(); -} - -function finish_test(count) { - is(count, 2, "2 Add-ons should have been successfully installed"); - gBrowser.removeCurrentTab(); - Harness.finish(); -} -// ---------------------------------------------------------------------------- diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_signed_multiple.js b/toolkit/mozapps/extensions/test/xpinstall/browser_signed_multiple.js index 9dda1aaeb..e6efe5468 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_signed_multiple.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_signed_multiple.js @@ -37,7 +37,7 @@ function confirm_install(window) { var bundle = sbs.createBundle("chrome://mozapps/locale/xpinstall/xpinstallConfirm.properties"); var expectedIntroString = bundle.formatStringFromName("itemWarnIntroMultiple", ["5"], 1); - + var introStringNode = window.document.getElementById("itemWarningIntro"); is(introStringNode.textContent, expectedIntroString, "Should have the correct intro string"); @@ -65,7 +65,7 @@ function install_ended(install, addon) { function finish_test(count) { is(count, 5, "5 Add-ons should have been successfully installed"); - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("example.com", "install"); gBrowser.removeCurrentTab(); Harness.finish(); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_signed_naming.js b/toolkit/mozapps/extensions/test/xpinstall/browser_signed_naming.js index 5c3f79045..c57ddb200 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_signed_naming.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_signed_naming.js @@ -60,7 +60,7 @@ function install_ended(install, addon) { function finish_test(count) { is(count, 3, "3 Add-ons should have been successfully installed"); - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("example.com", "install"); gBrowser.removeCurrentTab(); Harness.finish(); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_signed_tampered.js b/toolkit/mozapps/extensions/test/xpinstall/browser_signed_tampered.js index fc798d66a..a3dc454d9 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_signed_tampered.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_signed_tampered.js @@ -26,7 +26,7 @@ function download_failed(install) { function finish_test(count) { is(count, 0, "No add-ons should have been installed"); - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("example.com", "install"); gBrowser.removeCurrentTab(); Harness.finish(); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_signed_trigger.js b/toolkit/mozapps/extensions/test/xpinstall/browser_signed_trigger.js index 8f1ae2d87..cefce2a4c 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_signed_trigger.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_signed_trigger.js @@ -34,7 +34,7 @@ function install_ended(install, addon) { function finish_test(count) { is(count, 1, "1 Add-on should have been successfully installed"); - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("example.com", "install"); gBrowser.removeCurrentTab(); Harness.finish(); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_signed_untrusted.js b/toolkit/mozapps/extensions/test/xpinstall/browser_signed_untrusted.js index d5fa9ae01..afb34d8a3 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_signed_untrusted.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_signed_untrusted.js @@ -33,7 +33,7 @@ function install_ended(install, addon) { function finish_test(count) { is(count, 1, "1 Add-on should have been successfully installed"); - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("example.com", "install"); gBrowser.removeCurrentTab(); Harness.finish(); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_softwareupdate.js b/toolkit/mozapps/extensions/test/xpinstall/browser_softwareupdate.js index 16e20f3e9..4c3dc768e 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_softwareupdate.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_softwareupdate.js @@ -9,7 +9,7 @@ function test() { pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.loadURI(TESTROOT + "startsoftwareupdate.html? " + encodeURIComponent(TESTROOT + "amosigned.xpi")); + gBrowser.loadURI(TESTROOT + "startsoftwareupdate.html? " + encodeURIComponent(TESTROOT + "unsigned.xpi")); } function install_ended(install, addon) { @@ -18,7 +18,7 @@ function install_ended(install, addon) { function finish_test(count) { is(count, 1, "1 Add-on should have been successfully installed"); - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("example.com", "install"); gBrowser.removeCurrentTab(); Harness.finish(); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_switchtab.js b/toolkit/mozapps/extensions/test/xpinstall/browser_switchtab.js index 9bbb59400..9672de9bd 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_switchtab.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_switchtab.js @@ -1,7 +1,7 @@ // ---------------------------------------------------------------------------- // Tests installing an unsigned add-on through an InstallTrigger call in web // content. -var expectedTab = null; +let expectedTab = null; function test() { Harness.installConfirmCallback = confirm_install; @@ -14,7 +14,7 @@ function test() { var triggers = encodeURIComponent(JSON.stringify({ "Unsigned XPI": { - URL: TESTROOT + "amosigned.xpi", + URL: TESTROOT + "unsigned.xpi", IconURL: TESTROOT + "icon.png", toString: function() { return this.URL; } } @@ -27,7 +27,7 @@ function confirm_install(window) { var items = window.document.getElementById("itemList").childNodes; is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); is(items[0].name, "XPI Test", "Should have seen the name"); - is(items[0].url, TESTROOT + "amosigned.xpi", "Should have listed the correct url for the item"); + is(items[0].url, TESTROOT + "unsigned.xpi", "Should have listed the correct url for the item"); is(items[0].icon, TESTROOT + "icon.png", "Should have listed the correct icon for the item"); is(items[0].signed, "false", "Should have listed the item as unsigned"); @@ -42,7 +42,7 @@ function install_ended(install, addon) { function finish_test(count) { is(count, 1, "1 Add-on should have been successfully installed"); - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("example.com", "install"); gBrowser.removeTab(expectedTab); Harness.finish(); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_trigger_redirect.js b/toolkit/mozapps/extensions/test/xpinstall/browser_trigger_redirect.js index 9c0543602..a5448b616 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_trigger_redirect.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_trigger_redirect.js @@ -18,7 +18,7 @@ function confirm_install(window) { var items = window.document.getElementById("itemList").childNodes; is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); is(items[0].name, "XPI Test", "Should have seen the name"); - is(items[0].url, TESTROOT + "amosigned.xpi", "Should have listed the correct url for the item"); + is(items[0].url, TESTROOT + "unsigned.xpi", "Should have listed the correct url for the item"); is(items[0].icon, TESTROOT + "icon.png", "Should have listed the correct icon for the item"); is(items[0].signed, "false", "Should have listed the item as unsigned"); return true; @@ -31,7 +31,7 @@ function install_ended(install, addon) { function finish_test(count) { is(count, 1, "1 Add-on should have been successfully installed"); - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("example.com", "install"); var doc = gBrowser.contentDocument; is(gBrowser.currentURI.spec, TESTROOT + "triggerredirect.html#foo", "Should have redirected"); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger.js b/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger.js index 006879439..ab0f238aa 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger.js @@ -36,21 +36,15 @@ function install_ended(install, addon) { install.cancel(); } -const finish_test = Task.async(function*(count) { +function finish_test(count) { is(count, 1, "1 Add-on should have been successfully installed"); - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("example.com", "install"); - const results = yield ContentTask.spawn(gBrowser.selectedBrowser, null, () => { - return { - return: content.document.getElementById("return").textContent, - status: content.document.getElementById("status").textContent, - } - }) - - is(results.return, "true", "installTrigger should have claimed success"); - is(results.status, "0", "Callback should have seen a success"); + var doc = gBrowser.contentDocument; + is(doc.getElementById("return").textContent, "true", "installTrigger should have claimed success"); + is(doc.getElementById("status").textContent, "0", "Callback should have seen a success"); gBrowser.removeCurrentTab(); Harness.finish(); -}); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger_iframe.js b/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger_iframe.js index b9df6615e..658bbfe1c 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger_iframe.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger_iframe.js @@ -37,21 +37,15 @@ function install_ended(install, addon) { install.cancel(); } -const finish_test = Task.async(function*(count) { +function finish_test(count) { is(count, 1, "1 Add-on should have been successfully installed"); - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("example.com", "install"); - const results = yield ContentTask.spawn(gBrowser.selectedBrowser, null, () => { - return { - return: content.frames[0].document.getElementById("return").textContent, - status: content.frames[0].document.getElementById("status").textContent, - } - }) - - is(results.return, "true", "installTrigger in iframe should have claimed success"); - is(results.status, "0", "Callback in iframe should have seen a success"); + var doc = gBrowser.contentWindow.frames[0].document; // Document of iframe + is(doc.getElementById("return").textContent, "true", "installTrigger in iframe should have claimed success"); + is(doc.getElementById("status").textContent, "0", "Callback in iframe should have seen a success"); gBrowser.removeCurrentTab(); Harness.finish(); -}); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger_xorigin.js b/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger_xorigin.js index b0875fc99..07947a135 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger_xorigin.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger_xorigin.js @@ -1,7 +1,7 @@ // ---------------------------------------------------------------------------- // Ensure that an inner frame from a different origin can't initiate an install -var wasOriginBlocked = false; +let wasOriginBlocked = false; function test() { Harness.installOriginBlockedCallback = install_blocked; @@ -14,7 +14,7 @@ function test() { var inner_url = encodeURIComponent(TESTROOT + "installtrigger.html?" + encodeURIComponent(JSON.stringify({ "Unsigned XPI": { - URL: TESTROOT + "amosigned.xpi", + URL: TESTROOT + "unsigned.xpi", IconURL: TESTROOT + "icon.png", toString: function() { return this.URL; } } @@ -31,7 +31,7 @@ function finish_test(count) { ok(wasOriginBlocked, "Should have been blocked due to the cross origin request."); is(count, 0, "No add-ons should have been installed"); - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("http://example.com", "install"); gBrowser.removeCurrentTab(); Harness.finish(); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist.js b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist.js index ad3d645f5..448ce3a5c 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist.js @@ -10,7 +10,7 @@ function test() { Harness.setup(); var triggers = encodeURIComponent(JSON.stringify({ - "Unsigned XPI": TESTROOT + "amosigned.xpi" + "Unsigned XPI": TESTROOT + "unsigned.xpi" })); gBrowser.selectedTab = gBrowser.addTab(); gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); @@ -26,7 +26,7 @@ function confirm_install(window) { var items = window.document.getElementById("itemList").childNodes; is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); is(items[0].name, "XPI Test", "Should have seen the name from the trigger list"); - is(items[0].url, TESTROOT + "amosigned.xpi", "Should have listed the correct url for the item"); + is(items[0].url, TESTROOT + "unsigned.xpi", "Should have listed the correct url for the item"); is(items[0].signed, "false", "Should have listed the item as unsigned"); return true; } @@ -35,19 +35,12 @@ function install_ended(install, addon) { install.cancel(); } -const finish_test = Task.async(function*(count) { +function finish_test(count) { is(count, 1, "1 Add-on should have been successfully installed"); - const results = yield ContentTask.spawn(gBrowser.selectedBrowser, null, () => { - return { - return: content.document.getElementById("return").textContent, - status: content.document.getElementById("status").textContent, - } - }) - - is(results.return, "false", "installTrigger should seen a failure"); - + var doc = gBrowser.contentDocument; + is(doc.getElementById("return").textContent, "false", "installTrigger should seen a failure"); gBrowser.removeCurrentTab(); Harness.finish(); -}); +} // ---------------------------------------------------------------------------- diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist2.js b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist2.js index fd9e944e8..168a31ef3 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist2.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist2.js @@ -11,7 +11,7 @@ function test() { pm.add(makeURI("http://example.org/"), "install", pm.ALLOW_ACTION); var triggers = encodeURIComponent(JSON.stringify({ - "Unsigned XPI": TESTROOT2 + "amosigned.xpi" + "Unsigned XPI": TESTROOT2 + "unsigned.xpi" })); gBrowser.selectedTab = gBrowser.addTab(); gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); @@ -24,7 +24,7 @@ function allow_blocked(installInfo) { } function finish_test() { - Services.perms.remove(makeURI("http://example.org"), "install"); + Services.perms.remove("example.org", "install"); gBrowser.removeCurrentTab(); Harness.finish(); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist3.js b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist3.js index 6f4306df6..888e1bd5a 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist3.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist3.js @@ -1,7 +1,7 @@ // ---------------------------------------------------------------------------- // Tests installing an unsigned add-on through a navigation. Should not be // blocked since the referer is whitelisted. -var url = TESTROOT2 + "navigate.html?" + encodeURIComponent(TESTROOT + "amosigned.xpi"); +let URL = TESTROOT2 + "navigate.html?" + encodeURIComponent(TESTROOT + "unsigned.xpi"); function test() { Harness.installConfirmCallback = confirm_install; @@ -12,7 +12,7 @@ function test() { pm.add(makeURI("http://example.org/"), "install", pm.ALLOW_ACTION); gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.loadURI(url); + gBrowser.loadURI(URL); } function confirm_install(window) { @@ -21,7 +21,7 @@ function confirm_install(window) { function finish_test(count) { is(count, 0, "No add-ons should have been installed"); - Services.perms.remove(makeURI("http://example.org"), "install"); + Services.perms.remove("example.org", "install"); gBrowser.removeCurrentTab(); Harness.finish(); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist4.js b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist4.js index e4c47cda5..14a961742 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist4.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist4.js @@ -1,7 +1,7 @@ // ---------------------------------------------------------------------------- // Tests installing an unsigned add-on through a navigation. Should be // blocked since the referer is not whitelisted even though the target is. -var url = TESTROOT2 + "navigate.html?" + encodeURIComponent(TESTROOT + "amosigned.xpi"); +let URL = TESTROOT2 + "navigate.html?" + encodeURIComponent(TESTROOT + "unsigned.xpi"); function test() { Harness.installBlockedCallback = allow_blocked; @@ -12,18 +12,18 @@ function test() { pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.loadURI(url); + gBrowser.loadURI(URL); } function allow_blocked(installInfo) { is(installInfo.browser, gBrowser.selectedBrowser, "Install should have been triggered by the right browser"); - is(installInfo.originatingURI.spec, url, "Install should have been triggered by the right uri"); + is(installInfo.originatingURI.spec, URL, "Install should have been triggered by the right uri"); return false; } function finish_test(count) { is(count, 0, "No add-ons should have been installed"); - Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove("example.com", "install"); gBrowser.removeCurrentTab(); Harness.finish(); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist5.js b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist5.js index 0a9333430..97448d803 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist5.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist5.js @@ -8,7 +8,7 @@ function test() { Harness.setup(); gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.loadURI(TESTROOT + "startsoftwareupdate.html? " + encodeURIComponent(TESTROOT + "amosigned.xpi")); + gBrowser.loadURI(TESTROOT + "startsoftwareupdate.html? " + encodeURIComponent(TESTROOT + "unsigned.xpi")); } function allow_blocked(installInfo) { diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist6.js b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist6.js index 555f1e2fc..f2f3641e4 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist6.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist6.js @@ -8,7 +8,7 @@ function test() { Harness.setup(); gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.loadURI(TESTROOT + "installchrome.html? " + encodeURIComponent(TESTROOT + "amosigned.xpi")); + gBrowser.loadURI(TESTROOT + "installchrome.html? " + encodeURIComponent(TESTROOT + "unsigned.xpi")); } function allow_blocked(installInfo) { diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist7.js b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist7.js index 96c60ac9e..b36617ab5 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist7.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist7.js @@ -12,7 +12,7 @@ function test() { gBrowser.selectedTab = gBrowser.addTab("about:blank"); BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(() => { - gBrowser.loadURI(TESTROOT + "amosigned.xpi"); + gBrowser.loadURI(TESTROOT + "unsigned.xpi"); }); } @@ -24,7 +24,7 @@ function allow_blocked(installInfo) { function finish_test(count) { is(count, 0, "No add-ons should have been installed"); - Services.perms.remove(makeURI("http://example.org"), "install"); + Services.perms.remove("example.org", "install"); Services.prefs.clearUserPref("xpinstall.whitelist.directRequest"); gBrowser.removeCurrentTab(); diff --git a/toolkit/mozapps/extensions/test/xpinstall/bug540558.html b/toolkit/mozapps/extensions/test/xpinstall/bug540558.html index 286046d25..666a56437 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/bug540558.html +++ b/toolkit/mozapps/extensions/test/xpinstall/bug540558.html @@ -10,7 +10,7 @@ <script type="text/javascript"> function startInstall() { window.InstallTrigger.install({ - "Unsigned XPI": "amosigned.xpi" + "Unsigned XPI": "unsigned.xpi" }); } </script> diff --git a/toolkit/mozapps/extensions/test/xpinstall/bug645699.html b/toolkit/mozapps/extensions/test/xpinstall/bug645699.html index 8334c37c2..9a65720ae 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/bug645699.html +++ b/toolkit/mozapps/extensions/test/xpinstall/bug645699.html @@ -6,7 +6,6 @@ <head> <title>InstallTrigger tests</title> <script type="text/javascript"> -/* globals InstallTrigger */ function startInstall() { var whiteUrl = "https://example.org/"; @@ -20,7 +19,7 @@ function startInstall() { Object.defineProperty(document, "documentURIObject", { spec : { href : whiteUrl } }); InstallTrigger.install({ - "Unsigned XPI": "http://example.com/browser/toolkit/mozapps/extensions/test/xpinstall/amosigned.xpi" + "Unsigned XPI": "http://example.com/browser/toolkit/mozapps/extensions/test/xpinstall/unsigned.xpi" }); } </script> diff --git a/toolkit/mozapps/extensions/test/xpinstall/concurrent_installs.html b/toolkit/mozapps/extensions/test/xpinstall/concurrent_installs.html index 780409257..192bbf2bc 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/concurrent_installs.html +++ b/toolkit/mozapps/extensions/test/xpinstall/concurrent_installs.html @@ -7,7 +7,6 @@ <meta charset="utf-8"> <title>Concurrent InstallTrigger tests</title> <script type="text/javascript"> -/* globals InstallTrigger */ function installCallback(url, status) { document.getElementById("status").textContent = status; @@ -19,7 +18,7 @@ function installCallback(url, status) { function startInstall() { var root = location.href.replace("concurrent_installs.html", ""); var triggers = { - "Unsigned XPI": root + "amosigned.xpi" + "Unsigned XPI": root + "unsigned.xpi" }; try { document.getElementById("return").textContent = InstallTrigger.install(triggers, installCallback); diff --git a/toolkit/mozapps/extensions/test/xpinstall/enabled.html b/toolkit/mozapps/extensions/test/xpinstall/enabled.html index 370cde8fb..ec8513edc 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/enabled.html +++ b/toolkit/mozapps/extensions/test/xpinstall/enabled.html @@ -8,7 +8,6 @@ <head> <title>InstallTrigger tests</title> <script type="text/javascript"> -/* globals InstallTrigger */ function init() { document.getElementById("enabled").textContent = InstallTrigger.enabled() ? "true" : "false"; dump("Sending PageLoaded\n"); diff --git a/toolkit/mozapps/extensions/test/xpinstall/head.js b/toolkit/mozapps/extensions/test/xpinstall/head.js index 197fe3fac..90db29924 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/head.js +++ b/toolkit/mozapps/extensions/test/xpinstall/head.js @@ -8,7 +8,6 @@ const ADDONS_URL = "chrome://mozapps/content/extensions/extensions.xul"; const PREF_LOGGING_ENABLED = "extensions.logging.enabled"; const PREF_INSTALL_REQUIREBUILTINCERTS = "extensions.install.requireBuiltInCerts"; const PREF_INSTALL_REQUIRESECUREORIGIN = "extensions.install.requireSecureOrigin"; -const PREF_CUSTOM_CONFIRMATION_UI = "xpinstall.customConfirmationUI"; const CHROME_NAME = "mochikit"; function getChromeRoot(path) { @@ -28,11 +27,6 @@ function extractChromeRoot(path) { return chromeRootPath; } -Services.prefs.setBoolPref(PREF_CUSTOM_CONFIRMATION_UI, false); -registerCleanupFunction(() => { - Services.prefs.clearUserPref(PREF_CUSTOM_CONFIRMATION_UI); -}); - /** * This is a test harness designed to handle responding to UI during the process * of installing an XPI. A test can set callbacks to hear about specific parts @@ -174,7 +168,7 @@ var Harness = { this.runningInstalls = null; if (callback) - executeSoon(() => callback(count)); + callback(count); }, // Window open handling @@ -244,8 +238,6 @@ var Harness = { ok(!!this.installDisabledCallback, "Installation shouldn't have been disabled"); if (this.installDisabledCallback) this.installDisabledCallback(installInfo); - this.expectingCancelled = true; - this.expectingCancelled = false; this.endTest(); }, @@ -307,17 +299,15 @@ var Harness = { if (this.finalContentEvent && !this.waitingForEvent) { this.waitingForEvent = true; info("Waiting for " + this.finalContentEvent); - let mm = gBrowser.selectedBrowser.messageManager; - mm.loadFrameScript(`data:,content.addEventListener("${this.finalContentEvent}", () => { sendAsyncMessage("Test:GotNewInstallEvent"); });`, false); let win = gBrowser.contentWindow; let listener = () => { info("Saw " + this.finalContentEvent); - mm.removeMessageListener("Test:GotNewInstallEvent", listener); + win.removeEventListener(this.finalContentEvent, listener, false); this.waitingForEvent = false; if (this.pendingCount == 0) this.endTest(); } - mm.addMessageListener("Test:GotNewInstallEvent", listener); + win.addEventListener(this.finalContentEvent, listener, false); } }, diff --git a/toolkit/mozapps/extensions/test/xpinstall/incompatible.xpi b/toolkit/mozapps/extensions/test/xpinstall/incompatible.xpi Binary files differindex 262ed38a7..cc40f43c9 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/incompatible.xpi +++ b/toolkit/mozapps/extensions/test/xpinstall/incompatible.xpi diff --git a/toolkit/mozapps/extensions/test/xpinstall/installchrome.html b/toolkit/mozapps/extensions/test/xpinstall/installchrome.html index 6abee2ef3..71c072d3a 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/installchrome.html +++ b/toolkit/mozapps/extensions/test/xpinstall/installchrome.html @@ -8,7 +8,6 @@ <head> <title>InstallTrigger tests</title> <script type="text/javascript"> -/* globals InstallTrigger */ function startInstall() { InstallTrigger.installChrome(InstallTrigger.SKIN, decodeURIComponent(document.location.search.substring(1)), diff --git a/toolkit/mozapps/extensions/test/xpinstall/installtrigger.html b/toolkit/mozapps/extensions/test/xpinstall/installtrigger.html index 65cab1ef1..cd7618cc5 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/installtrigger.html +++ b/toolkit/mozapps/extensions/test/xpinstall/installtrigger.html @@ -8,7 +8,6 @@ <head> <title>InstallTrigger tests</title> <script type="text/javascript"> -/* globals InstallTrigger */ function installCallback(url, status) { document.getElementById("status").textContent = status; diff --git a/toolkit/mozapps/extensions/test/xpinstall/multipackage.xpi b/toolkit/mozapps/extensions/test/xpinstall/multipackage.xpi Binary files differindex d52f28c28..11fbe1861 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/multipackage.xpi +++ b/toolkit/mozapps/extensions/test/xpinstall/multipackage.xpi diff --git a/toolkit/mozapps/extensions/test/xpinstall/restartless-unsigned.xpi b/toolkit/mozapps/extensions/test/xpinstall/restartless-unsigned.xpi Binary files differdeleted file mode 100644 index 8e76bd052..000000000 --- a/toolkit/mozapps/extensions/test/xpinstall/restartless-unsigned.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpinstall/restartless.xpi b/toolkit/mozapps/extensions/test/xpinstall/restartless.xpi Binary files differindex 9fee8f60b..973bc00cb 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/restartless.xpi +++ b/toolkit/mozapps/extensions/test/xpinstall/restartless.xpi diff --git a/toolkit/mozapps/extensions/test/xpinstall/signed-multipackage.xpi b/toolkit/mozapps/extensions/test/xpinstall/signed-multipackage.xpi Binary files differdeleted file mode 100644 index 11fbe1861..000000000 --- a/toolkit/mozapps/extensions/test/xpinstall/signed-multipackage.xpi +++ /dev/null diff --git a/toolkit/mozapps/extensions/test/xpinstall/startsoftwareupdate.html b/toolkit/mozapps/extensions/test/xpinstall/startsoftwareupdate.html index 50083ca90..4845a504a 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/startsoftwareupdate.html +++ b/toolkit/mozapps/extensions/test/xpinstall/startsoftwareupdate.html @@ -8,7 +8,6 @@ <head> <title>InstallTrigger tests</title> <script type="text/javascript"> -/* globals InstallTrigger */ function startInstall() { InstallTrigger.startSoftwareUpdate(decodeURIComponent(document.location.search.substring(1))); } diff --git a/toolkit/mozapps/extensions/test/xpinstall/theme.xpi b/toolkit/mozapps/extensions/test/xpinstall/theme.xpi Binary files differindex 74e650b4a..0c94a280b 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/theme.xpi +++ b/toolkit/mozapps/extensions/test/xpinstall/theme.xpi diff --git a/toolkit/mozapps/extensions/test/xpinstall/triggerredirect.html b/toolkit/mozapps/extensions/test/xpinstall/triggerredirect.html index 42e0e1cd0..49fda7dc8 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/triggerredirect.html +++ b/toolkit/mozapps/extensions/test/xpinstall/triggerredirect.html @@ -8,7 +8,6 @@ <head> <title>InstallTrigger tests</title> <script type="text/javascript"> -/* globals InstallTrigger */ function installCallback(url, status) { document.location = "#foo"; @@ -20,7 +19,7 @@ function installCallback(url, status) { function startInstall() { InstallTrigger.install({ "Unsigned XPI": { - URL: "amosigned.xpi", + URL: "unsigned.xpi", IconURL: "icon.png", toString: function() { return this.URL; } } |