Commit 245a0fac authored by Sebastien Marchand's avatar Sebastien Marchand Committed by Commit Bot

[TM] Don't freeze/discard a tab if it's using bluetooth

The ukm.xml change simply add an enum value to a metric that has already been approved here: https://bugs.chromium.org/p/chromium/issues/detail?id=753486#c26

Bug: 995761
Change-Id: I7c83f490f1e86fef3d4d1ba1cdf60681cfdb3ce2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1778406Reviewed-by: default avatarAlexei Svitkine <asvitkine@chromium.org>
Reviewed-by: default avatarBrian White <bcwhite@chromium.org>
Reviewed-by: default avatarScott Violet <sky@chromium.org>
Reviewed-by: default avatarFrançois Doray <fdoray@chromium.org>
Reviewed-by: default avatarOvidio de Jesús Ruiz-Henríquez <odejesush@chromium.org>
Auto-Submit: Sébastien Marchand <sebmarchand@chromium.org>
Commit-Queue: Sébastien Marchand <sebmarchand@chromium.org>
Cr-Commit-Position: refs/heads/master@{#693946}
parent f785e86d
...@@ -35,6 +35,7 @@ const char* kDecisionFailureReasonStrings[] = { ...@@ -35,6 +35,7 @@ const char* kDecisionFailureReasonStrings[] = {
"Tab is currently using DevTools", "Tab is currently using DevTools",
"Tab is currently capturing a window or screen", "Tab is currently capturing a window or screen",
"Tab is sharing its BrowsingInstance with another tab", "Tab is sharing its BrowsingInstance with another tab",
"Tab is currently connected to a bluetooth device",
}; };
static_assert(base::size(kDecisionFailureReasonStrings) == static_assert(base::size(kDecisionFailureReasonStrings) ==
static_cast<size_t>(DecisionFailureReason::MAX), static_cast<size_t>(DecisionFailureReason::MAX),
...@@ -134,6 +135,9 @@ void PopulateFailureReason( ...@@ -134,6 +135,9 @@ void PopulateFailureReason(
case DecisionFailureReason::LIVE_STATE_SHARING_BROWSING_INSTANCE: case DecisionFailureReason::LIVE_STATE_SHARING_BROWSING_INSTANCE:
ukm->SetFailureLiveStateSharingBrowsingInstance(1); ukm->SetFailureLiveStateSharingBrowsingInstance(1);
break; break;
case DecisionFailureReason::LIVE_STATE_USING_BLUETOOTH:
ukm->SetFailureLiveStateUsingBluetooth(1);
break;
case DecisionFailureReason::MAX: case DecisionFailureReason::MAX:
break; break;
} }
......
...@@ -77,6 +77,9 @@ enum class DecisionFailureReason : int32_t { ...@@ -77,6 +77,9 @@ enum class DecisionFailureReason : int32_t {
// This tab is sharing its BrowsingInstance with another tab, and so could // This tab is sharing its BrowsingInstance with another tab, and so could
// want to communicate with it. // want to communicate with it.
LIVE_STATE_SHARING_BROWSING_INSTANCE, LIVE_STATE_SHARING_BROWSING_INSTANCE,
// The tab is opted out of the intervention as it's currently connected to a
// bluetooth device.
LIVE_STATE_USING_BLUETOOTH,
// This must remain last. // This must remain last.
MAX, MAX,
}; };
......
...@@ -205,6 +205,8 @@ TEST(DecisionDetailsTest, TabManagerLifecycleStateChangeUkm) { ...@@ -205,6 +205,8 @@ TEST(DecisionDetailsTest, TabManagerLifecycleStateChangeUkm) {
details.AddReason(DecisionFailureReason::LIVE_STATE_DEVTOOLS_OPEN)); details.AddReason(DecisionFailureReason::LIVE_STATE_DEVTOOLS_OPEN));
EXPECT_FALSE( EXPECT_FALSE(
details.AddReason(DecisionFailureReason::LIVE_STATE_DESKTOP_CAPTURE)); details.AddReason(DecisionFailureReason::LIVE_STATE_DESKTOP_CAPTURE));
EXPECT_FALSE(
details.AddReason(DecisionFailureReason::LIVE_STATE_USING_BLUETOOTH));
EXPECT_TRUE(details.AddReason( EXPECT_TRUE(details.AddReason(
DecisionSuccessReason::LIFECYCLES_FEATURE_POLICY_OPT_IN)); DecisionSuccessReason::LIFECYCLES_FEATURE_POLICY_OPT_IN));
...@@ -258,6 +260,8 @@ TEST(DecisionDetailsTest, TabManagerLifecycleStateChangeUkm) { ...@@ -258,6 +260,8 @@ TEST(DecisionDetailsTest, TabManagerLifecycleStateChangeUkm) {
entry, ukm_builder.kFailureLiveStateDevToolsOpenName, 1); entry, ukm_builder.kFailureLiveStateDevToolsOpenName, 1);
ukm_recorder.ExpectEntryMetric( ukm_recorder.ExpectEntryMetric(
entry, ukm_builder.kFailureLiveStateDesktopCaptureName, 1); entry, ukm_builder.kFailureLiveStateDesktopCaptureName, 1);
ukm_recorder.ExpectEntryMetric(
entry, ukm_builder.kFailureLiveStateUsingBluetoothName, 1);
EXPECT_FALSE(ukm_recorder.EntryHasMetric( EXPECT_FALSE(ukm_recorder.EntryHasMetric(
entry, ukm_builder.kSuccessLifecyclesFeaturePolicyOptInName)); entry, ukm_builder.kSuccessLifecyclesFeaturePolicyOptInName));
EXPECT_FALSE(ukm_recorder.EntryHasMetric( EXPECT_FALSE(ukm_recorder.EntryHasMetric(
......
...@@ -968,6 +968,13 @@ void TabLifecycleUnitSource::TabLifecycleUnit::CheckIfTabIsUsedInBackground( ...@@ -968,6 +968,13 @@ void TabLifecycleUnitSource::TabLifecycleUnit::CheckIfTabIsUsedInBackground(
decision_details->AddReason( decision_details->AddReason(
DecisionFailureReason::LIVE_STATE_DEVTOOLS_OPEN); DecisionFailureReason::LIVE_STATE_DEVTOOLS_OPEN);
} }
// Do not freeze or discard tabs that are connected to at least one bluetooth
// device.
if (web_contents()->IsConnectedToBluetoothDevice()) {
decision_details->AddReason(
DecisionFailureReason::LIVE_STATE_USING_BLUETOOTH);
}
} }
void TabLifecycleUnitSource::TabLifecycleUnit::CanFreezeHeuristicsChecks( void TabLifecycleUnitSource::TabLifecycleUnit::CanFreezeHeuristicsChecks(
......
...@@ -901,4 +901,34 @@ TEST_F(TabLifecycleUnitTest, DisableHeuristicsFlag) { ...@@ -901,4 +901,34 @@ TEST_F(TabLifecycleUnitTest, DisableHeuristicsFlag) {
decision_details.Clear(); decision_details.Clear();
} }
TEST_F(TabLifecycleUnitTest, CannotFreezeOrDiscardIfConnectedToBluetooth) {
TabLifecycleUnit tab_lifecycle_unit(GetTabLifecycleUnitSource(), &observers_,
usage_clock_.get(), web_contents_,
tab_strip_model_.get());
TabLoadTracker::Get()->TransitionStateForTesting(web_contents_,
LoadingState::LOADED);
// Advance time enough that the tab is urgent discardable.
test_clock_.Advance(kBackgroundUrgentProtectionTime);
ExpectCanDiscardTrueAllReasons(&tab_lifecycle_unit);
content::WebContentsTester::For(web_contents_)
->SetIsConnectedToBluetoothDevice(true);
DecisionDetails decision_details;
EXPECT_FALSE(tab_lifecycle_unit.CanFreeze(&decision_details));
EXPECT_FALSE(decision_details.IsPositive());
EXPECT_EQ(DecisionFailureReason::LIVE_STATE_USING_BLUETOOTH,
decision_details.FailureReason());
decision_details.Clear();
EXPECT_FALSE(tab_lifecycle_unit.CanDiscard(
LifecycleUnitDiscardReason::PROACTIVE, &decision_details));
EXPECT_FALSE(decision_details.IsPositive());
EXPECT_EQ(DecisionFailureReason::LIVE_STATE_USING_BLUETOOTH,
decision_details.FailureReason());
content::WebContentsTester::For(web_contents_)
->SetIsConnectedToBluetoothDevice(false);
}
} // namespace resource_coordinator } // namespace resource_coordinator
...@@ -176,6 +176,11 @@ class WebContentsTester { ...@@ -176,6 +176,11 @@ class WebContentsTester {
// Sets the last active time. // Sets the last active time.
virtual void SetLastActiveTime(base::TimeTicks last_active_time) = 0; virtual void SetLastActiveTime(base::TimeTicks last_active_time) = 0;
// Setting this to true will make IsConnectedToBluetoothDevice() return true,
// setting it to false will make the value use the logic from WebContentsImpl.
virtual void SetIsConnectedToBluetoothDevice(
bool is_connected_to_bluetooth_device) = 0;
}; };
} // namespace content } // namespace content
......
...@@ -50,7 +50,8 @@ TestWebContents::TestWebContents(BrowserContext* browser_context) ...@@ -50,7 +50,8 @@ TestWebContents::TestWebContents(BrowserContext* browser_context)
expect_set_history_offset_and_length_(false), expect_set_history_offset_and_length_(false),
expect_set_history_offset_and_length_history_length_(0), expect_set_history_offset_and_length_history_length_(0),
pause_subresource_loading_called_(false), pause_subresource_loading_called_(false),
audio_group_id_(base::UnguessableToken::Create()) { audio_group_id_(base::UnguessableToken::Create()),
is_connected_to_bluetooth_device_(false) {
if (!RenderProcessHostImpl::get_render_process_host_factory_for_testing()) { if (!RenderProcessHostImpl::get_render_process_host_factory_for_testing()) {
// Most unit tests should prefer to create a generic MockRenderProcessHost // Most unit tests should prefer to create a generic MockRenderProcessHost
// (instead of a real RenderProcessHostImpl). Tests that need to use a // (instead of a real RenderProcessHostImpl). Tests that need to use a
...@@ -443,6 +444,16 @@ void TestWebContents::SetLastActiveTime(base::TimeTicks last_active_time) { ...@@ -443,6 +444,16 @@ void TestWebContents::SetLastActiveTime(base::TimeTicks last_active_time) {
last_active_time_ = last_active_time; last_active_time_ = last_active_time;
} }
void TestWebContents::SetIsConnectedToBluetoothDevice(
bool is_connected_to_bluetooth_device) {
is_connected_to_bluetooth_device_ = is_connected_to_bluetooth_device;
}
bool TestWebContents::IsConnectedToBluetoothDevice() {
return is_connected_to_bluetooth_device_ ||
WebContentsImpl::IsConnectedToBluetoothDevice();
}
base::UnguessableToken TestWebContents::GetAudioGroupId() { base::UnguessableToken TestWebContents::GetAudioGroupId() {
return audio_group_id_; return audio_group_id_;
} }
......
...@@ -163,6 +163,12 @@ class TestWebContents : public WebContentsImpl, public WebContentsTester { ...@@ -163,6 +163,12 @@ class TestWebContents : public WebContentsImpl, public WebContentsTester {
void SetLastActiveTime(base::TimeTicks last_active_time) override; void SetLastActiveTime(base::TimeTicks last_active_time) override;
void SetIsConnectedToBluetoothDevice(
bool is_connected_to_bluetooth_device) override;
// Override IsConnectedToBluetoothDevice() to allow using the mocked value.
bool IsConnectedToBluetoothDevice() override;
base::UnguessableToken GetAudioGroupId() override; base::UnguessableToken GetAudioGroupId() override;
protected: protected:
...@@ -214,6 +220,7 @@ class TestWebContents : public WebContentsImpl, public WebContentsTester { ...@@ -214,6 +220,7 @@ class TestWebContents : public WebContentsImpl, public WebContentsTester {
base::Optional<base::string16> title_; base::Optional<base::string16> title_;
bool pause_subresource_loading_called_; bool pause_subresource_loading_called_;
base::UnguessableToken audio_group_id_; base::UnguessableToken audio_group_id_;
bool is_connected_to_bluetooth_device_;
}; };
} // namespace content } // namespace content
......
...@@ -7767,6 +7767,12 @@ be describing additional metrics about the same event. ...@@ -7767,6 +7767,12 @@ be describing additional metrics about the same event.
sharing its BrowsingInstance with at least one other tab. sharing its BrowsingInstance with at least one other tab.
</summary> </summary>
</metric> </metric>
<metric name="FailureLiveStateUsingBluetooth">
<summary>
Boolean indicating that the intervention was disallowed because the tab is
currently connnected to at least one bluetooth device.
</summary>
</metric>
<metric name="FailureLiveStateUsingWebSockets"> <metric name="FailureLiveStateUsingWebSockets">
<summary> <summary>
Boolean indicating that the intervention was disallowed because the tab is Boolean indicating that the intervention was disallowed because the tab is
......
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