Commit 494dcbfa authored by Sebastien Marchand's avatar Sebastien Marchand Committed by Commit Bot

Add a feature flag to disable the proactive discarding protections

Bug: 876348
Change-Id: Ib932652af7814f421009be79a7e9a1e5413fffd7
Reviewed-on: https://chromium-review.googlesource.com/c/1228505
Commit-Queue: Sébastien Marchand <sebmarchand@chromium.org>
Reviewed-by: default avatarChris Hamilton <chrisha@chromium.org>
Cr-Commit-Position: refs/heads/master@{#597171}
parent 1959608c
......@@ -1243,11 +1243,22 @@ const FeatureEntry::FeatureParam
{resource_coordinator::
kProactiveTabFreezeAndDiscard_ShouldProactivelyDiscardParam,
"true"}};
const FeatureEntry::FeatureParam
kProactiveTabFreezeAndDiscard_DisableHeuristics[] = {
{resource_coordinator::
kProactiveTabFreezeAndDiscard_ShouldProactivelyDiscardParam,
"true"},
{resource_coordinator::
kProactiveTabFreezeAndDiscard_DisableHeuristicsParam,
"true"}};
const FeatureEntry::FeatureVariation kProactiveTabFreezeAndDiscardVariations[] =
{{"Freeze only", kProactiveTabFreezeAndDiscard_FreezeOnly,
base::size(kProactiveTabFreezeAndDiscard_FreezeOnly), nullptr},
{"Freeze and discard", kProactiveTabFreezeAndDiscard_FreezeAndDiscard,
base::size(kProactiveTabFreezeAndDiscard_FreezeAndDiscard), nullptr}};
base::size(kProactiveTabFreezeAndDiscard_FreezeAndDiscard), nullptr},
{"Freeze and discard, heuristics disabled",
kProactiveTabFreezeAndDiscard_DisableHeuristics,
base::size(kProactiveTabFreezeAndDiscard_DisableHeuristics), nullptr}};
#endif
const FeatureEntry::FeatureParam kGamepadPollingRate100Hz[] = {
......
......@@ -513,30 +513,19 @@ bool TabLifecycleUnitSource::TabLifecycleUnit::CanFreeze(
return false;
}
if (!GetTabSource()->tab_lifecycles_enterprise_policy()) {
decision_details->AddReason(
DecisionFailureReason::LIFECYCLES_ENTERPRISE_POLICY_OPT_OUT);
}
bool check_heuristics = !GetStaticProactiveTabFreezeAndDiscardParams()
.disable_heuristics_protections;
auto intervention_policy =
GetTabSource()->intervention_policy_database()->GetFreezingPolicy(
url::Origin::Create(web_contents()->GetLastCommittedURL()));
switch (intervention_policy) {
case OriginInterventions::OPT_IN:
decision_details->AddReason(DecisionSuccessReason::GLOBAL_WHITELIST);
break;
case OriginInterventions::OPT_OUT:
decision_details->AddReason(DecisionFailureReason::GLOBAL_BLACKLIST);
break;
case OriginInterventions::DEFAULT:
break;
}
if (check_heuristics)
CanFreezeHeuristicsChecks(decision_details);
if (web_contents()->GetVisibility() == content::Visibility::VISIBLE)
decision_details->AddReason(DecisionFailureReason::LIVE_STATE_VISIBLE);
CheckIfTabIsUsedInBackground(decision_details, InterventionType::kProactive);
if (check_heuristics) {
CheckIfTabIsUsedInBackground(decision_details,
InterventionType::kProactive);
}
if (decision_details->reasons().empty()) {
decision_details->AddReason(
......@@ -598,31 +587,11 @@ bool TabLifecycleUnitSource::TabLifecycleUnit::CanDiscard(
}
#endif
// We deliberately run through all of the logic without early termination.
// This ensures that the decision details lists all possible reasons that the
// transition can be denied.
if (!GetTabSource()->tab_lifecycles_enterprise_policy()) {
decision_details->AddReason(
DecisionFailureReason::LIFECYCLES_ENTERPRISE_POLICY_OPT_OUT);
}
bool check_heuristics = !GetStaticProactiveTabFreezeAndDiscardParams()
.disable_heuristics_protections;
if (reason == LifecycleUnitDiscardReason::PROACTIVE) {
auto intervention_policy =
GetTabSource()->intervention_policy_database()->GetDiscardingPolicy(
url::Origin::Create(web_contents()->GetLastCommittedURL()));
switch (intervention_policy) {
case OriginInterventions::OPT_IN:
decision_details->AddReason(DecisionSuccessReason::GLOBAL_WHITELIST);
break;
case OriginInterventions::OPT_OUT:
decision_details->AddReason(DecisionFailureReason::GLOBAL_BLACKLIST);
break;
case OriginInterventions::DEFAULT:
break;
}
}
if (check_heuristics)
CanDiscardHeuristicsChecks(decision_details, reason);
#if defined(OS_CHROMEOS)
if (web_contents()->GetVisibility() == content::Visibility::VISIBLE)
......@@ -650,10 +619,12 @@ bool TabLifecycleUnitSource::TabLifecycleUnit::CanDiscard(
DecisionFailureReason::LIVE_STATE_EXTENSION_DISALLOWED);
}
CheckIfTabIsUsedInBackground(decision_details,
reason == LifecycleUnitDiscardReason::PROACTIVE
? InterventionType::kProactive
: InterventionType::kExternalOrUrgent);
if (check_heuristics) {
CheckIfTabIsUsedInBackground(decision_details,
reason == LifecycleUnitDiscardReason::PROACTIVE
? InterventionType::kProactive
: InterventionType::kExternalOrUrgent);
}
if (decision_details->reasons().empty()) {
decision_details->AddReason(
......@@ -980,4 +951,56 @@ void TabLifecycleUnitSource::TabLifecycleUnit::CheckIfTabIsUsedInBackground(
}
}
void TabLifecycleUnitSource::TabLifecycleUnit::CanFreezeHeuristicsChecks(
DecisionDetails* decision_details) const {
if (!GetTabSource()->tab_lifecycles_enterprise_policy()) {
decision_details->AddReason(
DecisionFailureReason::LIFECYCLES_ENTERPRISE_POLICY_OPT_OUT);
}
auto intervention_policy =
GetTabSource()->intervention_policy_database()->GetFreezingPolicy(
url::Origin::Create(web_contents()->GetLastCommittedURL()));
switch (intervention_policy) {
case OriginInterventions::OPT_IN:
decision_details->AddReason(DecisionSuccessReason::GLOBAL_WHITELIST);
break;
case OriginInterventions::OPT_OUT:
decision_details->AddReason(DecisionFailureReason::GLOBAL_BLACKLIST);
break;
case OriginInterventions::DEFAULT:
break;
}
}
void TabLifecycleUnitSource::TabLifecycleUnit::CanDiscardHeuristicsChecks(
DecisionDetails* decision_details,
LifecycleUnitDiscardReason reason) const {
// We deliberately run through all of the logic without early termination.
// This ensures that the decision details lists all possible reasons that
// the transition can be denied.
if (!GetTabSource()->tab_lifecycles_enterprise_policy()) {
decision_details->AddReason(
DecisionFailureReason::LIFECYCLES_ENTERPRISE_POLICY_OPT_OUT);
}
if (reason == LifecycleUnitDiscardReason::PROACTIVE) {
auto intervention_policy =
GetTabSource()->intervention_policy_database()->GetDiscardingPolicy(
url::Origin::Create(web_contents()->GetLastCommittedURL()));
switch (intervention_policy) {
case OriginInterventions::OPT_IN:
decision_details->AddReason(DecisionSuccessReason::GLOBAL_WHITELIST);
break;
case OriginInterventions::OPT_OUT:
decision_details->AddReason(DecisionFailureReason::GLOBAL_BLACKLIST);
break;
case OriginInterventions::DEFAULT:
break;
}
}
}
} // namespace resource_coordinator
......@@ -172,6 +172,18 @@ class TabLifecycleUnitSource::TabLifecycleUnit
void CheckIfTabIsUsedInBackground(DecisionDetails* decision_details,
InterventionType intervention_type) const;
// Runs the freezing heuristics checks on this tab and store the decision
// details in |decision_details|. This doesn't check for potential background
// feature usage.
void CanFreezeHeuristicsChecks(DecisionDetails* decision_details) const;
// Runs the discarding heuristics checks on this tab and store the decision
// details in |decision_details|. If |intervention_type| indicates that
// this is a proactive intervention then more heuristics will be
// applied. This doesn't check for potential background feature usage.
void CanDiscardHeuristicsChecks(DecisionDetails* decision_details,
LifecycleUnitDiscardReason reason) const;
// List of observers to notify when the discarded state or the auto-
// discardable state of this tab changes.
base::ObserverList<TabLifecycleObserver>::Unchecked* observers_;
......
......@@ -832,4 +832,51 @@ TEST_F(TabLifecycleUnitTest, ReloadingAFrozenTabUnfreezeIt) {
EXPECT_NE(LifecycleUnitState::FROZEN, tab_lifecycle_unit.GetState());
}
TEST_F(TabLifecycleUnitTest, DisableHeuristicsFlag) {
TabLifecycleUnit tab_lifecycle_unit(GetSource(), &observers_,
usage_clock_.get(), web_contents_,
tab_strip_model_.get());
TabLoadTracker::Get()->TransitionStateForTesting(web_contents_,
LoadingState::LOADED);
DecisionDetails decision_details;
EXPECT_TRUE(tab_lifecycle_unit.CanFreeze(&decision_details));
EXPECT_TRUE(decision_details.IsPositive());
decision_details.Clear();
EXPECT_TRUE(tab_lifecycle_unit.CanDiscard(
LifecycleUnitDiscardReason::PROACTIVE, &decision_details));
EXPECT_TRUE(decision_details.IsPositive());
decision_details.Clear();
// Use one of the heuristics on the tab to prevent it from being discarded.
InterventionPolicyDatabase* policy_db =
TabLifecycleUnitSource::GetInstance()->intervention_policy_database();
policy_db->AddOriginPoliciesForTesting(
url::Origin::Create(web_contents_->GetLastCommittedURL()),
{OriginInterventions::OPT_OUT, OriginInterventions::OPT_OUT});
EXPECT_FALSE(tab_lifecycle_unit.CanFreeze(&decision_details));
EXPECT_FALSE(decision_details.IsPositive());
decision_details.Clear();
EXPECT_FALSE(tab_lifecycle_unit.CanDiscard(
LifecycleUnitDiscardReason::PROACTIVE, &decision_details));
EXPECT_FALSE(decision_details.IsPositive());
decision_details.Clear();
// Disable the heuristics and check that the tab can now be safely discarded.
GetMutableStaticProactiveTabFreezeAndDiscardParamsForTesting()
->disable_heuristics_protections = true;
EXPECT_TRUE(tab_lifecycle_unit.CanFreeze(&decision_details));
EXPECT_TRUE(decision_details.IsPositive());
decision_details.Clear();
EXPECT_TRUE(tab_lifecycle_unit.CanDiscard(
LifecycleUnitDiscardReason::PROACTIVE, &decision_details));
EXPECT_TRUE(decision_details.IsPositive());
decision_details.Clear();
}
} // namespace resource_coordinator
......@@ -83,6 +83,8 @@ const char kProactiveTabFreezeAndDiscardFeatureName[] =
"ProactiveTabFreezeAndDiscard";
const char kProactiveTabFreezeAndDiscard_ShouldProactivelyDiscardParam[] =
"ShouldProactivelyDiscard";
const char kProactiveTabFreezeAndDiscard_DisableHeuristicsParam[] =
"DisableHeuristicsProtections";
// Instantiate the feature parameters for proactive tab discarding.
constexpr base::FeatureParam<bool>
......@@ -109,6 +111,8 @@ constexpr base::FeatureParam<int>
ProactiveTabFreezeAndDiscardParams::kUnfreezeTimeout;
constexpr base::FeatureParam<int>
ProactiveTabFreezeAndDiscardParams::kRefreezeTimeout;
constexpr base::FeatureParam<bool>
ProactiveTabFreezeAndDiscardParams::kDisableHeuristicsProtections;
// Instantiate the feature parameters for the site characteristics database.
constexpr base::FeatureParam<int>
......@@ -199,6 +203,9 @@ ProactiveTabFreezeAndDiscardParams GetProactiveTabFreezeAndDiscardParams(
params.refreeze_timeout = base::TimeDelta::FromSeconds(
ProactiveTabFreezeAndDiscardParams::kRefreezeTimeout.Get());
params.disable_heuristics_protections =
ProactiveTabFreezeAndDiscardParams::kDisableHeuristicsProtections.Get();
return params;
}
......
......@@ -32,6 +32,10 @@ extern const char kProactiveTabFreezeAndDiscardFeatureName[];
// ProactiveTabFreezeAndDiscard feature.
extern const char kProactiveTabFreezeAndDiscard_ShouldProactivelyDiscardParam[];
// The name of the |DisableHeuristicsProtections| parameter of the
// ProactiveTabFreezeAndDiscard feature.
extern const char kProactiveTabFreezeAndDiscard_DisableHeuristicsParam[];
// Parameters used by the proactive tab discarding feature.
//
// Proactive discarding has 5 key parameters:
......@@ -125,6 +129,10 @@ struct ProactiveTabFreezeAndDiscardParams {
&features::kProactiveTabFreezeAndDiscard, "RefreezeTimeout",
base::TimeDelta::FromMinutes(10).InSeconds()};
static constexpr base::FeatureParam<bool> kDisableHeuristicsProtections{
&features::kProactiveTabFreezeAndDiscard,
kProactiveTabFreezeAndDiscard_DisableHeuristicsParam, false};
// Whether tabs should be proactively discarded. When the
// |kProactiveTabFreezeAndDiscard| feature is enabled and this is false, only
// proactive tab freezing happens.
......@@ -162,6 +170,9 @@ struct ProactiveTabFreezeAndDiscardParams {
base::TimeDelta unfreeze_timeout;
// Amount of time that a tab stays unfrozen before being frozen again.
base::TimeDelta refreeze_timeout;
// Disable all the heuristics protections when doing a freezing or discarding
// intervention.
bool disable_heuristics_protections;
};
// Parameters used by the site characteristics database.
......
......@@ -60,7 +60,8 @@ class TabManagerFeaturesTest : public testing::Test {
base::TimeDelta high_occluded_timeout,
base::TimeDelta freeze_timeout,
base::TimeDelta unfreeze_timeout,
base::TimeDelta refreeze_timeout) {
base::TimeDelta refreeze_timeout,
bool disable_heuristics_protections) {
ProactiveTabFreezeAndDiscardParams params =
GetProactiveTabFreezeAndDiscardParams(memory_in_gb);
......@@ -85,6 +86,9 @@ class TabManagerFeaturesTest : public testing::Test {
EXPECT_EQ(freeze_timeout, params.freeze_timeout);
EXPECT_EQ(unfreeze_timeout, params.unfreeze_timeout);
EXPECT_EQ(refreeze_timeout, params.refreeze_timeout);
EXPECT_EQ(disable_heuristics_protections,
params.disable_heuristics_protections);
}
void ExpectSiteCharacteristicsDatabaseParams(
......@@ -163,8 +167,9 @@ class TabManagerFeaturesTest : public testing::Test {
base::TimeDelta::FromSeconds(
ProactiveTabFreezeAndDiscardParams::kUnfreezeTimeout.default_value),
base::TimeDelta::FromSeconds(
ProactiveTabFreezeAndDiscardParams::kRefreezeTimeout
.default_value));
ProactiveTabFreezeAndDiscardParams::kRefreezeTimeout.default_value),
ProactiveTabFreezeAndDiscardParams::kDisableHeuristicsProtections
.default_value);
}
void ExpectDefaultSiteCharacteristicsDatabaseParams() {
......@@ -245,6 +250,9 @@ TEST_F(TabManagerFeaturesTest,
SetParam(ProactiveTabFreezeAndDiscardParams::kFreezeTimeout.name, "b");
SetParam(ProactiveTabFreezeAndDiscardParams::kUnfreezeTimeout.name, "i");
SetParam(ProactiveTabFreezeAndDiscardParams::kRefreezeTimeout.name, "m");
SetParam(
ProactiveTabFreezeAndDiscardParams::kDisableHeuristicsProtections.name,
"bleh");
EnableProactiveTabFreezeAndDiscard();
ExpectDefaultProactiveTabFreezeAndDiscardParams();
}
......@@ -270,6 +278,9 @@ TEST_F(TabManagerFeaturesTest, GetProactiveTabFreezeAndDiscardParams) {
SetParam(ProactiveTabFreezeAndDiscardParams::kFreezeTimeout.name, "10");
SetParam(ProactiveTabFreezeAndDiscardParams::kUnfreezeTimeout.name, "20");
SetParam(ProactiveTabFreezeAndDiscardParams::kRefreezeTimeout.name, "30");
SetParam(
ProactiveTabFreezeAndDiscardParams::kDisableHeuristicsProtections.name,
"true");
EnableProactiveTabFreezeAndDiscard();
// Should snap |moderate_loaded_tab_count| to |low_loaded_tab_count|, when the
......@@ -280,7 +291,7 @@ TEST_F(TabManagerFeaturesTest, GetProactiveTabFreezeAndDiscardParams) {
true, true, true, 7, 7, 42, memory_in_gb_low,
base::TimeDelta::FromSeconds(60), base::TimeDelta::FromSeconds(120),
base::TimeDelta::FromSeconds(247), base::TimeDelta::FromSeconds(10),
base::TimeDelta::FromSeconds(20), base::TimeDelta::FromSeconds(30));
base::TimeDelta::FromSeconds(20), base::TimeDelta::FromSeconds(30), true);
// Should snap |moderate_loaded_tab_count| to |high_loaded_tab_count|, when
// the amount of physical memory is so high that (|memory_in_gb| *
......@@ -290,7 +301,7 @@ TEST_F(TabManagerFeaturesTest, GetProactiveTabFreezeAndDiscardParams) {
true, true, true, 7, 42, 42, memory_in_gb_high,
base::TimeDelta::FromSeconds(60), base::TimeDelta::FromSeconds(120),
base::TimeDelta::FromSeconds(247), base::TimeDelta::FromSeconds(10),
base::TimeDelta::FromSeconds(20), base::TimeDelta::FromSeconds(30));
base::TimeDelta::FromSeconds(20), base::TimeDelta::FromSeconds(30), true);
// Tests normal case where |memory_in gb| * |moderate_tab_count_per_gb_ram| is
// in the interval [low_loaded_tab_count, high_loaded_tab_count].
......@@ -299,7 +310,7 @@ TEST_F(TabManagerFeaturesTest, GetProactiveTabFreezeAndDiscardParams) {
true, true, true, 7, 16, 42, memory_in_gb_normal,
base::TimeDelta::FromSeconds(60), base::TimeDelta::FromSeconds(120),
base::TimeDelta::FromSeconds(247), base::TimeDelta::FromSeconds(10),
base::TimeDelta::FromSeconds(20), base::TimeDelta::FromSeconds(30));
base::TimeDelta::FromSeconds(20), base::TimeDelta::FromSeconds(30), true);
}
TEST_F(TabManagerFeaturesTest,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment