зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to inbound a=merge on a CLOSED TREE
This commit is contained in:
Коммит
68a73ded70
|
@ -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:
|
||||
|
|
Загрузка…
Ссылка в новой задаче