Merge mozilla-central to inbound a=merge on a CLOSED TREE

This commit is contained in:
Coroiu Cristina 2018-09-24 12:53:39 +03:00
Родитель 47e5a8b711 881a3c5664
Коммит 68a73ded70
19 изменённых файлов: 356 добавлений и 207 удалений

Просмотреть файл

@ -233,7 +233,7 @@ AccGroupInfo::TotalItemCount(Accessible* aContainer, bool* aIsHierarchical)
Accessible* childItem = AccGroupInfo::FirstItemOf(aContainer);
if (!childItem) {
childItem = aContainer->FirstChild();
if (childItem->IsTextLeaf()) {
if (childItem && childItem->IsTextLeaf()) {
// First child can be a text leaf, check its sibling for an item.
childItem = childItem->NextSibling();
}

Просмотреть файл

@ -6,7 +6,6 @@
const {XPCOMUtils} = require("resource://gre/modules/XPCOMUtils.jsm");
const {SideMenuWidget} = require("devtools/client/shared/widgets/SideMenuWidget.jsm");
const promise = require("promise");
const defer = require("devtools/shared/defer");
const {Task} = require("devtools/shared/task");
const EventEmitter = require("devtools/shared/event-emitter");
const { HTMLTooltip } = require("devtools/client/shared/widgets/tooltip/HTMLTooltip");
@ -415,22 +414,21 @@ class ShadersEditorsView {
return this._editorPromises.get(type);
}
const deferred = defer();
this._editorPromises.set(type, deferred.promise);
const promise = new Promise(resolve =>{
// Initialize the source editor and store the newly created instance
// in the ether of a resolved promise's value.
const parent = $("#" + type + "-editor");
const editor = new Editor(DEFAULT_EDITOR_CONFIG);
editor.config.mode = Editor.modes[type];
// Initialize the source editor and store the newly created instance
// in the ether of a resolved promise's value.
const parent = $("#" + type + "-editor");
const editor = new Editor(DEFAULT_EDITOR_CONFIG);
editor.config.mode = Editor.modes[type];
if (this._destroyed) {
deferred.resolve(editor);
} else {
editor.appendTo(parent).then(() => deferred.resolve(editor));
}
return deferred.promise;
if (this._destroyed) {
resolve(editor);
} else {
editor.appendTo(parent).then(() => resolve(editor));
}
});
this._editorPromises.set(type, promise);
return promise;
}
/**

Просмотреть файл

@ -83,15 +83,12 @@ function createCanvas() {
function observe(aNotificationName, aOwnsWeak = false) {
info("Waiting for observer notification: '" + aNotificationName + ".");
const deferred = defer();
Services.obs.addObserver(function onNotification(...aArgs) {
Services.obs.removeObserver(onNotification, aNotificationName);
deferred.resolve.apply(deferred, aArgs);
}, aNotificationName, aOwnsWeak);
return deferred.promise;
return new Promise(resolve =>{
Services.obs.addObserver(function onNotification(...aArgs) {
Services.obs.removeObserver(onNotification, aNotificationName);
resolve.apply(deferred, aArgs);
}, aNotificationName, aOwnsWeak);
});
}
function isApprox(aFirst, aSecond, aMargin = 1) {
@ -195,19 +192,19 @@ function teardown(aPanel) {
// programs that should be listened to and waited on, and an optional
// `onAdd` function that calls with the entire actors array on program link
function getPrograms(front, count, onAdd) {
const actors = [];
const deferred = defer();
front.on("program-linked", function onLink(actor) {
if (actors.length !== count) {
actors.push(actor);
if (typeof onAdd === "function") {
onAdd(actors);
return new Promise(resolve => {
const actors = [];
front.on("program-linked", function onLink(actor) {
if (actors.length !== count) {
actors.push(actor);
if (typeof onAdd === "function") {
onAdd(actors);
}
}
}
if (actors.length === count) {
front.off("program-linked", onLink);
deferred.resolve(actors);
}
if (actors.length === count) {
front.off("program-linked", onLink);
resolve(actors);
}
});
});
return deferred.promise;
}

Просмотреть файл

@ -54,12 +54,6 @@ PrioEncoder::Encode(GlobalObject& aGlobal,
SECStatus prio_rv = SECSuccess;
if (!sSingleton) {
sSingleton = new PrioEncoder();
ClearOnShutdown(&sSingleton);
Prio_init();
nsresult rv;
nsAutoCStringN<CURVE25519_KEY_LEN_HEX + 1> prioKeyA;
@ -84,6 +78,13 @@ PrioEncoder::Encode(GlobalObject& aGlobal,
return;
}
prio_rv = Prio_init();
if (prio_rv != SECSuccess) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
prio_rv = PublicKey_import_hex(&sPublicKeyA,
reinterpret_cast<const unsigned char*>(prioKeyA.BeginReading()),
CURVE25519_KEY_LEN_HEX);
@ -99,6 +100,9 @@ PrioEncoder::Encode(GlobalObject& aGlobal,
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
sSingleton = new PrioEncoder();
ClearOnShutdown(&sSingleton);
}
bool dataItems[] = {

Просмотреть файл

@ -12,6 +12,40 @@
#include "mozilla/Preferences.h"
#include "mozilla/dom/ScriptSettings.h"
TEST(PrioEncoder, BadPublicKeys)
{
mozilla::dom::AutoJSAPI jsAPI;
ASSERT_TRUE(jsAPI.Init(xpc::PrivilegedJunkScope()));
JSContext* cx = jsAPI.cx();
mozilla::Preferences::SetCString("prio.publicKeyA",
nsCString(NS_LITERAL_CSTRING("badA")));
mozilla::Preferences::SetCString("prio.publicKeyB",
nsCString(NS_LITERAL_CSTRING("badB")));
mozilla::dom::GlobalObject global(cx, xpc::PrivilegedJunkScope());
nsCString batchID = NS_LITERAL_CSTRING("abc123");
mozilla::dom::PrioParams prioParams;
prioParams.mBrowserIsUserDefault = true;
prioParams.mNewTabPageEnabled = true;
prioParams.mPdfViewerUsed = false;
mozilla::dom::RootedDictionary<mozilla::dom::PrioEncodedData> prioEncodedData(cx);
mozilla::ErrorResult rv;
mozilla::dom::PrioEncoder::Encode(global, batchID, prioParams, prioEncodedData, rv);
ASSERT_TRUE(rv.Failed());
// Call again to ensure that the singleton state is consistent.
mozilla::dom::PrioEncoder::Encode(global, batchID, prioParams, prioEncodedData, rv);
ASSERT_TRUE(rv.Failed());
// Reset error result so test runner does not fail.
rv = mozilla::ErrorResult();
}
TEST(PrioEncoder, VerifyFull)
{
SECStatus prioRv = SECSuccess;

Просмотреть файл

@ -1285,7 +1285,7 @@ gfxPlatformFontList::AppendCJKPrefLangs(eFontPrefLang aPrefLangs[], uint32_t &aL
AutoTArray<nsCString,16> sysLocales;
AutoTArray<nsCString,16> negLocales;
if (OSPreferences::GetInstance()->GetSystemLocales(sysLocales)) {
if (NS_SUCCEEDED(OSPreferences::GetInstance()->GetSystemLocales(sysLocales))) {
LocaleService::GetInstance()->NegotiateLanguages(
sysLocales, prefLocales, NS_LITERAL_CSTRING(""),
LocaleService::kLangNegStrategyFiltering, negLocales);

Просмотреть файл

@ -628,7 +628,7 @@ LocaleService::GetRegionalPrefsLocales(nsTArray<nsCString>& aRetVal)
// If the user specified that they want to use OS Regional Preferences locales,
// try to retrieve them and use.
if (useOSLocales) {
if (OSPreferences::GetInstance()->GetRegionalPrefsLocales(aRetVal)) {
if (NS_SUCCEEDED(OSPreferences::GetInstance()->GetRegionalPrefsLocales(aRetVal))) {
return NS_OK;
}
@ -647,7 +647,7 @@ LocaleService::GetRegionalPrefsLocales(nsTArray<nsCString>& aRetVal)
AutoTArray<nsCString, 10> regionalPrefsLocales;
LocaleService::GetInstance()->GetAppLocaleAsBCP47(appLocale);
if (!OSPreferences::GetInstance()->GetRegionalPrefsLocales(regionalPrefsLocales)) {
if (NS_FAILED(OSPreferences::GetInstance()->GetRegionalPrefsLocales(regionalPrefsLocales))) {
GetAppLocalesAsBCP47(aRetVal);
return NS_OK;
}

Просмотреть файл

@ -33,42 +33,6 @@ OSPreferences::GetInstance()
return sInstance;
}
bool
OSPreferences::GetSystemLocales(nsTArray<nsCString>& aRetVal)
{
if (!mSystemLocales.IsEmpty()) {
aRetVal = mSystemLocales;
return true;
}
if (ReadSystemLocales(aRetVal)) {
mSystemLocales = aRetVal;
return true;
}
// If we failed to get the system locale, we still need
// to return something because there are tests out there that
// depend on system locale to be set.
aRetVal.AppendElement(NS_LITERAL_CSTRING("en-US"));
return false;
}
bool
OSPreferences::GetRegionalPrefsLocales(nsTArray<nsCString>& aRetVal)
{
if (!mRegionalPrefsLocales.IsEmpty()) {
aRetVal = mRegionalPrefsLocales;
return true;
}
if (ReadRegionalPrefsLocales(aRetVal)) {
mRegionalPrefsLocales = aRetVal;
return true;
}
return false;
}
void
OSPreferences::Refresh()
{
@ -298,27 +262,23 @@ OSPreferences::GetDateTimeConnectorPattern(const nsACString& aLocale,
* mozIOSPreferences methods
*/
NS_IMETHODIMP
OSPreferences::GetSystemLocales(uint32_t* aCount, char*** aOutArray)
OSPreferences::GetSystemLocales(nsTArray<nsCString>& aRetVal)
{
AutoTArray<nsCString,10> tempLocales;
nsTArray<nsCString>* systemLocalesPtr;
if (!mSystemLocales.IsEmpty()) {
// use cached value
systemLocalesPtr = &mSystemLocales;
} else {
// get a (perhaps temporary/fallback/hack) value
GetSystemLocales(tempLocales);
systemLocalesPtr = &tempLocales;
}
*aCount = systemLocalesPtr->Length();
*aOutArray = static_cast<char**>(moz_xmalloc(*aCount * sizeof(char*)));
for (uint32_t i = 0; i < *aCount; i++) {
(*aOutArray)[i] = moz_xstrdup((*systemLocalesPtr)[i].get());
aRetVal = mSystemLocales;
return NS_OK;
}
return NS_OK;
if (ReadSystemLocales(aRetVal)) {
mSystemLocales = aRetVal;
return NS_OK;
}
// If we failed to get the system locale, we still need
// to return something because there are tests out there that
// depend on system locale to be set.
aRetVal.AppendElement(NS_LITERAL_CSTRING("en-US"));
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
@ -337,27 +297,19 @@ OSPreferences::GetSystemLocale(nsACString& aRetVal)
}
NS_IMETHODIMP
OSPreferences::GetRegionalPrefsLocales(uint32_t* aCount, char*** aOutArray)
OSPreferences::GetRegionalPrefsLocales(nsTArray<nsCString>& aRetVal)
{
AutoTArray<nsCString,10> tempLocales;
nsTArray<nsCString>* regionalPrefsLocalesPtr;
if (!mRegionalPrefsLocales.IsEmpty()) {
// use cached value
regionalPrefsLocalesPtr = &mRegionalPrefsLocales;
} else {
// get a (perhaps temporary/fallback/hack) value
GetRegionalPrefsLocales(tempLocales);
regionalPrefsLocalesPtr = &tempLocales;
}
*aCount = regionalPrefsLocalesPtr->Length();
*aOutArray = static_cast<char**>(moz_xmalloc(*aCount * sizeof(char*)));
for (uint32_t i = 0; i < *aCount; i++) {
(*aOutArray)[i] = moz_xstrdup((*regionalPrefsLocalesPtr)[i].get());
aRetVal = mRegionalPrefsLocales;
return NS_OK;
}
return NS_OK;
if (ReadRegionalPrefsLocales(aRetVal)) {
mRegionalPrefsLocales = aRetVal;
return NS_OK;
}
return NS_ERROR_FAILURE;
}
static OSPreferences::DateTimeFormatStyle

Просмотреть файл

@ -81,54 +81,6 @@ public:
}
/**
* Returns a list of locales used by the host environment for UI
* localization.
*
* The result is a sorted list and we expect that the OS attempts to
* use the top locale from the list for which it has data.
*
* Each element of the list is a valid locale ID that can be passed to ICU
* and ECMA402 Intl APIs,
* At the same time each element is a valid BCP47 language tag that can be
* used for language negotiation.
*
* Example: ["en-US", "de", "pl", "sr-Cyrl", "zh-Hans-HK"]
*
* The return bool value indicates whether the function successfully
* resolved at least one locale.
*
* Usage:
* nsTArray<nsCString> systemLocales;
* OSPreferences::GetInstance()->GetSystemLocales(systemLocales);
*
* (See mozIOSPreferences.idl for a JS-callable version of this.)
*/
bool GetSystemLocales(nsTArray<nsCString>& aRetVal);
/**
* Returns a list of locales used by host environment for regional
* preferences internationalization.
*
* The result is a sorted list and we expect that the OS attempts to
* use the top locale from the list for which it has data.
*
* Each element of the list is a valid locale ID that can be passed to ICU
* and ECMA402 Intl APIs,
*
* Example: ["en-US", "de", "pl", "sr-Cyrl", "zh-Hans-HK"]
*
* The return bool value indicates whether the function successfully
* resolved at least one locale.
*
* Usage:
* nsTArray<nsCString> systemLocales;
* OSPreferences::GetInstance()->GetRegionalPrefsLocales(regionalPrefsLocales);
*
* (See mozIOSPreferences.idl for a JS-callable version of this.)
*/
bool GetRegionalPrefsLocales(nsTArray<nsCString>& aRetVal);
static bool GetDateTimeConnectorPattern(const nsACString& aLocale,
nsAString& aRetVal);

