Bug 1669538: Expose reason for Fission enablement decision in nsIXULRuntime. r=nika

Differential Revision: https://phabricator.services.mozilla.com/D92676
This commit is contained in:
Kris Maglione 2020-10-07 18:40:35 +00:00
Родитель ca0617ab87
Коммит 00b133dff8
5 изменённых файлов: 266 добавлений и 87 удалений

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

@ -248,6 +248,9 @@ var dataProviders = {
data.launcherProcessState = Services.appinfo.launcherProcessState;
} catch (e) {}
data.fissionAutoStart = Services.appinfo.fissionAutostart;
data.fissionDecisionStatus = Services.appinfo.fissionDecisionStatusString;
data.remoteAutoStart = Services.appinfo.browserTabsRemoteAutostart;
try {

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

@ -181,6 +181,12 @@ const SNAPSHOT_SCHEMA = {
autoStartStatus: {
type: "number",
},
fissionAutoStart: {
type: "boolean",
},
fissionDecisionStatus: {
type: "string",
},
numTotalWindows: {
type: "number",
},

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

@ -500,6 +500,85 @@ static nsIXULRuntime::ExperimentStatus gFissionExperimentStatus =
nsIXULRuntime::eExperimentStatusUnenrolled;
static bool gFissionAutostart = false;
static bool gFissionAutostartInitialized = false;
static nsIXULRuntime::FissionDecisionStatus gFissionDecisionStatus;
static bool gBrowserTabsRemoteAutostart = false;
static uint64_t gBrowserTabsRemoteStatus = 0;
static bool gBrowserTabsRemoteAutostartInitialized = false;
// TODO: Remove this when fissionDecisionStatus is exposed in about:support.
// If you add anything to this enum, please update about:support to reflect it
enum {
// kE10sEnabledByUser = 0, removed when ending non-e10s support
kE10sEnabledByDefault = 1,
kE10sDisabledByUser = 2,
// kE10sDisabledInSafeMode = 3, was removed in bug 1172491.
// kE10sDisabledForAccessibility = 4,
// kE10sDisabledForMacGfx = 5, was removed in bug 1068674.
// kE10sDisabledForBidi = 6, removed in bug 1309599
// kE10sDisabledForAddons = 7, removed in bug 1406212
kE10sForceDisabled = 8,
// kE10sDisabledForXPAcceleration = 9, removed in bug 1296353
// kE10sDisabledForOperatingSystem = 10, removed due to xp-eol
};
namespace mozilla {
bool BrowserTabsRemoteAutostart() {
if (gBrowserTabsRemoteAutostartInitialized) {
return gBrowserTabsRemoteAutostart;
}
gBrowserTabsRemoteAutostartInitialized = true;
// If we're not in the parent process, we are running E10s.
if (!XRE_IsParentProcess()) {
gBrowserTabsRemoteAutostart = true;
return gBrowserTabsRemoteAutostart;
}
#if defined(MOZILLA_OFFICIAL) && MOZ_BUILD_APP_IS_BROWSER
bool allowSingleProcessOutsideAutomation = false;
#else
bool allowSingleProcessOutsideAutomation = true;
#endif
int status = kE10sEnabledByDefault;
// We use "are non-local connections disabled" as a proxy for
// "are we running some kind of automated test". It would be nicer to use
// xpc::IsInAutomation(), but that depends on some prefs being set, which
// they are not in (at least) gtests (where we can't) and xpcshell.
// Long-term, hopefully we can make tests switch to environment variables
// to disable e10s and then we can get rid of this.
if (allowSingleProcessOutsideAutomation ||
xpc::AreNonLocalConnectionsDisabled()) {
bool optInPref =
Preferences::GetBool("browser.tabs.remote.autostart", true);
if (optInPref) {
gBrowserTabsRemoteAutostart = true;
} else {
status = kE10sDisabledByUser;
}
} else {
gBrowserTabsRemoteAutostart = true;
}
// Uber override pref for emergency blocking
if (gBrowserTabsRemoteAutostart) {
const char* forceDisable = PR_GetEnv("MOZ_FORCE_DISABLE_E10S");
// The environment variable must match the application version to apply.
if (forceDisable && gAppData && !strcmp(forceDisable, gAppData->version)) {
gBrowserTabsRemoteAutostart = false;
status = kE10sForceDisabled;
}
}
gBrowserTabsRemoteStatus = status;
return gBrowserTabsRemoteAutostart;
}
} // namespace mozilla
static bool FissionExperimentEnrolled() {
MOZ_ASSERT(XRE_IsParentProcess());
@ -570,14 +649,37 @@ static void EnsureFissionAutostartInitialized() {
PrefValueKind::Default);
}
if (gSafeMode) {
if (!BrowserTabsRemoteAutostart()) {
gFissionAutostart = false;
if (gBrowserTabsRemoteStatus == kE10sForceDisabled) {
gFissionDecisionStatus = nsIXULRuntime::eFissionDisabledByE10sEnv;
} else {
gFissionDecisionStatus = nsIXULRuntime::eFissionDisabledByE10sOther;
}
} else if (gSafeMode) {
gFissionAutostart = false;
gFissionDecisionStatus = nsIXULRuntime::eFissionDisabledBySafeMode;
} else if (EnvHasValue("MOZ_FORCE_ENABLE_FISSION")) {
gFissionAutostart = true;
gFissionDecisionStatus = nsIXULRuntime::eFissionEnabledByEnv;
} else {
// NOTE: This will take into account changes to the default due to
// `InitializeFissionExperimentStatus`.
gFissionAutostart = Preferences::GetBool(kPrefFissionAutostart, false);
if (gFissionExperimentStatus == nsIXULRuntime::eExperimentStatusControl) {
gFissionDecisionStatus = nsIXULRuntime::eFissionExperimentControl;
} else if (gFissionExperimentStatus ==
nsIXULRuntime::eExperimentStatusTreatment) {
gFissionDecisionStatus = nsIXULRuntime::eFissionExperimentTreatment;
} else if (Preferences::HasUserValue(kPrefFissionAutostart)) {
gFissionDecisionStatus = gFissionAutostart
? nsIXULRuntime::eFissionEnabledByUserPref
: nsIXULRuntime::eFissionDisabledByUserPref;
} else {
gFissionDecisionStatus = gFissionAutostart
? nsIXULRuntime::eFissionEnabledByDefault
: nsIXULRuntime::eFissionDisabledByDefault;
}
}
// Content processes cannot run the same logic as we're running in the parent
@ -917,13 +1019,10 @@ nsXULAppInfo::GetLastAppBuildID(nsACString& aResult) {
return NS_OK;
}
static bool gBrowserTabsRemoteAutostart = false;
static uint64_t gBrowserTabsRemoteStatus = 0;
static bool gBrowserTabsRemoteAutostartInitialized = false;
NS_IMETHODIMP
nsXULAppInfo::Observe(nsISupports* aSubject, const char* aTopic,
const char16_t* aData) {
// TODO: Remove this when fissionDecisionStatus is exposed in about:support.
if (!nsCRT::strcmp(aTopic, "getE10SBlocked")) {
nsCOMPtr<nsISupportsPRUint64> ret = do_QueryInterface(aSubject);
if (!ret) return NS_ERROR_FAILURE;
@ -948,10 +1047,67 @@ nsXULAppInfo::GetFissionExperimentStatus(ExperimentStatus* aResult) {
}
EnsureFissionAutostartInitialized();
MOZ_ASSERT(gFissionExperimentStatus != eFissionStatusUnknown);
*aResult = gFissionExperimentStatus;
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetFissionDecisionStatus(FissionDecisionStatus* aResult) {
if (!XRE_IsParentProcess()) {
return NS_ERROR_NOT_AVAILABLE;
}
EnsureFissionAutostartInitialized();
*aResult = gFissionDecisionStatus;
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetFissionDecisionStatusString(nsACString& aResult) {
if (!XRE_IsParentProcess()) {
return NS_ERROR_NOT_AVAILABLE;
}
EnsureFissionAutostartInitialized();
switch (gFissionDecisionStatus) {
case eFissionExperimentControl:
aResult = "experimentControl";
break;
case eFissionExperimentTreatment:
aResult = "experimentTreatment";
break;
case eFissionDisabledByE10sEnv:
aResult = "disabledByE10sEnv";
break;
case eFissionEnabledByEnv:
aResult = "enabledByEnv";
break;
case eFissionDisabledBySafeMode:
aResult = "disabledBySafeMode";
break;
case eFissionEnabledByDefault:
aResult = "enabledByDefault";
break;
case eFissionDisabledByDefault:
aResult = "disabledByDefault";
break;
case eFissionEnabledByUserPref:
aResult = "enabledByUserPref";
break;
case eFissionDisabledByUserPref:
aResult = "disabledByUserPref";
break;
case eFissionDisabledByE10sOther:
aResult = "disabledByE10sOther";
break;
default:
MOZ_ASSERT_UNREACHABLE("Unexpected enum value");
}
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetSessionHistoryInParent(bool* aResult) {
*aResult = SessionHistoryInParent();
@ -5262,77 +5418,8 @@ bool XRE_UseNativeEventProcessing() {
return true;
}
// If you add anything to this enum, please update about:support to reflect it
enum {
// kE10sEnabledByUser = 0, removed when ending non-e10s support
kE10sEnabledByDefault = 1,
kE10sDisabledByUser = 2,
// kE10sDisabledInSafeMode = 3, was removed in bug 1172491.
// kE10sDisabledForAccessibility = 4,
// kE10sDisabledForMacGfx = 5, was removed in bug 1068674.
// kE10sDisabledForBidi = 6, removed in bug 1309599
// kE10sDisabledForAddons = 7, removed in bug 1406212
kE10sForceDisabled = 8,
// kE10sDisabledForXPAcceleration = 9, removed in bug 1296353
// kE10sDisabledForOperatingSystem = 10, removed due to xp-eol
};
namespace mozilla {
bool BrowserTabsRemoteAutostart() {
if (gBrowserTabsRemoteAutostartInitialized) {
return gBrowserTabsRemoteAutostart;
}
gBrowserTabsRemoteAutostartInitialized = true;
// If we're not in the parent process, we are running E10s.
if (!XRE_IsParentProcess()) {
gBrowserTabsRemoteAutostart = true;
return gBrowserTabsRemoteAutostart;
}
#if defined(MOZILLA_OFFICIAL) && MOZ_BUILD_APP_IS_BROWSER
bool allowSingleProcessOutsideAutomation = false;
#else
bool allowSingleProcessOutsideAutomation = true;
#endif
int status = kE10sEnabledByDefault;
// We use "are non-local connections disabled" as a proxy for
// "are we running some kind of automated test". It would be nicer to use
// xpc::IsInAutomation(), but that depends on some prefs being set, which
// they are not in (at least) gtests (where we can't) and xpcshell.
// Long-term, hopefully we can make tests switch to environment variables
// to disable e10s and then we can get rid of this.
if (allowSingleProcessOutsideAutomation ||
xpc::AreNonLocalConnectionsDisabled()) {
bool optInPref =
Preferences::GetBool("browser.tabs.remote.autostart", true);
if (optInPref) {
gBrowserTabsRemoteAutostart = true;
} else {
status = kE10sDisabledByUser;
}
} else {
gBrowserTabsRemoteAutostart = true;
}
// Uber override pref for emergency blocking
if (gBrowserTabsRemoteAutostart) {
const char* forceDisable = PR_GetEnv("MOZ_FORCE_DISABLE_E10S");
// The environment variable must match the application version to apply.
if (forceDisable && gAppData && !strcmp(forceDisable, gAppData->version)) {
gBrowserTabsRemoteAutostart = false;
status = kE10sForceDisabled;
}
}
gBrowserTabsRemoteStatus = status;
return gBrowserTabsRemoteAutostart;
}
uint32_t GetMaxWebProcessCount() {
// multiOptOut is in int to allow us to run multiple experiments without
// introducing multiple prefs a la the autostart.N prefs.

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

@ -18,6 +18,21 @@ class Prefs:
ENV_ENABLE_FISSION = 'MOZ_FORCE_ENABLE_FISSION'
ENV_DISABLE_E10S = 'MOZ_FORCE_DISABLE_E10S'
DECISION_STATUS = {
'experimentControl': 1,
'experimentTreatment': 2,
'disabledByE10sEnv': 3,
'enabledByEnv': 4,
'disabledBySafeMode': 5,
'enabledByDefault': 6,
'disabledByDefault': 7,
'enabledByUserPref': 8,
'disabledByUserPref': 9,
'disabledByE10sOther': 10,
}
class TestFissionAutostart(MarionetteTestCase):
@ -36,19 +51,23 @@ class TestFissionAutostart(MarionetteTestCase):
return {
fissionAutostart: Services.appinfo.fissionAutostart,
fissionExperimentStatus: Services.appinfo.fissionExperimentStatus,
decisionStatus: Services.appinfo.fissionDecisionStatus,
decisionStatusString: Services.appinfo.fissionDecisionStatusString,
useRemoteSubframes: win.docShell.nsILoadContext.useRemoteSubframes,
fissionAutostartSession: Services.prefs.getBoolPref("fission.autostart.session"),
dynamicFissionAutostart: Services.prefs.getBoolPref("fission.autostart"),
};
''')
def check_fission_status(self, enabled, experiment, dynamic=None):
def check_fission_status(self, enabled, experiment, decision, dynamic=None):
if dynamic is None:
dynamic = enabled
expected = {
'fissionAutostart': enabled,
'fissionExperimentStatus': experiment,
'decisionStatus': DECISION_STATUS[decision],
'decisionStatusString': decision,
'useRemoteSubframes': enabled,
'fissionAutostartSession': enabled,
'dynamicFissionAutostart': dynamic,
@ -154,41 +173,49 @@ class TestFissionAutostart(MarionetteTestCase):
return
self.check_fission_status(enabled=False,
experiment=ExperimentStatus.UNENROLLED)
experiment=ExperimentStatus.UNENROLLED,
decision='disabledByDefault')
self.restart(prefs={Prefs.FISSION_AUTOSTART: True})
self.check_fission_status(enabled=True,
experiment=ExperimentStatus.UNENROLLED)
experiment=ExperimentStatus.UNENROLLED,
decision='enabledByUserPref')
self.set_enrollment_status(ExperimentStatus.ENROLLED_CONTROL)
self.check_fission_status(enabled=True,
experiment=ExperimentStatus.UNENROLLED)
experiment=ExperimentStatus.UNENROLLED,
decision='enabledByUserPref')
self.marionette.set_pref(Prefs.FISSION_AUTOSTART,
False)
self.check_fission_status(enabled=True,
experiment=ExperimentStatus.UNENROLLED,
decision='enabledByUserPref',
dynamic=False)
self.marionette.clear_pref(Prefs.FISSION_AUTOSTART)
self.check_fission_status(enabled=True,
experiment=ExperimentStatus.UNENROLLED,
decision='enabledByUserPref',
dynamic=False)
self.restart()
self.check_fission_status(enabled=False,
experiment=ExperimentStatus.ENROLLED_CONTROL)
experiment=ExperimentStatus.ENROLLED_CONTROL,
decision='experimentControl')
self.marionette.set_pref(Prefs.ENROLLMENT_STATUS,
ExperimentStatus.UNENROLLED,
default_branch=True)
self.check_fission_status(enabled=False,
experiment=ExperimentStatus.ENROLLED_CONTROL)
experiment=ExperimentStatus.ENROLLED_CONTROL,
decision='experimentControl')
self.set_env(ENV_ENABLE_FISSION, '1')
self.check_fission_status(enabled=False,
experiment=ExperimentStatus.ENROLLED_CONTROL)
experiment=ExperimentStatus.ENROLLED_CONTROL,
decision='experimentControl')
def test_fission_precedence(self):
if self.check_pref_locked():
@ -196,36 +223,43 @@ class TestFissionAutostart(MarionetteTestCase):
return
self.check_fission_status(enabled=False,
experiment=ExperimentStatus.UNENROLLED)
experiment=ExperimentStatus.UNENROLLED,
decision='disabledByDefault')
self.restart(prefs={Prefs.FISSION_AUTOSTART: False},
env={ENV_ENABLE_FISSION: '1'})
self.check_fission_status(enabled=True,
experiment=ExperimentStatus.UNENROLLED,
decision='enabledByEnv',
dynamic=False)
self.restart(prefs={Prefs.FISSION_AUTOSTART: True},
env={ENV_ENABLE_FISSION: ''})
self.check_fission_status(enabled=True,
experiment=ExperimentStatus.UNENROLLED)
experiment=ExperimentStatus.UNENROLLED,
decision='enabledByUserPref')
self.restart(prefs={Prefs.FISSION_AUTOSTART: None})
self.check_fission_status(enabled=False,
experiment=ExperimentStatus.UNENROLLED)
experiment=ExperimentStatus.UNENROLLED,
decision='disabledByDefault')
self.set_enrollment_status(ExperimentStatus.ENROLLED_TREATMENT)
self.restart()
self.check_fission_status(enabled=True,
experiment=ExperimentStatus.ENROLLED_TREATMENT)
experiment=ExperimentStatus.ENROLLED_TREATMENT,
decision='experimentTreatment')
self.set_enrollment_status(ExperimentStatus.ENROLLED_CONTROL)
self.restart()
self.check_fission_status(enabled=False,
experiment=ExperimentStatus.ENROLLED_CONTROL)
experiment=ExperimentStatus.ENROLLED_CONTROL,
decision='experimentControl')
self.marionette.set_pref(Prefs.FISSION_AUTOSTART, True)
self.check_fission_status(enabled=False,
experiment=ExperimentStatus.ENROLLED_CONTROL,
decision='experimentControl',
dynamic=True)
self.assertEqual(self.marionette.get_pref(Prefs.ENROLLMENT_STATUS),
@ -234,4 +268,12 @@ class TestFissionAutostart(MarionetteTestCase):
self.restart()
self.check_fission_status(enabled=True,
experiment=ExperimentStatus.DISQUALIFIED)
experiment=ExperimentStatus.DISQUALIFIED,
decision='enabledByUserPref')
app_version = self.execute_script('return Services.appinfo.version')
self.restart(env={ENV_DISABLE_E10S: app_version})
self.check_fission_status(enabled=False,
experiment=ExperimentStatus.DISQUALIFIED,
decision='disabledByE10sEnv',
dynamic=True)

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

@ -63,6 +63,39 @@ interface nsIXULRuntime : nsISupports
eExperimentStatusCount,
};
cenum FissionDecisionStatus : 8 {
eFissionStatusUnknown = 0,
// Fission is disabled because the user is in the control group of a
// Normandy experiment.
eFissionExperimentControl = 1,
// Fission is enabled because the user is in the treatment group of a
// Normandy experiment.
eFissionExperimentTreatment = 2,
// Fission is disabled because the `MOZ_FORCE_DISABLE_E10S` environment
// variable is set.
eFissionDisabledByE10sEnv = 3,
// Fission is enabled because the `MOZ_FORCE_ENABLE_FISSION` environment
// variable is set.
eFissionEnabledByEnv = 4,
// Fission is disabled because the current session is running in safe
// mode.
eFissionDisabledBySafeMode = 5,
// Fission is enabled because the "fission.autostart" preference is true
// by default.
eFissionEnabledByDefault = 6,
// Fission is disabled because the "fission.autostart" preference is false
// by default.
eFissionDisabledByDefault = 7,
// Fission is enabled because the "fission.autostart" preference was
// turned on by the user.
eFissionEnabledByUserPref = 8,
// Fission is enabled because the "fission.autostart" preference was
// turned on by the user.
eFissionDisabledByUserPref = 9,
// Fission is disabled because e10s is disabled for some other reason.
eFissionDisabledByE10sOther = 10,
};
/**
* Whether Fission should be automatically enabled for new browser windows.
* This may not match the value of the 'fission.autostart' pref.
@ -83,6 +116,14 @@ interface nsIXULRuntime : nsISupports
*/
readonly attribute nsIXULRuntime_ExperimentStatus fissionExperimentStatus;
/**
* The deciding factor which caused Fission to be enabled or disabled in
* this session. The string version is the same of the name of the constant,
* without the leading `eFission`, and with an initial lower-case letter.
*/
readonly attribute nsIXULRuntime_FissionDecisionStatus fissionDecisionStatus;
readonly attribute ACString fissionDecisionStatusString;
/**
* Whether session history is stored in the parent process.
*/