Bug 1234675 - Ability to disable e10s for users with addons. r=Mossop

This commit is contained in:
Gabor Krizsanits 2016-01-22 10:10:17 +01:00
parent b8de4eedc3
commit a9c6984669
4 changed files with 219 additions and 15 deletions

View File

@ -4239,6 +4239,33 @@ this.XPIProvider = {
}
},
/**
* 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) {
// Only extensions change behaviour
if (aAddon.type != "extension")
return false;
// The hotfix is exempt
let hotfixID = Preferences.get(PREF_EM_HOTFIX_ID, undefined);
if (hotfixID && hotfixID == aAddon.id)
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;
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
@ -4257,21 +4284,7 @@ this.XPIProvider = {
if (!Services.appinfo.browserTabsRemoteAutostart)
return false;
// Only extensions change behaviour
if (aAddon.type != "extension")
return false;
// The hotfix is exempt
let hotfixID = Preferences.get(PREF_EM_HOTFIX_ID, undefined);
if (hotfixID && hotfixID == aAddon.id)
return false;
// System add-ons are exempt
if (aAddon._installLocation.name == KEY_APP_SYSTEM_DEFAULTS ||
aAddon._installLocation.name == KEY_APP_SYSTEM_ADDONS)
return false;
return true;
return this.isBlockingE10s(aAddon);
},
/**

View File

@ -48,6 +48,7 @@ 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 KEY_APP_PROFILE = "app-profile";
const KEY_APP_SYSTEM_ADDONS = "app-system-addons";
@ -460,6 +461,7 @@ this.XPIDatabase = {
ASYNC_SAVE_DELAY_MS);
}
this.updateAddonsBlockingE10s();
let promise = this._deferredSave.saveChanges();
if (!this._schemaVersionSet) {
this._schemaVersionSet = true;
@ -1389,6 +1391,17 @@ this.XPIDatabase = {
this.saveChanges();
},
updateAddonsBlockingE10s: function() {
let blockE10s = false;
for (let [, addon] of this.addonDB) {
let active = (addon.visible && !addon.disabled && !addon.pendingUninstall);
if (active && XPIProvider.isBlockingE10s(addon))
blockE10s = true;
}
Preferences.set(PREF_E10S_BLOCKED_BY_ADDONS, blockE10s);
},
/**
* Synchronously calculates and updates all the active flags in the database.
*/

View File

@ -3,6 +3,7 @@
*/
const ID = "bootstrap1@tests.mozilla.org";
const ID2 = "bootstrap2@tests.mozilla.org";
BootstrapMonitor.init();
@ -115,6 +116,170 @@ add_task(function*() {
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);
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);
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);
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);
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();
});
// The hotfix is unaffected
add_task(function*() {
gAppInfo.browserTabsRemoteAutostart = true;

View File

@ -4652,6 +4652,7 @@ enum {
kE10sDisabledForAccessibility = 4,
kE10sDisabledForMacGfx = 5,
kE10sDisabledForBidi = 6,
kE10sDisabledForAddons = 7,
};
#ifdef XP_WIN
@ -4760,6 +4761,15 @@ mozilla::BrowserTabsRemoteAutostart()
gfxPrefs::GetSingleton().LayersOffMainThreadCompositionTestingEnabled();
#endif
bool addonsCanDisable = Preferences::GetBool("extensions.e10sBlocksEnabling", false);
bool disabledByAddons = Preferences::GetBool("extensions.e10sBlockedByAddons", false);
#ifdef MOZ_CRASHREPORTER
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("AddonsShouldHaveBlockedE10s"),
disabledByAddons ? NS_LITERAL_CSTRING("1")
: NS_LITERAL_CSTRING("0"));
#endif
if (e10sAllowed && prefEnabled) {
if (disabledForA11y) {
status = kE10sDisabledForAccessibility;
@ -4767,6 +4777,9 @@ mozilla::BrowserTabsRemoteAutostart()
} else if (disabledForBidi) {
status = kE10sDisabledForBidi;
LogE10sBlockedReason("Disabled for RTL locales due to broken bidi detection.");
} else if (addonsCanDisable && disabledByAddons) {
status = kE10sDisabledForAddons;
LogE10sBlockedReason("3rd party add-ons are installed and enabled.");
} else {
gBrowserTabsRemoteAutostart = true;
}