Просмотреть файл

@ -35,11 +35,8 @@ interface mozIOSPreferences : nsISupports
* used for language negotiation.
*
* Example: ["en-US", "de", "pl", "sr-Cyrl", "zh-Hans-HK"]
*
* (See OSPreferences.h for a more C++-friendly version of this.)
*/
void getSystemLocales([optional] out unsigned long aCount,
[retval, array, size_is(aCount)] out string aOutArray);
readonly attribute Array<ACString> systemLocales;
/**
* Returns a list of locales used by host environment for regional
@ -52,11 +49,8 @@ interface mozIOSPreferences : nsISupports
* and ECMA402 Intl APIs,
*
* Example: ["en-US", "de", "pl", "sr-Cyrl", "zh-Hans-HK"]
*
* (See OSPreferences.h for a more C++-friendly version of this.)
*/
void getRegionalPrefsLocales([optional] out unsigned long aCount,
[retval, array, size_is(aCount)] out string aOutArray);
readonly attribute Array<ACString> regionalPrefsLocales;
/**
* Returns the best locale that the host environment is localized to.
@ -64,7 +58,7 @@ interface mozIOSPreferences : nsISupports
* The result is a valid locale ID and it should be
* used for all APIs that do not handle language negotiation.
*
* In any scenario involving language negotiation, GetSystemLocales should
* In any scenario involving language negotiation, systemLocales should
* be preferred over the single value.
*
* Example: "zh-Hans-HK"

Просмотреть файл

@ -65,8 +65,8 @@ nsLanguageAtomService::GetLocaleLanguage()
do {
if (!mLocaleLanguage) {
AutoTArray<nsCString, 10> regionalPrefsLocales;
if (OSPreferences::GetInstance()->GetRegionalPrefsLocales(
regionalPrefsLocales)) {
if (NS_SUCCEEDED(OSPreferences::GetInstance()->GetRegionalPrefsLocales(
regionalPrefsLocales))) {
// use lowercase for all language atoms
ToLowerCase(regionalPrefsLocales[0]);
mLocaleLanguage = NS_Atomize(regionalPrefsLocales[0]);

Просмотреть файл

@ -19,7 +19,7 @@ using namespace mozilla::intl;
*/
TEST(Intl_Locale_OSPreferences, GetSystemLocales) {
nsTArray<nsCString> systemLocales;
ASSERT_TRUE(OSPreferences::GetInstance()->GetSystemLocales(systemLocales));
ASSERT_TRUE(NS_SUCCEEDED(OSPreferences::GetInstance()->GetSystemLocales(systemLocales)));
ASSERT_FALSE(systemLocales.IsEmpty());
}
@ -34,7 +34,7 @@ TEST(Intl_Locale_OSPreferences, GetSystemLocales) {
*/
TEST(Intl_Locale_OSPreferences, GetRegionalPrefsLocales) {
nsTArray<nsCString> rgLocales;
ASSERT_TRUE(OSPreferences::GetInstance()->GetRegionalPrefsLocales(rgLocales));
ASSERT_TRUE(NS_SUCCEEDED(OSPreferences::GetInstance()->GetRegionalPrefsLocales(rgLocales)));
ASSERT_FALSE(rgLocales.IsEmpty());
}

Просмотреть файл

@ -11,13 +11,13 @@ function run_test()
const systemLocale = osprefs.systemLocale;
Assert.ok(systemLocale != "", "systemLocale is non-empty");
const systemLocales = osprefs.getSystemLocales();
const systemLocales = osprefs.systemLocales;
Assert.ok(Array.isArray(systemLocales), "systemLocales returns an array");
Assert.ok(systemLocale == systemLocales[0],
"systemLocale matches first entry in systemLocales");
const rgLocales = osprefs.getRegionalPrefsLocales();
const rgLocales = osprefs.regionalPrefsLocales;
Assert.ok(Array.isArray(rgLocales), "regionalPrefsLocales returns an array");
const getDateTimePatternTests = [

Просмотреть файл

@ -625,8 +625,8 @@ var dataProviders = {
defaultLocale: Services.locale.defaultLocale,
},
osPrefs: {
systemLocales: osPrefs.getSystemLocales(),
regionalPrefsLocales: osPrefs.getRegionalPrefsLocales(),
systemLocales: osPrefs.systemLocales,
regionalPrefsLocales: osPrefs.regionalPrefsLocales,
},
});
},

