bfcache: Introduce detailed memory pressure handling to BFCachePolicy
BFCachePolicy is introduced to purge bfcached page based on memory
pressure. But the current implementation was too harsh to enable
BFCachePolicy by default.
This CL introduces the following 4 feature params to evict bfcached
pages depending on the pressure level and tab status
(foregrounded/backgrounded).
- foreground_cache_size_on_moderate_pressure
- background_cache_size_on_moderate_pressure
- foreground_cache_size_on_critical_pressure
- background_cache_size_on_critical_pressure
When the cache size is set to be negative, which means that there is
no cache limit for such a situation. For example, if
foreground_cache_size_on_moderate_pressure is -1, BFCachePolicy
doesn’t evict bfcached pages for the foregrounded tabs when moderate
memory pressure is triggered.
BFCache also has the following feature params. These params are still
available as a hard limit of the cache size.
- cache_size
- foreground_cache_size
Bug: 1291435
Change-Id: I30bd5e9b4f080cab431b6f0fd4931c385c3b55fd
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3420805
Reviewed-by: Francois Pierre Doray <fdoray@chromium.org>
Reviewed-by: Rakina Zata Amni <rakina@chromium.org>
Reviewed-by: Alexander Timin <altimin@chromium.org>
Commit-Queue: Minoru Chikamune <chikamune@chromium.org>
Cr-Commit-Position: refs/heads/main@{#969749}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
996f457ea2
commit
53530571d3
chrome/browser/performance_manager/policies
components/performance_manager/graph/policies
content
browser
renderer_host
public
browser
@ -36,23 +36,67 @@ namespace performance_manager::policies {
|
||||
|
||||
namespace {
|
||||
|
||||
struct PolicyTestParams {
|
||||
const std::string scenario;
|
||||
bool enable_policy = false;
|
||||
bool flush_on_moderate_pressure = false;
|
||||
using MemoryPressureLevel = base::MemoryPressureListener::MemoryPressureLevel;
|
||||
|
||||
struct PolicyTestParam {
|
||||
const MemoryPressureLevel memory_pressure_level =
|
||||
MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_MODERATE;
|
||||
bool tab_backgrounded = false;
|
||||
bool enable_policy = true;
|
||||
int foreground_cache_size_on_moderate_pressure = 3;
|
||||
int background_cache_size_on_moderate_pressure = 2;
|
||||
int foreground_cache_size_on_critical_pressure = 1;
|
||||
int background_cache_size_on_critical_pressure = 0;
|
||||
int expected_cached_pages = 4;
|
||||
};
|
||||
|
||||
const PolicyTestParam kPolicyTestParams[] = {
|
||||
// When BFCachePolicy is disabled, the bfcached pages are kept as it is.
|
||||
{.enable_policy = false},
|
||||
// Tab foregrounded, moderate memory pressure.
|
||||
{.expected_cached_pages = 3},
|
||||
// Tab backgrounded, moderate memory pressure.
|
||||
{.tab_backgrounded = true, .expected_cached_pages = 2},
|
||||
// Tab foregrounded, critical memory pressure.
|
||||
{.memory_pressure_level =
|
||||
MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_CRITICAL,
|
||||
.expected_cached_pages = 1},
|
||||
// Tab backgrounded, critical memory pressure.
|
||||
{.memory_pressure_level =
|
||||
MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_CRITICAL,
|
||||
.tab_backgrounded = true,
|
||||
.expected_cached_pages = 0},
|
||||
// Tab foregrounded, moderate memory pressure, cache limit is -1 (no limit).
|
||||
{.foreground_cache_size_on_moderate_pressure = -1},
|
||||
// Tab backgrounded, moderate memory pressure, cache limit is -1 (no limit).
|
||||
{.tab_backgrounded = true,
|
||||
.background_cache_size_on_moderate_pressure = -1},
|
||||
// Tab foregrounded, critical memory pressure, cache limit is -1 (no limit).
|
||||
{.memory_pressure_level =
|
||||
MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_CRITICAL,
|
||||
.foreground_cache_size_on_critical_pressure = -1},
|
||||
// Tab backgrounded, critical memory pressure, cache limit is -1 (no limit).
|
||||
{.memory_pressure_level =
|
||||
MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_CRITICAL,
|
||||
.tab_backgrounded = true,
|
||||
.background_cache_size_on_critical_pressure = -1}};
|
||||
|
||||
class BFCachePolicyBrowserTest
|
||||
: public InProcessBrowserTest,
|
||||
public ::testing::WithParamInterface<PolicyTestParams> {
|
||||
public ::testing::WithParamInterface<PolicyTestParam> {
|
||||
public:
|
||||
~BFCachePolicyBrowserTest() override = default;
|
||||
|
||||
void SetUpCommandLine(base::CommandLine* command_line) override {
|
||||
EnableFeature(::features::kBackForwardCache,
|
||||
{{"TimeToLiveInBackForwardCacheInSeconds", "3600"},
|
||||
{{"foreground_cache_size", "10"},
|
||||
{"cache_size", "10"},
|
||||
{"TimeToLiveInBackForwardCacheInSeconds", "3600"},
|
||||
{"ignore_outstanding_network_request_for_testing", "true"}});
|
||||
DisableFeature(::features::kBackForwardCacheMemoryControls);
|
||||
// Disable discarding of pages directly from PerformanceManager for test.
|
||||
DisableFeature(::performance_manager::features::
|
||||
kUrgentDiscardingFromPerformanceManager);
|
||||
// Occlusion can cause the web_contents to be marked visible between the
|
||||
// time the test calls WasHidden and BFCachePolicy::MaybeFlushBFCache is
|
||||
// called, which kills the timer set by BFCachePolicy::OnIsVisibleChanged.
|
||||
@ -62,8 +106,18 @@ class BFCachePolicyBrowserTest
|
||||
if (GetParam().enable_policy) {
|
||||
EnableFeature(
|
||||
performance_manager::features::kBFCachePerformanceManagerPolicy,
|
||||
{{"flush_on_moderate_pressure",
|
||||
GetParam().flush_on_moderate_pressure ? "true" : "false"}});
|
||||
{{"foreground_cache_size_on_moderate_pressure",
|
||||
base::NumberToString(
|
||||
GetParam().foreground_cache_size_on_moderate_pressure)},
|
||||
{"background_cache_size_on_moderate_pressure",
|
||||
base::NumberToString(
|
||||
GetParam().background_cache_size_on_moderate_pressure)},
|
||||
{"foreground_cache_size_on_critical_pressure",
|
||||
base::NumberToString(
|
||||
GetParam().foreground_cache_size_on_critical_pressure)},
|
||||
{"background_cache_size_on_critical_pressure",
|
||||
base::NumberToString(
|
||||
GetParam().background_cache_size_on_critical_pressure)}});
|
||||
} else {
|
||||
DisableFeature(
|
||||
performance_manager::features::kBFCachePerformanceManagerPolicy);
|
||||
@ -97,23 +151,23 @@ class BFCachePolicyBrowserTest
|
||||
return web_contents()->GetMainFrame();
|
||||
}
|
||||
|
||||
void VerifyEvictionExpectation(bool should_be_evicted,
|
||||
content::RenderFrameHostWrapper& rfh) {
|
||||
if (should_be_evicted) {
|
||||
// When the page is evicted the RenderFrame will be deleted.
|
||||
ASSERT_TRUE(rfh.WaitUntilRenderFrameDeleted());
|
||||
} else {
|
||||
// BFCachePolicy runs asynchronously. So we need to wait for the result
|
||||
// before checking.
|
||||
base::RunLoop run_loop;
|
||||
base::SequencedTaskRunnerHandle::Get()->PostTask(
|
||||
FROM_HERE, base::BindLambdaForTesting([&]() {
|
||||
EXPECT_EQ(
|
||||
rfh->GetLifecycleState(),
|
||||
content::RenderFrameHost::LifecycleState::kInBackForwardCache);
|
||||
run_loop.Quit();
|
||||
}));
|
||||
run_loop.Run();
|
||||
void VerifyEvictionExpectation(
|
||||
std::vector<content::RenderFrameHostWrapper>& render_frame_hosts) {
|
||||
// Wait for memory pressure signal processed and handled by BFCachePolicy.
|
||||
content::RunAllTasksUntilIdle();
|
||||
|
||||
size_t expected_deleted_pages =
|
||||
render_frame_hosts.size() - GetParam().expected_cached_pages;
|
||||
|
||||
for (size_t i = 0; i < render_frame_hosts.size(); i++) {
|
||||
content::RenderFrameHostWrapper& rfh = render_frame_hosts[i];
|
||||
if (i < expected_deleted_pages) {
|
||||
ASSERT_TRUE(rfh.IsRenderFrameDeleted());
|
||||
} else {
|
||||
EXPECT_EQ(
|
||||
rfh->GetLifecycleState(),
|
||||
content::RenderFrameHost::LifecycleState::kInBackForwardCache);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -128,60 +182,44 @@ class BFCachePolicyBrowserTest
|
||||
|
||||
IN_PROC_BROWSER_TEST_P(BFCachePolicyBrowserTest, CacheFlushed) {
|
||||
memory_pressure::test::FakeMemoryPressureMonitor fake_memory_pressure_monitor;
|
||||
const GURL url_a(embedded_test_server()->GetURL("a.com", "/title1.html"));
|
||||
const GURL url_b(embedded_test_server()->GetURL("b.com", "/title1.html"));
|
||||
const std::vector<std::string> hostnames{"a.com", "b.com", "c.com", "d.com"};
|
||||
std::vector<content::RenderFrameHostWrapper> render_frame_hosts;
|
||||
render_frame_hosts.reserve(hostnames.size());
|
||||
for (std::string hostname : hostnames) {
|
||||
const GURL url(embedded_test_server()->GetURL(hostname, "/title1.html"));
|
||||
EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
|
||||
render_frame_hosts.emplace_back(
|
||||
content::RenderFrameHostWrapper(top_frame_host()));
|
||||
}
|
||||
|
||||
const GURL url(embedded_test_server()->GetURL("last.com", "/title1.html"));
|
||||
EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
|
||||
content::RenderFrameHostWrapper last_rfh =
|
||||
content::RenderFrameHostWrapper(top_frame_host());
|
||||
|
||||
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
|
||||
|
||||
// Navigate to A.
|
||||
EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), url_a));
|
||||
content::RenderFrameHostWrapper rfh_a(top_frame_host());
|
||||
|
||||
// Navigate to B.
|
||||
EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), url_b));
|
||||
content::RenderFrameHostWrapper rfh_b(top_frame_host());
|
||||
|
||||
// Ensure A is cached.
|
||||
EXPECT_EQ(rfh_a->GetLifecycleState(),
|
||||
content::RenderFrameHost::LifecycleState::kInBackForwardCache);
|
||||
|
||||
if (GetParam().scenario == "FlushOnModerateMemoryPressure") {
|
||||
// A moderate memory pressure signal will evict the page from BFCache.
|
||||
fake_memory_pressure_monitor.SetAndNotifyMemoryPressure(
|
||||
base::MemoryPressureListener::MemoryPressureLevel::
|
||||
MEMORY_PRESSURE_LEVEL_MODERATE);
|
||||
VerifyEvictionExpectation(
|
||||
/* should_be_evicted = */
|
||||
(GetParam().enable_policy && GetParam().flush_on_moderate_pressure),
|
||||
rfh_a);
|
||||
} else if (GetParam().scenario == "FlushOnCriticalMemoryPressure") {
|
||||
// A critical memory pressure signal will evict the page from BFCache.
|
||||
fake_memory_pressure_monitor.SetAndNotifyMemoryPressure(
|
||||
base::MemoryPressureListener::MemoryPressureLevel::
|
||||
MEMORY_PRESSURE_LEVEL_CRITICAL);
|
||||
VerifyEvictionExpectation(
|
||||
/* should_be_evicted = */ GetParam().enable_policy, rfh_a);
|
||||
} else {
|
||||
NOTREACHED();
|
||||
if (GetParam().tab_backgrounded) {
|
||||
web_contents()->WasHidden();
|
||||
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::HIDDEN);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<PolicyTestParams> BFCachePolicyBrowserTestValues() {
|
||||
std::vector<PolicyTestParams> test_cases;
|
||||
|
||||
for (const std::string scenario :
|
||||
{"FlushOnModerateMemoryPressure", "FlushOnCriticalMemoryPressure"}) {
|
||||
test_cases.push_back({.scenario = scenario});
|
||||
test_cases.push_back({.scenario = scenario, .enable_policy = true});
|
||||
test_cases.push_back({.scenario = scenario,
|
||||
.enable_policy = true,
|
||||
.flush_on_moderate_pressure = true});
|
||||
// Ensure pages are cached.
|
||||
for (const auto& render_frame_host : render_frame_hosts) {
|
||||
EXPECT_EQ(render_frame_host->GetLifecycleState(),
|
||||
content::RenderFrameHost::LifecycleState::kInBackForwardCache);
|
||||
}
|
||||
return test_cases;
|
||||
// Ensure the last page is not cached.
|
||||
EXPECT_EQ(last_rfh->GetLifecycleState(),
|
||||
content::RenderFrameHost::LifecycleState::kActive);
|
||||
|
||||
fake_memory_pressure_monitor.SetAndNotifyMemoryPressure(
|
||||
GetParam().memory_pressure_level);
|
||||
|
||||
VerifyEvictionExpectation(render_frame_hosts);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(All,
|
||||
BFCachePolicyBrowserTest,
|
||||
testing::ValuesIn(BFCachePolicyBrowserTestValues()));
|
||||
testing::ValuesIn(kPolicyTestParams));
|
||||
|
||||
} // namespace performance_manager::policies
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "base/memory/memory_pressure_listener.h"
|
||||
#include "base/notreached.h"
|
||||
#include "base/task/task_traits.h"
|
||||
#include "base/time/time.h"
|
||||
#include "base/timer/timer.h"
|
||||
@ -22,15 +23,44 @@ namespace performance_manager::policies {
|
||||
|
||||
namespace {
|
||||
|
||||
// Whether or not the BFCache of all pages should be flushed when the system
|
||||
// is under *moderate* memory pressure. The policy always flushes the bfcache
|
||||
// under critical pressure.
|
||||
bool IsFlushOnModeratePressureEnabled() {
|
||||
static constexpr base::FeatureParam<bool> flush_on_moderate_pressure{
|
||||
&features::kBFCachePerformanceManagerPolicy, "flush_on_moderate_pressure",
|
||||
false};
|
||||
// The foregrounded tab's cache limit on moderate memory pressure. The negative
|
||||
// value means no limit.
|
||||
int ForegroundCacheSizeOnModeratePressure() {
|
||||
static constexpr base::FeatureParam<int>
|
||||
foreground_cache_size_on_moderate_pressure{
|
||||
&features::kBFCachePerformanceManagerPolicy,
|
||||
"foreground_cache_size_on_moderate_pressure", 3};
|
||||
return foreground_cache_size_on_moderate_pressure.Get();
|
||||
}
|
||||
|
||||
return flush_on_moderate_pressure.Get();
|
||||
// The backgrounded tab's cache limit on moderate memory pressure. The negative
|
||||
// value means no limit.
|
||||
int BackgroundCacheSizeOnModeratePressure() {
|
||||
static constexpr base::FeatureParam<int>
|
||||
background_cache_size_on_moderate_pressure{
|
||||
&features::kBFCachePerformanceManagerPolicy,
|
||||
"background_cache_size_on_moderate_pressure", 1};
|
||||
return background_cache_size_on_moderate_pressure.Get();
|
||||
}
|
||||
|
||||
// The foregrounded tab's cache limit on critical memory pressure. The negative
|
||||
// value means no limit.
|
||||
int ForegroundCacheSizeOnCriticalPressure() {
|
||||
static constexpr base::FeatureParam<int>
|
||||
foreground_cache_size_on_critical_pressure{
|
||||
&features::kBFCachePerformanceManagerPolicy,
|
||||
"foreground_cache_size_on_critical_pressure", 0};
|
||||
return foreground_cache_size_on_critical_pressure.Get();
|
||||
}
|
||||
|
||||
// The backgrounded tab's cache limit on critical memory pressure. The negative
|
||||
// value means no limit.
|
||||
int BackgroundCacheSizeOnCriticalPressure() {
|
||||
static constexpr base::FeatureParam<int>
|
||||
background_cache_size_on_critical_pressure{
|
||||
&features::kBFCachePerformanceManagerPolicy,
|
||||
"background_cache_size_on_critical_pressure", 0};
|
||||
return background_cache_size_on_critical_pressure.Get();
|
||||
}
|
||||
|
||||
bool PageMightHaveFramesInBFCache(const PageNode* page_node) {
|
||||
@ -45,32 +75,52 @@ bool PageMightHaveFramesInBFCache(const PageNode* page_node) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void MaybeFlushBFCacheOnUIThread(const WebContentsProxy& contents_proxy) {
|
||||
using MemoryPressureLevel = base::MemoryPressureListener::MemoryPressureLevel;
|
||||
|
||||
void MaybeFlushBFCacheOnUIThread(const WebContentsProxy& contents_proxy,
|
||||
MemoryPressureLevel memory_pressure_level) {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
||||
content::WebContents* const content = contents_proxy.Get();
|
||||
if (!content)
|
||||
return;
|
||||
|
||||
int cache_size = -1;
|
||||
bool foregrounded =
|
||||
(content->GetVisibility() == content::Visibility::VISIBLE);
|
||||
switch (memory_pressure_level) {
|
||||
case MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_MODERATE:
|
||||
cache_size = foregrounded ? ForegroundCacheSizeOnModeratePressure()
|
||||
: BackgroundCacheSizeOnModeratePressure();
|
||||
break;
|
||||
case MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_CRITICAL:
|
||||
cache_size = foregrounded ? ForegroundCacheSizeOnCriticalPressure()
|
||||
: BackgroundCacheSizeOnCriticalPressure();
|
||||
break;
|
||||
default:
|
||||
NOTREACHED();
|
||||
}
|
||||
// Do not flush BFCache if cache_size is negative (such as -1).
|
||||
if (cache_size < 0)
|
||||
return;
|
||||
|
||||
// Do not flush the BFCache if there's a pending navigation as this could stop
|
||||
// it.
|
||||
// TODO(sebmarchand): Check if this is really needed.
|
||||
auto& navigation_controller = content->GetController();
|
||||
if (!navigation_controller.GetPendingEntry())
|
||||
navigation_controller.GetBackForwardCache().Flush();
|
||||
navigation_controller.GetBackForwardCache().Prune(cache_size);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
BFCachePolicy::BFCachePolicy()
|
||||
: flush_on_moderate_pressure_{IsFlushOnModeratePressureEnabled()} {}
|
||||
|
||||
BFCachePolicy::~BFCachePolicy() = default;
|
||||
|
||||
void BFCachePolicy::MaybeFlushBFCache(const PageNode* page_node) {
|
||||
void BFCachePolicy::MaybeFlushBFCache(
|
||||
const PageNode* page_node,
|
||||
MemoryPressureLevel memory_pressure_level) {
|
||||
DCHECK(page_node);
|
||||
content::GetUIThreadTaskRunner({})->PostTask(
|
||||
FROM_HERE, base::BindOnce(&MaybeFlushBFCacheOnUIThread,
|
||||
page_node->GetContentsProxy()));
|
||||
FROM_HERE,
|
||||
base::BindOnce(&MaybeFlushBFCacheOnUIThread,
|
||||
page_node->GetContentsProxy(), memory_pressure_level));
|
||||
}
|
||||
|
||||
void BFCachePolicy::OnPassedToGraph(Graph* graph) {
|
||||
@ -84,25 +134,17 @@ void BFCachePolicy::OnTakenFromGraph(Graph* graph) {
|
||||
graph_ = nullptr;
|
||||
}
|
||||
|
||||
void BFCachePolicy::OnMemoryPressure(
|
||||
base::MemoryPressureListener::MemoryPressureLevel new_level) {
|
||||
void BFCachePolicy::OnMemoryPressure(MemoryPressureLevel new_level) {
|
||||
// This shouldn't happen but add the check anyway in case the API changes.
|
||||
if (new_level == base::MemoryPressureListener::MemoryPressureLevel::
|
||||
MEMORY_PRESSURE_LEVEL_NONE) {
|
||||
if (new_level == MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (new_level == base::MemoryPressureListener::MemoryPressureLevel::
|
||||
MEMORY_PRESSURE_LEVEL_MODERATE &&
|
||||
!flush_on_moderate_pressure_) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Flush the cache of all pages.
|
||||
// Apply the cache limit to all pages.
|
||||
for (auto* page_node : graph_->GetAllPageNodes()) {
|
||||
if (page_node->GetPageState() == PageNode::PageState::kActive &&
|
||||
PageMightHaveFramesInBFCache(page_node)) {
|
||||
MaybeFlushBFCache(page_node);
|
||||
MaybeFlushBFCache(page_node, new_level);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,19 +18,20 @@ namespace performance_manager::policies {
|
||||
class BFCachePolicy : public GraphOwned,
|
||||
public SystemNode::ObserverDefaultImpl {
|
||||
public:
|
||||
BFCachePolicy();
|
||||
BFCachePolicy() = default;
|
||||
BFCachePolicy(const BFCachePolicy&) = delete;
|
||||
BFCachePolicy(BFCachePolicy&&) = delete;
|
||||
BFCachePolicy& operator=(const BFCachePolicy&) = delete;
|
||||
BFCachePolicy& operator=(BFCachePolicy&&) = delete;
|
||||
~BFCachePolicy() override;
|
||||
~BFCachePolicy() override = default;
|
||||
|
||||
protected:
|
||||
using MemoryPressureLevel = base::MemoryPressureListener::MemoryPressureLevel;
|
||||
|
||||
// Try to flush the BFCache associated with |page_node|. This will be a no-op
|
||||
// if there's a pending navigation.
|
||||
virtual void MaybeFlushBFCache(const PageNode* page_node);
|
||||
|
||||
bool flush_on_moderate_pressure_;
|
||||
virtual void MaybeFlushBFCache(const PageNode* page_node,
|
||||
MemoryPressureLevel memory_pressure_level);
|
||||
|
||||
private:
|
||||
// GraphOwned implementation:
|
||||
@ -38,8 +39,7 @@ class BFCachePolicy : public GraphOwned,
|
||||
void OnTakenFromGraph(Graph* graph) override;
|
||||
|
||||
// SystemNodeObserver:
|
||||
void OnMemoryPressure(
|
||||
base::MemoryPressureListener::MemoryPressureLevel new_level) override;
|
||||
void OnMemoryPressure(MemoryPressureLevel new_level) override;
|
||||
|
||||
raw_ptr<Graph> graph_;
|
||||
};
|
||||
|
@ -13,20 +13,22 @@
|
||||
#include "testing/gmock/include/gmock/gmock.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
namespace performance_manager {
|
||||
namespace policies {
|
||||
namespace performance_manager::policies {
|
||||
|
||||
namespace {
|
||||
|
||||
// Mock version of a performance_manager::BFCachePolicy.
|
||||
class LenientMockBFCachePolicy : public BFCachePolicy {
|
||||
public:
|
||||
LenientMockBFCachePolicy() { flush_on_moderate_pressure_ = true; }
|
||||
LenientMockBFCachePolicy() = default;
|
||||
~LenientMockBFCachePolicy() override = default;
|
||||
LenientMockBFCachePolicy(const LenientMockBFCachePolicy& other) = delete;
|
||||
LenientMockBFCachePolicy& operator=(const LenientMockBFCachePolicy&) = delete;
|
||||
MOCK_METHOD1(MaybeFlushBFCache, void(const PageNode* page_node));
|
||||
MOCK_METHOD2(MaybeFlushBFCache,
|
||||
void(const PageNode* page_node,
|
||||
MemoryPressureLevel memory_pressure_level));
|
||||
};
|
||||
using MemoryPressureLevel = base::MemoryPressureListener::MemoryPressureLevel;
|
||||
using MockBFCachePolicy = ::testing::StrictMock<LenientMockBFCachePolicy>;
|
||||
|
||||
} // namespace
|
||||
@ -74,18 +76,21 @@ TEST_F(BFCachePolicyTest, BFCacheFlushedOnMemoryPressure) {
|
||||
page_node_->SetLoadingState(PageNode::LoadingState::kLoadedBusy);
|
||||
::testing::Mock::VerifyAndClearExpectations(policy_);
|
||||
|
||||
EXPECT_CALL(*policy_, MaybeFlushBFCache(page_node_.get()));
|
||||
EXPECT_CALL(
|
||||
*policy_,
|
||||
MaybeFlushBFCache(page_node_.get(),
|
||||
MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_MODERATE));
|
||||
GetSystemNode()->OnMemoryPressureForTesting(
|
||||
base::MemoryPressureListener::MemoryPressureLevel::
|
||||
MEMORY_PRESSURE_LEVEL_MODERATE);
|
||||
MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_MODERATE);
|
||||
::testing::Mock::VerifyAndClearExpectations(policy_);
|
||||
|
||||
EXPECT_CALL(*policy_, MaybeFlushBFCache(page_node_.get()));
|
||||
EXPECT_CALL(
|
||||
*policy_,
|
||||
MaybeFlushBFCache(page_node_.get(),
|
||||
MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_CRITICAL));
|
||||
GetSystemNode()->OnMemoryPressureForTesting(
|
||||
base::MemoryPressureListener::MemoryPressureLevel::
|
||||
MEMORY_PRESSURE_LEVEL_CRITICAL);
|
||||
MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_CRITICAL);
|
||||
::testing::Mock::VerifyAndClearExpectations(policy_);
|
||||
}
|
||||
|
||||
} // namespace policies
|
||||
} // namespace performance_manager
|
||||
} // namespace performance_manager::policies
|
||||
|
@ -1054,6 +1054,11 @@ void BackForwardCacheImpl::EnforceCacheSizeLimit() {
|
||||
/*foregrounded_only=*/false);
|
||||
}
|
||||
|
||||
void BackForwardCacheImpl::Prune(size_t limit) {
|
||||
EnforceCacheSizeLimitInternal(limit,
|
||||
/*foregrounded_only=*/false);
|
||||
}
|
||||
|
||||
size_t BackForwardCacheImpl::EnforceCacheSizeLimitInternal(
|
||||
size_t limit,
|
||||
bool foregrounded_only) {
|
||||
|
@ -310,6 +310,7 @@ class CONTENT_EXPORT BackForwardCacheImpl
|
||||
|
||||
// BackForwardCache overrides:
|
||||
void Flush() override;
|
||||
void Prune(size_t limit) override;
|
||||
void DisableForTesting(DisableForTestingReason reason) override;
|
||||
|
||||
// RenderProcessHostInternalObserver methods
|
||||
|
@ -143,6 +143,10 @@ class CONTENT_EXPORT BackForwardCache {
|
||||
// Evict all entries from the BackForwardCache.
|
||||
virtual void Flush() = 0;
|
||||
|
||||
// Evict back/forward cache entries from the least recently used ones until
|
||||
// the cache is within the given size limit.
|
||||
virtual void Prune(size_t limit) = 0;
|
||||
|
||||
// Disables the BackForwardCache so that no documents will be stored/served.
|
||||
// This allows tests to "force" not using the BackForwardCache, this can be
|
||||
// useful when:
|
||||
|
Reference in New Issue
Block a user