Commit 399e41a2 authored by Sebastien Marchand's avatar Sebastien Marchand Committed by Commit Bot

[PM] Decouple the page discarding logic from the memory pressure policy

This will make it possible to do page discarding from other policies.

Change-Id: I0ddc0d5a2e60a873d8c295b76c0b482427967b7d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2303774Reviewed-by: default avatarFrançois Doray <fdoray@chromium.org>
Commit-Queue: Sébastien Marchand <sebmarchand@chromium.org>
Cr-Commit-Position: refs/heads/master@{#789977}
parent 9ec8c701
...@@ -3353,6 +3353,8 @@ static_library("browser") { ...@@ -3353,6 +3353,8 @@ static_library("browser") {
"performance_manager/policies/background_tab_loading_policy.h", "performance_manager/policies/background_tab_loading_policy.h",
"performance_manager/policies/background_tab_loading_policy_helpers.cc", "performance_manager/policies/background_tab_loading_policy_helpers.cc",
"performance_manager/policies/background_tab_loading_policy_helpers.h", "performance_manager/policies/background_tab_loading_policy_helpers.h",
"performance_manager/policies/page_discarding_helper.cc",
"performance_manager/policies/page_discarding_helper.h",
"performance_manager/policies/urgent_page_discarding_policy.cc", "performance_manager/policies/urgent_page_discarding_policy.cc",
"performance_manager/policies/urgent_page_discarding_policy.h", "performance_manager/policies/urgent_page_discarding_policy.h",
"permissions/attestation_permission_request.cc", "permissions/attestation_permission_request.cc",
......
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
#include "chrome/browser/performance_manager/policies/background_tab_loading_policy.h" #include "chrome/browser/performance_manager/policies/background_tab_loading_policy.h"
#include "chrome/browser/performance_manager/policies/high_pmf_memory_pressure_policy.h" #include "chrome/browser/performance_manager/policies/high_pmf_memory_pressure_policy.h"
#include "chrome/browser/performance_manager/policies/policy_features.h" #include "chrome/browser/performance_manager/policies/policy_features.h"
#include "chrome/browser/performance_manager/policies/urgent_page_discarding_policy.h"
#include "chrome/browser/performance_manager/policies/working_set_trimmer_policy.h" #include "chrome/browser/performance_manager/policies/working_set_trimmer_policy.h"
#include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/profiles/profile_manager.h"
#include "components/performance_manager/embedder/performance_manager_lifetime.h" #include "components/performance_manager/embedder/performance_manager_lifetime.h"
...@@ -43,6 +42,8 @@ ...@@ -43,6 +42,8 @@
#endif // defined(OS_CHROMEOS) #endif // defined(OS_CHROMEOS)
#if !defined(OS_ANDROID) #if !defined(OS_ANDROID)
#include "chrome/browser/performance_manager/policies/page_discarding_helper.h"
#include "chrome/browser/performance_manager/policies/urgent_page_discarding_policy.h"
#include "chrome/browser/tab_contents/form_interaction_tab_helper.h" #include "chrome/browser/tab_contents/form_interaction_tab_helper.h"
#endif // !defined(OS_ANDROID) #endif // !defined(OS_ANDROID)
...@@ -105,6 +106,8 @@ void ChromeBrowserMainExtraPartsPerformanceManager::CreatePoliciesAndDecorators( ...@@ -105,6 +106,8 @@ void ChromeBrowserMainExtraPartsPerformanceManager::CreatePoliciesAndDecorators(
if (base::FeatureList::IsEnabled( if (base::FeatureList::IsEnabled(
performance_manager::features:: performance_manager::features::
kUrgentDiscardingFromPerformanceManager)) { kUrgentDiscardingFromPerformanceManager)) {
graph->PassToGraph(std::make_unique<
performance_manager::policies::PageDiscardingHelper>());
graph->PassToGraph( graph->PassToGraph(
std::make_unique< std::make_unique<
performance_manager::policies::UrgentPageDiscardingPolicy>()); performance_manager::policies::UrgentPageDiscardingPolicy>());
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_PERFORMANCE_MANAGER_POLICIES_PAGE_DISCARDING_HELPER_H_
#define CHROME_BROWSER_PERFORMANCE_MANAGER_POLICIES_PAGE_DISCARDING_HELPER_H_
#include "base/callback_forward.h"
#include "base/containers/flat_map.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "chrome/browser/performance_manager/policies/policy_features.h"
#include "components/performance_manager/public/decorators/page_live_state_decorator.h"
#include "components/performance_manager/public/graph/graph.h"
#include "components/performance_manager/public/graph/graph_registered.h"
#include "components/performance_manager/public/graph/node_data_describer.h"
#include "components/performance_manager/public/graph/page_node.h"
namespace performance_manager {
namespace mechanism {
class PageDiscarder;
} // namespace mechanism
namespace policies {
// Helper class to be used by the policies that want to discard tabs.
//
// This is a GraphRegistered object and should be accessed via
// PageDiscardingHelper::GetFromGraph(graph()).
class PageDiscardingHelper : public GraphOwned,
public PageNode::ObserverDefaultImpl,
public GraphRegisteredImpl<PageDiscardingHelper>,
public NodeDataDescriberDefaultImpl {
public:
PageDiscardingHelper();
~PageDiscardingHelper() override;
PageDiscardingHelper(const PageDiscardingHelper& other) = delete;
PageDiscardingHelper& operator=(const PageDiscardingHelper&) = delete;
// Selects a tab to discard based on |strategy| and posts to the UI thread to
// discard it. This will try to discard a tab until there's been a successful
// discard or until there's no more discard candidate.
void UrgentlyDiscardAPage(
features::UrgentDiscardingParams::DiscardStrategy discard_strategy,
base::OnceCallback<void(bool)> post_discard_cb);
// PageNodeObserver:
void OnBeforePageNodeRemoved(const PageNode* page_node) override;
void OnIsAudibleChanged(const PageNode* page_node) override;
void SetMockDiscarderForTesting(
std::unique_ptr<mechanism::PageDiscarder> discarder);
bool CanUrgentlyDiscardForTesting(const PageNode* page_node) const {
return CanUrgentlyDiscard(page_node);
}
void AdornsPageWithDiscardAttemptMarkerForTesting(PageNode* page_node);
void SetGraphForTesting(Graph* graph) { graph_ = graph; }
protected:
void OnPassedToGraph(Graph* graph) override;
void OnTakenFromGraph(Graph* graph) override;
// Returns the PageLiveStateDecorator::Data associated with a PageNode.
// Exposed and made virtual to allowed injecting some fake data in tests.
virtual const PageLiveStateDecorator::Data* GetPageNodeLiveStateData(
const PageNode* page_node) const;
private:
// Indicates if a PageNode can be urgently discarded.
bool CanUrgentlyDiscard(const PageNode* page_node) const;
// NodeDataDescriber implementation:
base::Value DescribePageNodeData(const PageNode* node) const override;
// Called after each discard attempt. |success| will indicate whether or not
// the attempt has been successful. |post_discard_cb| will be called once
// there's been a successful discard or if there's no more discard candidates.
void PostDiscardAttemptCallback(
features::UrgentDiscardingParams::DiscardStrategy discard_strategy,
base::OnceCallback<void(bool)> post_discard_cb,
bool success);
// Map that associates a PageNode with the last time it became non audible.
// PageNodes that have never been audible are not present in this map.
base::flat_map<const PageNode*, base::TimeTicks>
last_change_to_non_audible_time_;
// The mechanism used to do the actual discarding.
std::unique_ptr<performance_manager::mechanism::PageDiscarder>
page_discarder_;
Graph* graph_ = nullptr;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<PageDiscardingHelper> weak_factory_{this};
};
} // namespace policies
} // namespace performance_manager
#endif // CHROME_BROWSER_PERFORMANCE_MANAGER_POLICIES_PAGE_DISCARDING_HELPER_H_
...@@ -5,31 +5,19 @@ ...@@ -5,31 +5,19 @@
#ifndef CHROME_BROWSER_PERFORMANCE_MANAGER_POLICIES_URGENT_PAGE_DISCARDING_POLICY_H_ #ifndef CHROME_BROWSER_PERFORMANCE_MANAGER_POLICIES_URGENT_PAGE_DISCARDING_POLICY_H_
#define CHROME_BROWSER_PERFORMANCE_MANAGER_POLICIES_URGENT_PAGE_DISCARDING_POLICY_H_ #define CHROME_BROWSER_PERFORMANCE_MANAGER_POLICIES_URGENT_PAGE_DISCARDING_POLICY_H_
#include "base/containers/flat_map.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/memory_pressure_listener.h" #include "base/memory/memory_pressure_listener.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/sequence_checker.h" #include "base/sequence_checker.h"
#include "components/performance_manager/public/decorators/page_live_state_decorator.h"
#include "components/performance_manager/public/graph/graph.h" #include "components/performance_manager/public/graph/graph.h"
#include "components/performance_manager/public/graph/node_data_describer.h"
#include "components/performance_manager/public/graph/page_node.h"
namespace performance_manager { namespace performance_manager {
namespace mechanism {
class PageDiscarder;
} // namespace mechanism
namespace policies { namespace policies {
// Urgently discard a tab when receiving a memory pressure signal. The discard // Urgently discard a tab when receiving a memory pressure signal. The discard
// strategy used by this policy is based on a feature flag, see // strategy used by this policy is based on a feature flag, see
// UrgentDiscardingParams for more details. // UrgentDiscardingParams for more details.
class UrgentPageDiscardingPolicy : public GraphOwned, class UrgentPageDiscardingPolicy : public GraphOwned {
public PageNode::ObserverDefaultImpl,
public NodeDataDescriberDefaultImpl {
public: public:
UrgentPageDiscardingPolicy(); UrgentPageDiscardingPolicy();
~UrgentPageDiscardingPolicy() override; ~UrgentPageDiscardingPolicy() override;
...@@ -41,23 +29,6 @@ class UrgentPageDiscardingPolicy : public GraphOwned, ...@@ -41,23 +29,6 @@ class UrgentPageDiscardingPolicy : public GraphOwned,
void OnPassedToGraph(Graph* graph) override; void OnPassedToGraph(Graph* graph) override;
void OnTakenFromGraph(Graph* graph) override; void OnTakenFromGraph(Graph* graph) override;
// PageNodeObserver:
void OnBeforePageNodeRemoved(const PageNode* page_node) override;
void OnIsAudibleChanged(const PageNode* page_node) override;
void SetMockDiscarderForTesting(
std::unique_ptr<mechanism::PageDiscarder> discarder);
bool CanUrgentlyDiscardForTesting(const PageNode* page_node) const {
return CanUrgentlyDiscard(page_node);
}
void AdornsPageWithDiscardAttemptMarkerForTesting(PageNode* page_node);
protected:
// Returns the PageLiveStateDecorator::Data associated with a PageNode.
// Exposed and made virtual to allowed injecting some fake data in tests.
virtual const PageLiveStateDecorator::Data* GetPageNodeLiveStateData(
const PageNode* page_node) const;
private: private:
void OnMemoryPressure( void OnMemoryPressure(
base::MemoryPressureListener::MemoryPressureLevel level); base::MemoryPressureListener::MemoryPressureLevel level);
...@@ -70,32 +41,13 @@ class UrgentPageDiscardingPolicy : public GraphOwned, ...@@ -70,32 +41,13 @@ class UrgentPageDiscardingPolicy : public GraphOwned,
// when handling a pressure event. // when handling a pressure event.
void UnregisterMemoryPressureListener(); void UnregisterMemoryPressureListener();
// Indicates if a PageNode can be urgently discarded.
bool CanUrgentlyDiscard(const PageNode* page_node) const;
// Selects a tab to discard and posts to the UI thread to discard it.
void UrgentlyDiscardAPage();
// Callback called when a discard attempt has completed. // Callback called when a discard attempt has completed.
void PostDiscardAttemptCallback(bool success); void PostDiscardAttemptCallback(bool success);
// NodeDataDescriber implementation:
base::Value DescribePageNodeData(const PageNode* node) const override;
std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_; std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_;
Graph* graph_ = nullptr; Graph* graph_ = nullptr;
// Map that associates a PageNode with the last time it became non audible.
// PageNodes that have never been audible are not present in this map.
base::flat_map<const PageNode*, base::TimeTicks>
last_change_to_non_audible_time_;
std::unique_ptr<performance_manager::mechanism::PageDiscarder>
page_discarder_;
SEQUENCE_CHECKER(sequence_checker_); SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<UrgentPageDiscardingPolicy> weak_factory_{this};
}; };
} // namespace policies } // namespace policies
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/performance_manager/test_support/page_discarding_utils.h"
#include "base/time/time.h"
#include "chrome/browser/performance_manager/decorators/page_aggregator.h"
#include "chrome/browser/performance_manager/policies/page_discarding_helper.h"
#include "components/performance_manager/graph/frame_node_impl.h"
#include "components/performance_manager/graph/page_node_impl.h"
#include "components/performance_manager/test_support/graph_test_harness.h"
namespace performance_manager {
namespace testing {
namespace {
// Test version of the PageDiscardingHelper.
class TestPageDiscardingHelper : public policies::PageDiscardingHelper {
public:
TestPageDiscardingHelper();
~TestPageDiscardingHelper() override;
TestPageDiscardingHelper(const TestPageDiscardingHelper& other) = delete;
TestPageDiscardingHelper& operator=(const TestPageDiscardingHelper&) = delete;
protected:
const PageLiveStateDecorator::Data* GetPageNodeLiveStateData(
const PageNode* page_node) const override {
// Returns a fake version of the PageLiveStateDecorator::Data, create it if
// it doesn't exist. Tests that want to set some fake live state data should
// call |FakePageLiveStateData::GetOrCreate|.
return FakePageLiveStateData::GetOrCreate(
PageNodeImpl::FromNode(page_node));
}
};
} // namespace
FakePageLiveStateData::~FakePageLiveStateData() = default;
// PageLiveStateDecorator::Data:
bool FakePageLiveStateData::IsConnectedToUSBDevice() const {
return is_connected_to_usb_device_;
}
bool FakePageLiveStateData::IsConnectedToBluetoothDevice() const {
return is_connected_to_bluetooth_device_;
}
bool FakePageLiveStateData::IsCapturingVideo() const {
return is_capturing_video_;
}
bool FakePageLiveStateData::IsCapturingAudio() const {
return is_capturing_audio_;
}
bool FakePageLiveStateData::IsBeingMirrored() const {
return is_being_mirrored_;
}
bool FakePageLiveStateData::IsCapturingDesktop() const {
return is_capturing_desktop_;
}
bool FakePageLiveStateData::IsAutoDiscardable() const {
return is_auto_discardable_;
}
bool FakePageLiveStateData::WasDiscarded() const {
return was_discarded_;
}
FakePageLiveStateData::FakePageLiveStateData(const PageNodeImpl* page_node) {}
LenientMockPageDiscarder::LenientMockPageDiscarder() = default;
LenientMockPageDiscarder::~LenientMockPageDiscarder() = default;
void LenientMockPageDiscarder::DiscardPageNode(
const PageNode* page_node,
base::OnceCallback<void(bool)> post_discard_cb) {
std::move(post_discard_cb).Run(DiscardPageNodeImpl(page_node));
}
TestPageDiscardingHelper::TestPageDiscardingHelper() = default;
TestPageDiscardingHelper::~TestPageDiscardingHelper() = default;
GraphTestHarnessWithMockDiscarder::GraphTestHarnessWithMockDiscarder() {
// Some tests depends on the existence of the PageAggregator.
graph()->PassToGraph(std::make_unique<PageAggregator>());
}
GraphTestHarnessWithMockDiscarder::~GraphTestHarnessWithMockDiscarder() =
default;
void GraphTestHarnessWithMockDiscarder::SetUp() {
GraphTestHarness::SetUp();
// Make the policy use a mock PageDiscarder.
auto mock_discarder = std::make_unique<MockPageDiscarder>();
mock_discarder_ = mock_discarder.get();
// Create the helper and pass it to the graph.
auto page_discarding_helper = std::make_unique<TestPageDiscardingHelper>();
page_discarding_helper->SetMockDiscarderForTesting(std::move(mock_discarder));
graph()->PassToGraph(std::move(page_discarding_helper));
DCHECK(policies::PageDiscardingHelper::GetFromGraph(graph()));
// Create a PageNode and make it discardable.
process_node_ = CreateNode<performance_manager::ProcessNodeImpl>();
page_node_ = CreateNode<performance_manager::PageNodeImpl>();
main_frame_node_ =
CreateFrameNodeAutoId(process_node_.get(), page_node_.get());
main_frame_node_->SetIsCurrent(true);
MakePageNodeDiscardable(page_node(), task_env());
}
void GraphTestHarnessWithMockDiscarder::TearDown() {
main_frame_node_.reset();
page_node_.reset();
process_node_.reset();
GraphTestHarness::TearDown();
}
void MakePageNodeDiscardable(PageNodeImpl* page_node,
content::BrowserTaskEnvironment& task_env) {
page_node->SetIsVisible(false);
page_node->SetIsAudible(false);
const auto kUrl = GURL("https://foo.com");
page_node->OnMainFrameNavigationCommitted(false, base::TimeTicks::Now(), 42,
kUrl, "text/html");
(*page_node->main_frame_nodes().begin())->OnNavigationCommitted(kUrl, false);
task_env.FastForwardBy(base::TimeDelta::FromMinutes(10));
DCHECK(policies::PageDiscardingHelper::GetFromGraph(page_node->graph())
->CanUrgentlyDiscardForTesting(page_node));
}
} // namespace testing
} // namespace performance_manager
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_PERFORMANCE_MANAGER_TEST_SUPPORT_PAGE_DISCARDING_UTILS_H_
#define CHROME_BROWSER_PERFORMANCE_MANAGER_TEST_SUPPORT_PAGE_DISCARDING_UTILS_H_
#include "chrome/browser/performance_manager/mechanisms/page_discarder.h"
#include "chrome/browser/performance_manager/policies/page_discarding_helper.h"
#include "components/performance_manager/graph/node_attached_data_impl.h"
#include "components/performance_manager/public/decorators/page_live_state_decorator.h"
#include "components/performance_manager/test_support/graph_test_harness.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace performance_manager {
class FrameNodeImpl;
class PageNodeImpl;
class ProcessNodeImpl;
namespace testing {
// Class allowing setting some fake PageLiveStateDecorator::Data for a PageNode.
class FakePageLiveStateData
: public PageLiveStateDecorator::Data,
public NodeAttachedDataImpl<FakePageLiveStateData> {
public:
struct Traits : public NodeAttachedDataInMap<PageNodeImpl> {};
~FakePageLiveStateData() override;
FakePageLiveStateData(const FakePageLiveStateData& other) = delete;
FakePageLiveStateData& operator=(const FakePageLiveStateData&) = delete;
// PageLiveStateDecorator::Data:
bool IsConnectedToUSBDevice() const override;
bool IsConnectedToBluetoothDevice() const override;
bool IsCapturingVideo() const override;
bool IsCapturingAudio() const override;
bool IsBeingMirrored() const override;
bool IsCapturingDesktop() const override;
bool IsAutoDiscardable() const override;
bool WasDiscarded() const override;
bool is_connected_to_usb_device_ = false;
bool is_connected_to_bluetooth_device_ = false;
bool is_capturing_video_ = false;
bool is_capturing_audio_ = false;
bool is_being_mirrored_ = false;
bool is_capturing_desktop_ = false;
bool is_auto_discardable_ = true;
bool was_discarded_ = false;
private:
friend class ::performance_manager::NodeAttachedDataImpl<
FakePageLiveStateData>;
explicit FakePageLiveStateData(const PageNodeImpl* page_node);
};
// Mock version of a performance_manager::mechanism::PageDiscarder.
class LenientMockPageDiscarder
: public performance_manager::mechanism::PageDiscarder {
public:
LenientMockPageDiscarder();
~LenientMockPageDiscarder() override;
LenientMockPageDiscarder(const LenientMockPageDiscarder& other) = delete;
LenientMockPageDiscarder& operator=(const LenientMockPageDiscarder&) = delete;
MOCK_METHOD1(DiscardPageNodeImpl, bool(const PageNode* page_node));
private:
void DiscardPageNode(const PageNode* page_node,
base::OnceCallback<void(bool)> post_discard_cb) override;
};
using MockPageDiscarder = ::testing::StrictMock<LenientMockPageDiscarder>;
// Specialization of a GraphTestHarness that uses a MockPageDiscarder to
// do the discard attempts.
class GraphTestHarnessWithMockDiscarder : public GraphTestHarness {
public:
GraphTestHarnessWithMockDiscarder();
~GraphTestHarnessWithMockDiscarder() override;
GraphTestHarnessWithMockDiscarder(
const GraphTestHarnessWithMockDiscarder& other) = delete;
GraphTestHarnessWithMockDiscarder& operator=(
const GraphTestHarnessWithMockDiscarder&) = delete;
void SetUp() override;
void TearDown() override;
protected:
PageNodeImpl* page_node() { return page_node_.get(); }
ProcessNodeImpl* process_node() { return process_node_.get(); }
FrameNodeImpl* frame_node() { return main_frame_node_.get(); }
void ResetFrameNode() { main_frame_node_.reset(); }
testing::MockPageDiscarder* discarder() { return mock_discarder_; }
private:
testing::MockPageDiscarder* mock_discarder_;
performance_manager::TestNodeWrapper<performance_manager::PageNodeImpl>
page_node_;
performance_manager::TestNodeWrapper<performance_manager::ProcessNodeImpl>
process_node_;
performance_manager::TestNodeWrapper<performance_manager::FrameNodeImpl>
main_frame_node_;
};
// Make sure that |page_node| is discardable.
void MakePageNodeDiscardable(PageNodeImpl* page_node,
content::BrowserTaskEnvironment& task_env);
} // namespace testing
} // namespace performance_manager
#endif // CHROME_BROWSER_PERFORMANCE_MANAGER_TEST_SUPPORT_PAGE_DISCARDING_UTILS_H_
...@@ -3635,6 +3635,8 @@ test("unit_tests") { ...@@ -3635,6 +3635,8 @@ test("unit_tests") {
"../browser/nearby_sharing/nearby_process_manager_unittest.cc", "../browser/nearby_sharing/nearby_process_manager_unittest.cc",
"../browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc", "../browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc",
"../browser/nearby_sharing/webrtc_signaling_messenger_unittest.cc", "../browser/nearby_sharing/webrtc_signaling_messenger_unittest.cc",
"../browser/performance_manager/test_support/page_discarding_utils.cc",
"../browser/performance_manager/test_support/page_discarding_utils.h",
"../browser/profiles/profile_avatar_icon_util_unittest.cc", "../browser/profiles/profile_avatar_icon_util_unittest.cc",
"../browser/profiles/profile_destroyer_unittest.cc", "../browser/profiles/profile_destroyer_unittest.cc",
"../browser/safe_browsing/generated_safe_browsing_pref_unittest.cc", "../browser/safe_browsing/generated_safe_browsing_pref_unittest.cc",
...@@ -4116,6 +4118,7 @@ test("unit_tests") { ...@@ -4116,6 +4118,7 @@ test("unit_tests") {
"../browser/performance_manager/persistence/site_data/unittest_utils.h", "../browser/performance_manager/persistence/site_data/unittest_utils.h",
# Urgent discarding from performance_manager isn't supported on Android. # Urgent discarding from performance_manager isn't supported on Android.
"../browser/performance_manager/policies/page_discarding_helper_unittest.cc",
"../browser/performance_manager/policies/urgent_page_discarding_policy_unittest.cc", "../browser/performance_manager/policies/urgent_page_discarding_policy_unittest.cc",
# Background tab loading from performance_manager isn't supported on Android. # Background tab loading from performance_manager isn't supported on Android.
......
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