Просмотреть файл

@ -534,13 +534,8 @@ class AddonInternal {
}
async updateBlocklistState(options = {}) {
let {applySoftBlock = true, oldAddon = null, updateDatabase = true} = options;
let {applySoftBlock = true, updateDatabase = true} = options;
if (oldAddon) {
this.userDisabled = oldAddon.userDisabled;
this.softDisabled = oldAddon.softDisabled;
this.blocklistState = oldAddon.blocklistState;
}
let oldState = this.blocklistState;
let entry = await this.findBlocklistEntry();
@ -685,6 +680,14 @@ class AddonInternal {
return permissions;
}
propagateDisabledState(oldAddon) {
if (oldAddon) {
this.userDisabled = oldAddon.userDisabled;
this.softDisabled = oldAddon.softDisabled;
this.blocklistState = oldAddon.blocklistState;
}
}
}
/**

Просмотреть файл

@ -829,7 +829,8 @@ var loadManifest = async function(aPackage, aLocation, aOldAddon) {
}
}
await addon.updateBlocklistState({oldAddon: aOldAddon});
addon.propagateDisabledState(aOldAddon);
await addon.updateBlocklistState();
addon.appDisabled = !XPIDatabase.isUsableAddon(addon);
defineSyncGUID(addon);
@ -1705,7 +1706,7 @@ class AddonInstall {
/**
* Installs the add-on into the install location.
*/
startInstall() {
async startInstall() {
this.state = AddonManager.STATE_INSTALLING;
if (!this._callInstallListeners("onInstallStarted")) {
this.state = AddonManager.STATE_DOWNLOADED;
@ -1726,6 +1727,19 @@ class AddonInstall {
}
}
// Reinstall existing user-disabled addon (of the same installed version).
// If addon is marked to be uninstalled - don't reinstall it.
if (this.existingAddon &&
this.existingAddon.location === this.location &&
this.existingAddon.version === this.addon.version &&
this.existingAddon.userDisabled &&
!this.existingAddon.pendingUninstall) {
await XPIDatabase.updateAddonDisabledState(this.existingAddon, false);
this.state = AddonManager.STATE_INSTALLED;
this._callInstallListeners("onInstallEnded", this.existingAddon.wrapper);
return;
}
let isUpgrade = this.existingAddon &&
this.existingAddon.location == this.location;
@ -1736,7 +1750,7 @@ class AddonInstall {
let stagedAddon = this.location.installer.getStagingDir();
(async () => {
try {
await this.location.installer.requestStagingDir();
// remove any previously staged files
@ -1767,8 +1781,7 @@ class AddonInstall {
this.addon.visible = true;
if (isUpgrade) {
this.addon = XPIDatabase.updateAddonMetadata(this.existingAddon, this.addon,
file.path);
this.addon = XPIDatabase.updateAddonMetadata(this.existingAddon, this.addon, file.path);
let state = this.location.get(this.addon.id);
if (state) {
state.syncWithDB(this.addon, true);
@ -1813,7 +1826,7 @@ class AddonInstall {
})();
await this._startupPromise;
})().catch((e) => {
} catch (e) {
logger.warn(`Failed to install ${this.file.path} from ${this.sourceURI.spec} to ${stagedAddon.path}`, e);
if (stagedAddon.exists())
@ -1824,10 +1837,10 @@ class AddonInstall {
AddonManagerPrivate.callAddonListeners("onOperationCancelled",
this.addon.wrapper);
this._callInstallListeners("onInstallFailed");
}).then(() => {
} finally {
this.removeTemporaryFile();
return this.location.installer.releaseStagingDir();
});
this.location.installer.releaseStagingDir();
}
}
/**
@ -2003,7 +2016,8 @@ var LocalAddonInstall = class extends AddonInstall {
let addon = await XPIDatabase.getVisibleAddonForID(this.addon.id);
this.existingAddon = addon;
await this.addon.updateBlocklistState({oldAddon: this.existingAddon});
this.addon.propagateDisabledState(this.existingAddon);
await this.addon.updateBlocklistState();
this.addon.updateDate = Date.now();
this.addon.installDate = addon ? addon.installDate : this.addon.updateDate;
@ -2398,7 +2412,8 @@ var DownloadAddonInstall = class extends AddonInstall {
} else {
this.addon.installDate = this.addon.updateDate;
}
await this.addon.updateBlocklistState({oldAddon: this.existingAddon});
this.addon.propagateDisabledState(this.existingAddon);
await this.addon.updateBlocklistState();
if (this._callInstallListeners("onDownloadEnded")) {
// If a listener changed our state then do not proceed with the install

Просмотреть файл

@ -0,0 +1,189 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
const ID = "test_addon@tests.mozilla.org";
const ADDONS = {
test_install1_1: {
name: "Test 1 Addon",
description: "Test 1 addon description",
manifest_version: 2,
version: "1.0",
applications: {
gecko: {
id: ID,
},
},
},
test_install1_2: {
name: "Test 1 Addon",
description: "Test 1 addon description",
manifest_version: 2,
version: "2.0",
applications: {
gecko: {
id: ID,
},
},
},
};
add_task(async function setup() {
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
await promiseStartupManager();
});
// User intentionally reinstalls existing disabled addon of the same version.
// No onInstalling nor onInstalled are fired.
add_task(async function reinstallExistingDisabledAddonSameVersion() {
prepare_test({
[ID]: [
["onInstalling", false],
"onInstalled",
],
}, [
"onNewInstall",
"onInstallStarted",
"onInstallEnded",
]);
const xpi = AddonTestUtils.createTempWebExtensionFile({manifest: ADDONS.test_install1_1});
let install = await AddonManager.getInstallForFile(xpi);
await install.install();
ensure_test_completed();
let addon = await promiseAddonByID(ID);
notEqual(addon, null);
equal(addon.pendingOperations, AddonManager.PENDING_NONE);
ok(addon.isActive);
ok(!addon.userDisabled);
prepare_test({
[ID]: [
["onDisabling", false],
"onDisabled",
],
});
await addon.disable();
ensure_test_completed();
addon = await promiseAddonByID(ID);
notEqual(addon, null);
equal(addon.pendingOperations, AddonManager.PENDING_NONE);
ok(!addon.isActive);
ok(addon.userDisabled);
prepare_test({
[ID]: [
["onEnabling", false],
"onEnabled",
],
}, [
"onNewInstall",
"onInstallStarted",
"onInstallEnded",
]);
const xpi2 = AddonTestUtils.createTempWebExtensionFile({manifest: ADDONS.test_install1_1});
install = await AddonManager.getInstallForFile(xpi2);
await install.install();
ensure_test_completed();
addon = await promiseAddonByID(ID);
notEqual(addon, null);
equal(addon.pendingOperations, AddonManager.PENDING_NONE);
ok(addon.isActive);
ok(!addon.userDisabled);
prepare_test({
[ID]: [
["onUninstalling", false],
"onUninstalled",
],
});
await addon.uninstall();
ensure_test_completed();
addon = await promiseAddonByID(ID);
equal(addon, null);
await promiseRestartManager();
});
// User intentionally reinstalls existing disabled addon of different version,
// but addon *still should be disabled*.
add_task(async function reinstallExistingDisabledAddonDifferentVersion() {
prepare_test({
[ID]: [
["onInstalling", false],
"onInstalled",
],
}, [
"onNewInstall",
"onInstallStarted",
"onInstallEnded",
]);
const xpi = AddonTestUtils.createTempWebExtensionFile({manifest: ADDONS.test_install1_1});
let install = await AddonManager.getInstallForFile(xpi);
await install.install();
ensure_test_completed();
let addon = await promiseAddonByID(ID);
notEqual(addon, null);
equal(addon.pendingOperations, AddonManager.PENDING_NONE);
ok(addon.isActive);
ok(!addon.userDisabled);
prepare_test({
[ID]: [
["onDisabling", false],
"onDisabled",
],
});
await addon.disable();
ensure_test_completed();
addon = await promiseAddonByID(ID);
notEqual(addon, null);
equal(addon.pendingOperations, AddonManager.PENDING_NONE);
ok(!addon.isActive);
ok(addon.userDisabled);
prepare_test({
[ID]: [
["onInstalling", false],
"onInstalled",
],
}, [
"onNewInstall",
"onInstallStarted",
"onInstallEnded",
]);
let xpi2 = AddonTestUtils.createTempWebExtensionFile({manifest: ADDONS.test_install1_2});
install = await AddonManager.getInstallForFile(xpi2);
await install.install();
ensure_test_completed();
addon = await promiseAddonByID(ID);
notEqual(addon, null);
equal(addon.pendingOperations, AddonManager.PENDING_NONE);
ok(!addon.isActive);
ok(addon.userDisabled);
equal(addon.version, "2.0");
prepare_test({
[ID]: [
["onUninstalling", false],
"onUninstalled",
],
});
await addon.uninstall();
ensure_test_completed();
addon = await promiseAddonByID(ID);
equal(addon, null);
});

Просмотреть файл

@ -184,6 +184,7 @@ skip-if = require_signing
[test_registerchrome.js]
[test_registry.js]
skip-if = os != 'win'
[test_reinstall_disabled_addon.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

Просмотреть файл

@ -293,13 +293,23 @@ public:
// Returns true if this string overlaps with the given string fragment.
bool IsDependentOn(const char_type* aStart, const char_type* aEnd) const
{
// If it _isn't_ the case that one fragment starts after the other ends,
// or ends before the other starts, then, they conflict:
//
// !(f2.begin >= f1.aEnd || f2.aEnd <= f1.begin)
//
// Simplified, that gives us:
return (aStart < (mData + mLength) && aEnd > mData);
// If it _isn't_ the case that one fragment starts after the other ends,
// or ends before the other starts, then, they conflict:
//
// !(f2.begin >= f1.aEnd || f2.aEnd <= f1.begin)
//
// Simplified, that gives us (To avoid relying on Undefined Behavior
// from comparing pointers from different allocations (which in
// principle gives the optimizer the permission to assume elsewhere
// that the pointers are from the same allocation), the comparisons
// are done on integers, which merely relies on implementation-defined
// behavior of converting pointers to integers. std::less and
// std::greater implementations don't actually provide the guarantees
// that they should.):
return (reinterpret_cast<uintptr_t>(aStart) <
reinterpret_cast<uintptr_t>(mData + mLength) &&
reinterpret_cast<uintptr_t>(aEnd) >
reinterpret_cast<uintptr_t>(mData));
}
protected: