blob: 0f2338c4a5cde3141676f13a2d4ea57880d6be41 [file] [log] [blame]
// Copyright 2021 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 <memory>
#include <string>
#include "base/callback_forward.h"
#include "base/files/file_path.h"
#include "base/memory/memory_pressure_listener.h"
#include "base/memory/memory_pressure_monitor.h"
#include "base/run_loop.h"
#include "base/test/scoped_feature_list.h"
#include "base/util/memory_pressure/fake_memory_pressure_monitor.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/performance_manager/public/features.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/visibility.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/content_features.h"
#include "content/public/test/browser_test.h"
#include "net/dns/mock_host_resolver.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace performance_manager {
namespace policies {
namespace {
struct PolicyTestParams {
const std::string scenario;
bool enable_policy = false;
bool enable_trim_on_moderate_pressure = false;
};
class BFCachePolicyBrowserTest
: public InProcessBrowserTest,
public ::testing::WithParamInterface<PolicyTestParams> {
public:
~BFCachePolicyBrowserTest() override = default;
void SetUpCommandLine(base::CommandLine* command_line) override {
EnableFeature(::features::kBackForwardCache,
{{"TimeToLiveInBackForwardCacheInSeconds", "3600"},
{"ignore_outstanding_network_request_for_testing", "true"}});
DisableFeature(::features::kBackForwardCacheMemoryControls);
if (GetParam().enable_policy) {
EnableFeature(
performance_manager::features::kBFCachePerformanceManagerPolicy,
{{"flush_on_moderate_pressure",
GetParam().enable_trim_on_moderate_pressure ? "true" : "false"}});
} else {
DisableFeature(
performance_manager::features::kBFCachePerformanceManagerPolicy);
}
feature_list_.InitWithFeaturesAndParameters(enabled_features_,
disabled_features_);
}
void SetUpOnMainThread() override {
InProcessBrowserTest::SetUpOnMainThread();
host_resolver()->AddRule("*", "127.0.0.1");
ASSERT_TRUE(embedded_test_server()->Start());
}
protected:
void EnableFeature(const base::Feature& feature,
const base::FieldTrialParams& params) {
enabled_features_.emplace_back(feature, params);
}
void DisableFeature(const base::Feature& feature) {
disabled_features_.emplace_back(feature);
}
content::WebContents* web_contents() const {
return browser()->tab_strip_model()->GetActiveWebContents();
}
content::RenderFrameHost* top_frame_host() {
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.
rfh.WaitUntilRenderFrameDeleted();
} else {
EXPECT_EQ(rfh->GetLifecycleState(),
content::RenderFrameHost::LifecycleState::kInBackForwardCache);
}
}
private:
base::test::ScopedFeatureList feature_list_;
std::vector<base::test::ScopedFeatureList::FeatureAndParams>
enabled_features_;
std::vector<base::Feature> disabled_features_;
};
} // namespace
IN_PROC_BROWSER_TEST_P(BFCachePolicyBrowserTest, CacheFlushed) {
util::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"));
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 == "FlushWhenTabBackgrounded") {
// Backgrounding the page will evict it from BFCache.
web_contents()->WasHidden();
VerifyEvictionExpectation(
/* should_be_evicted = */ GetParam().enable_policy, rfh_a);
} else if (GetParam().scenario == "FlushWhenTabBackgroundDuringNavigation") {
web_contents()->GetController().GoBack();
// Make the tab backgrounded before the back navigation completes. |rfh_a|
// will become the active frame and the cache will be flushed (i.e. |rfh_b|
// will be deleted).
web_contents()->WasHidden();
EXPECT_TRUE(WaitForLoadStop(web_contents()));
EXPECT_EQ(rfh_a.get(), top_frame_host());
VerifyEvictionExpectation(
/* should_be_evicted = */ GetParam().enable_policy, rfh_b);
} else 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().enable_trim_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);
}
}
std::vector<PolicyTestParams> BFCachePolicyBrowserTestValues() {
const std::vector<std::string> kTestScenarios = {
"FlushWhenTabBackgrounded", "FlushWhenTabBackgroundDuringNavigation",
"FlushOnModerateMemoryPressure", "FlushOnCriticalMemoryPressure"};
std::vector<PolicyTestParams> test_cases;
for (const auto& test_scenario : kTestScenarios) {
test_cases.push_back({.scenario = test_scenario, .enable_policy = false});
// Test the policy with |flush_on_moderate_pressure| enabled.
test_cases.push_back({.scenario = test_scenario,
.enable_policy = true,
.enable_trim_on_moderate_pressure = true});
// Test the policy with |flush_on_moderate_pressure| disabled.
test_cases.push_back({.scenario = test_scenario,
.enable_policy = true,
.enable_trim_on_moderate_pressure = false});
}
return test_cases;
}
INSTANTIATE_TEST_SUITE_P(All,
BFCachePolicyBrowserTest,
testing::ValuesIn(BFCachePolicyBrowserTestValues()));
} // namespace policies
} // namespace performance_manager