Commit 2db43e77 authored by Hajime Hoshi's avatar Hajime Hoshi Committed by Chromium LUCI CQ

BackForwardCache: Add a flag parameter supported_features

This CL adds a new flag parameter supported_features to BackForwardCache
feature. This parameter can specify the set of the features to be
allowed with back-forward cache. This enables us to enable the feature
remotely.

Bug: 1155449
Change-Id: Idb7eb55b114af688533ba2e069a9334714be725c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2573850Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Reviewed-by: default avatarAlexander Timin <altimin@chromium.org>
Reviewed-by: default avatarFergal Daly <fergal@chromium.org>
Commit-Queue: Hajime Hoshi <hajimehoshi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#835571}
parent df4f0d59
...@@ -8702,4 +8702,126 @@ IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTestWithFileSystemAPISupported, ...@@ -8702,4 +8702,126 @@ IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTestWithFileSystemAPISupported,
FROM_HERE); FROM_HERE);
} }
class BackForwardCacheBrowserTestWithSupportedFeatures
: public BackForwardCacheBrowserTest {
protected:
void SetUpCommandLine(base::CommandLine* command_line) override {
EnableFeatureAndSetParams(features::kBackForwardCache, "supported_features",
"WebFileSystem,WebLocks");
BackForwardCacheBrowserTest::SetUpCommandLine(command_line);
}
};
IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTestWithSupportedFeatures,
CacheWithFileSystemAPI) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url_a(embedded_test_server()->GetURL("/fileapi/request_test.html"));
GURL url_b(embedded_test_server()->GetURL("b.com", "/title1.html"));
// 1) Navigate to the page A with WebFileSystem usage.
EXPECT_TRUE(NavigateToURL(shell(), url_a));
RenderFrameHostImpl* rfh_a = current_frame_host();
RenderFrameDeletedObserver deleted(rfh_a);
// 2) Navigate away.
EXPECT_TRUE(NavigateToURL(shell(), url_b));
EXPECT_FALSE(deleted.deleted());
EXPECT_TRUE(rfh_a->IsInBackForwardCache());
// 3) Go back to the page A
web_contents()->GetController().GoBack();
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
EXPECT_EQ(rfh_a, current_frame_host());
ExpectOutcome(BackForwardCacheMetrics::HistoryNavigationOutcome::kRestored,
FROM_HERE);
// 4) Use WebLock
EXPECT_TRUE(ExecJs(rfh_a, R"(
const never_resolved = new Promise(resolve => {});
new Promise(continue_test => {
navigator.locks.request('test', async () => {
continue_test();
await never_resolved;
});
})
)"));
// 5) Navigate away again.
EXPECT_TRUE(NavigateToURL(shell(), url_b));
EXPECT_FALSE(deleted.deleted());
EXPECT_TRUE(rfh_a->IsInBackForwardCache());
// 6) Go back to the page A again.
web_contents()->GetController().GoBack();
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
EXPECT_EQ(rfh_a, current_frame_host());
ExpectOutcome(BackForwardCacheMetrics::HistoryNavigationOutcome::kRestored,
FROM_HERE);
}
class BackForwardCacheBrowserTestWithNoSupportedFeatures
: public BackForwardCacheBrowserTest {
protected:
void SetUpCommandLine(base::CommandLine* command_line) override {
// Specify empty supported features explicitly.
EnableFeatureAndSetParams(features::kBackForwardCache, "supported_features",
"");
BackForwardCacheBrowserTest::SetUpCommandLine(command_line);
}
};
IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTestWithNoSupportedFeatures,
DontCacheWithFileSystemAPI) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url_a(embedded_test_server()->GetURL("/fileapi/request_test.html"));
GURL url_b(embedded_test_server()->GetURL("b.com", "/title1.html"));
// 1) Navigate to the page A with WebFileSystem usage.
EXPECT_TRUE(NavigateToURL(shell(), url_a));
RenderFrameHostImpl* rfh_a1 = current_frame_host();
RenderFrameDeletedObserver deleted_a1(rfh_a1);
// 2) Navigate away.
EXPECT_TRUE(NavigateToURL(shell(), url_b));
EXPECT_TRUE(deleted_a1.deleted());
// 3) Go back to the page A
web_contents()->GetController().GoBack();
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
ExpectNotRestored(
{BackForwardCacheMetrics::NotRestoredReason::kBlocklistedFeatures},
FROM_HERE);
ExpectBlocklistedFeature(
blink::scheduler::WebSchedulerTrackedFeature::kWebFileSystem, FROM_HERE);
RenderFrameHostImpl* rfh_a2 = current_frame_host();
RenderFrameDeletedObserver deleted_a2(rfh_a2);
// 4) Use WebLock
EXPECT_TRUE(ExecJs(rfh_a2, R"(
const never_resolved = new Promise(resolve => {});
new Promise(continue_test => {
navigator.locks.request('test', async () => {
continue_test();
await never_resolved;
});
})
)"));
// 5) Navigate away again.
EXPECT_TRUE(NavigateToURL(shell(), url_b));
EXPECT_TRUE(deleted_a2.deleted());
// 6) Go back to the page A again.
web_contents()->GetController().GoBack();
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
ExpectNotRestored(
{BackForwardCacheMetrics::NotRestoredReason::kBlocklistedFeatures},
FROM_HERE);
ExpectBlocklistedFeatures(
{blink::scheduler::WebSchedulerTrackedFeature::kWebFileSystem,
blink::scheduler::WebSchedulerTrackedFeature::kWebLocks},
FROM_HERE);
}
} // namespace content } // namespace content
...@@ -18,7 +18,7 @@ std::string DescribeFeatures(uint64_t blocklisted_features) { ...@@ -18,7 +18,7 @@ std::string DescribeFeatures(uint64_t blocklisted_features) {
for (size_t i = 0; for (size_t i = 0;
i <= static_cast<size_t>(WebSchedulerTrackedFeature::kMaxValue); ++i) { i <= static_cast<size_t>(WebSchedulerTrackedFeature::kMaxValue); ++i) {
if (blocklisted_features & (1 << i)) { if (blocklisted_features & (1 << i)) {
features.push_back(blink::scheduler::FeatureToString( features.push_back(blink::scheduler::FeatureToHumanReadableString(
static_cast<WebSchedulerTrackedFeature>(i))); static_cast<WebSchedulerTrackedFeature>(i)));
} }
} }
......
...@@ -96,6 +96,31 @@ bool IsFileSystemSupported() { ...@@ -96,6 +96,31 @@ bool IsFileSystemSupported() {
return file_system_api_supported.Get(); return file_system_api_supported.Get();
} }
uint64_t SupportedFeaturesBitmaskImpl() {
if (!DeviceHasEnoughMemoryForBackForwardCache())
return 0;
static constexpr base::FeatureParam<std::string> supported_features(
&features::kBackForwardCache, "supported_features", "");
std::vector<std::string> tokens =
base::SplitString(supported_features.Get(), ",", base::TRIM_WHITESPACE,
base::SPLIT_WANT_NONEMPTY);
uint64_t mask = 0;
for (const std::string& token : tokens) {
auto feature = blink::scheduler::StringToFeature(token);
DCHECK(feature.has_value()) << "invalid feature string: " << token;
if (feature.has_value()) {
mask |= blink::scheduler::FeatureToBit(feature.value());
}
}
return mask;
}
uint64_t SupportedFeaturesBitmask() {
static uint64_t mask = SupportedFeaturesBitmaskImpl();
return mask;
}
bool IgnoresOutstandingNetworkRequestForTesting() { bool IgnoresOutstandingNetworkRequestForTesting() {
if (!DeviceHasEnoughMemoryForBackForwardCache()) if (!DeviceHasEnoughMemoryForBackForwardCache())
return false; return false;
...@@ -187,6 +212,8 @@ uint64_t GetDisallowedFeatures(RenderFrameHostImpl* rfh, ...@@ -187,6 +212,8 @@ uint64_t GetDisallowedFeatures(RenderFrameHostImpl* rfh,
result &= blink::scheduler::StickyFeaturesBitmask(); result &= blink::scheduler::StickyFeaturesBitmask();
} }
result &= ~SupportedFeaturesBitmask();
return result; return result;
} }
......
...@@ -272,6 +272,7 @@ source_set("common_unittests_sources") { ...@@ -272,6 +272,7 @@ source_set("common_unittests_sources") {
"origin_trials/trial_token_validator_unittest.cc", "origin_trials/trial_token_validator_unittest.cc",
"page/content_to_visible_time_reporter_unittest.cc", "page/content_to_visible_time_reporter_unittest.cc",
"page_state/page_state_serialization_unittest.cc", "page_state/page_state_serialization_unittest.cc",
"scheduler/web_scheduler_tracked_feature_unittest.cc",
"service_worker/service_worker_scope_match_unittest.cc", "service_worker/service_worker_scope_match_unittest.cc",
"test/run_all_unittests.cc", "test/run_all_unittests.cc",
"tokens/multi_token_unittest.cc", "tokens/multi_token_unittest.cc",
......
// 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 "third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace blink {
namespace scheduler {
TEST(WebSchedulerTrackedFeatureTest, StringToFeature) {
ASSERT_EQ(WebSchedulerTrackedFeature::kWebFileSystem,
StringToFeature("WebFileSystem"));
ASSERT_EQ(WebSchedulerTrackedFeature::kDocumentLoaded,
StringToFeature("DocumentLoaded"));
ASSERT_EQ(base::nullopt, StringToFeature("FeatureThatNeverExists"));
}
} // namespace scheduler
} // namespace blink
...@@ -6,7 +6,8 @@ ...@@ -6,7 +6,8 @@
#define THIRD_PARTY_BLINK_PUBLIC_COMMON_SCHEDULER_WEB_SCHEDULER_TRACKED_FEATURE_H_ #define THIRD_PARTY_BLINK_PUBLIC_COMMON_SCHEDULER_WEB_SCHEDULER_TRACKED_FEATURE_H_
#include <stdint.h> #include <stdint.h>
#include <string>
#include "base/optional.h"
#include "third_party/blink/public/common/common_export.h" #include "third_party/blink/public/common/common_export.h"
namespace blink { namespace blink {
...@@ -106,9 +107,12 @@ static_assert(static_cast<uint32_t>(WebSchedulerTrackedFeature::kMaxValue) < 64, ...@@ -106,9 +107,12 @@ static_assert(static_cast<uint32_t>(WebSchedulerTrackedFeature::kMaxValue) < 64,
"This enum is used in a bitmask, so the values should fit into a" "This enum is used in a bitmask, so the values should fit into a"
"64-bit integer"); "64-bit integer");
BLINK_COMMON_EXPORT const char* FeatureToString( BLINK_COMMON_EXPORT std::string FeatureToHumanReadableString(
WebSchedulerTrackedFeature feature); WebSchedulerTrackedFeature feature);
BLINK_COMMON_EXPORT base::Optional<WebSchedulerTrackedFeature> StringToFeature(
const std::string& str);
// Converts a WebSchedulerTrackedFeature to a bit for use in a bitmask. // Converts a WebSchedulerTrackedFeature to a bit for use in a bitmask.
BLINK_COMMON_EXPORT constexpr uint64_t FeatureToBit( BLINK_COMMON_EXPORT constexpr uint64_t FeatureToBit(
WebSchedulerTrackedFeature feature) { WebSchedulerTrackedFeature feature) {
......
...@@ -668,7 +668,7 @@ void FrameSchedulerImpl::OnStartedUsingFeature( ...@@ -668,7 +668,7 @@ void FrameSchedulerImpl::OnStartedUsingFeature(
"renderer.scheduler", "ActiveSchedulerTrackedFeature", "renderer.scheduler", "ActiveSchedulerTrackedFeature",
TRACE_ID_LOCAL(reinterpret_cast<intptr_t>(this) ^ TRACE_ID_LOCAL(reinterpret_cast<intptr_t>(this) ^
static_cast<int>(feature)), static_cast<int>(feature)),
"feature", FeatureToString(feature)); "feature", FeatureToHumanReadableString(feature));
} }
} }
......
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