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[] = {
"Tab is currently using DevTools",
"Tab is currently capturing a window or screen",
"Tab is sharing its BrowsingInstance with another tab",
"Tab is currently connected to a bluetooth device",
};
static_assert(base::size(kDecisionFailureReasonStrings) ==
static_cast<size_t>(DecisionFailureReason::MAX),
......@@ -134,6 +135,9 @@ void PopulateFailureReason(
case DecisionFailureReason::LIVE_STATE_SHARING_BROWSING_INSTANCE:
ukm->SetFailureLiveStateSharingBrowsingInstance(1);
break;
case DecisionFailureReason::LIVE_STATE_USING_BLUETOOTH:
ukm->SetFailureLiveStateUsingBluetooth(1);
break;
case DecisionFailureReason::MAX:
break;
}
......
......@@ -77,6 +77,9 @@ enum class DecisionFailureReason : int32_t {
// This tab is sharing its BrowsingInstance with another tab, and so could
// want to communicate with it.
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.
MAX,
};
......
......@@ -205,6 +205,8 @@ TEST(DecisionDetailsTest, TabManagerLifecycleStateChangeUkm) {
details.AddReason(DecisionFailureReason::LIVE_STATE_DEVTOOLS_OPEN));
EXPECT_FALSE(
details.AddReason(DecisionFailureReason::LIVE_STATE_DESKTOP_CAPTURE));
EXPECT_FALSE(
details.AddReason(DecisionFailureReason::LIVE_STATE_USING_BLUETOOTH));
EXPECT_TRUE(details.AddReason(
DecisionSuccessReason::LIFECYCLES_FEATURE_POLICY_OPT_IN));
......@@ -258,6 +260,8 @@ TEST(DecisionDetailsTest, TabManagerLifecycleStateChangeUkm) {
entry, ukm_builder.kFailureLiveStateDevToolsOpenName, 1);
ukm_recorder.ExpectEntryMetric(
entry, ukm_builder.kFailureLiveStateDesktopCaptureName, 1);
ukm_recorder.ExpectEntryMetric(
entry, ukm_builder.kFailureLiveStateUsingBluetoothName, 1);
EXPECT_FALSE(ukm_recorder.EntryHasMetric(
entry, ukm_builder.kSuccessLifecyclesFeaturePolicyOptInName));
EXPECT_FALSE(ukm_recorder.EntryHasMetric(
......
......@@ -968,6 +968,13 @@ void TabLifecycleUnitSource::TabLifecycleUnit::CheckIfTabIsUsedInBackground(
decision_details->AddReason(
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(
......
......@@ -901,4 +901,34 @@ TEST_F(TabLifecycleUnitTest, DisableHeuristicsFlag) {
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
......@@ -176,6 +176,11 @@ class WebContentsTester {
// Sets the last active time.
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
......
......@@ -50,7 +50,8 @@ TestWebContents::TestWebContents(BrowserContext* browser_context)
expect_set_history_offset_and_length_(false),
expect_set_history_offset_and_length_history_length_(0),
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()) {
// Most unit tests should prefer to create a generic MockRenderProcessHost
// (instead of a real RenderProcessHostImpl). Tests that need to use a
......@@ -443,6 +444,16 @@ void TestWebContents::SetLastActiveTime(base::TimeTicks 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() {
return audio_group_id_;
}
......
......@@ -163,6 +163,12 @@ class TestWebContents : public WebContentsImpl, public WebContentsTester {
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;
protected:
......@@ -214,6 +220,7 @@ class TestWebContents : public WebContentsImpl, public WebContentsTester {
base::Optional<base::string16> title_;
bool pause_subresource_loading_called_;
base::UnguessableToken audio_group_id_;
bool is_connected_to_bluetooth_device_;
};
} // namespace content
......
......@@ -7767,6 +7767,12 @@ be describing additional metrics about the same event.
sharing its BrowsingInstance with at least one other tab.
</summary>
</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">
<summary>
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