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",
......
...@@ -4,112 +4,175 @@ ...@@ -4,112 +4,175 @@
#include "third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h" #include "third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h"
#include <map>
namespace blink { namespace blink {
namespace scheduler { namespace scheduler {
const char* FeatureToString(WebSchedulerTrackedFeature feature) { namespace {
struct FeatureNames {
std::string short_name;
std::string human_readable;
};
FeatureNames FeatureToNames(WebSchedulerTrackedFeature feature) {
switch (feature) { switch (feature) {
case WebSchedulerTrackedFeature::kWebSocket: case WebSchedulerTrackedFeature::kWebSocket:
return "WebSocket"; return {"WebSocket", "WebSocket"};
case WebSchedulerTrackedFeature::kWebRTC: case WebSchedulerTrackedFeature::kWebRTC:
return "WebRTC"; return {"WebRTC", "WebRTC"};
case WebSchedulerTrackedFeature::kMainResourceHasCacheControlNoCache: case WebSchedulerTrackedFeature::kMainResourceHasCacheControlNoCache:
return "main resource has Cache-Control: No-Cache"; return {"MainResourceHasCacheControlNoCache",
"main resource has Cache-Control: No-Cache"};
case WebSchedulerTrackedFeature::kMainResourceHasCacheControlNoStore: case WebSchedulerTrackedFeature::kMainResourceHasCacheControlNoStore:
return "main resource has Cache-Control: No-Store"; return {"MainResourceHasCacheControlNoStore",
"main resource has Cache-Control: No-Store"};
case WebSchedulerTrackedFeature::kSubresourceHasCacheControlNoCache: case WebSchedulerTrackedFeature::kSubresourceHasCacheControlNoCache:
return "subresource has Cache-Control: No-Cache"; return {"SubresourceHasCacheControlNoCache",
"subresource has Cache-Control: No-Cache"};
case WebSchedulerTrackedFeature::kSubresourceHasCacheControlNoStore: case WebSchedulerTrackedFeature::kSubresourceHasCacheControlNoStore:
return "subresource has Cache-Control: No-Store"; return {"SubresourceHasCacheControlNoStore",
"subresource has Cache-Control: No-Store"};
case WebSchedulerTrackedFeature::kPageShowEventListener: case WebSchedulerTrackedFeature::kPageShowEventListener:
return "onpageshow() event listener"; return {"PageShowEventListener", "onpageshow() event listener"};
case WebSchedulerTrackedFeature::kPageHideEventListener: case WebSchedulerTrackedFeature::kPageHideEventListener:
return "onpagehide() event listener"; return {"PageHideEventListener", "onpagehide() event listener"};
case WebSchedulerTrackedFeature::kBeforeUnloadEventListener: case WebSchedulerTrackedFeature::kBeforeUnloadEventListener:
return "onbeforeunload() event listener"; return {"BeforeUnloadEventListener", "onbeforeunload() event listener"};
case WebSchedulerTrackedFeature::kUnloadEventListener: case WebSchedulerTrackedFeature::kUnloadEventListener:
return "onunload() event listener"; return {"UnloadEventListener", "onunload() event listener"};
case WebSchedulerTrackedFeature::kFreezeEventListener: case WebSchedulerTrackedFeature::kFreezeEventListener:
return "onfreeze() event listener"; return {"FreezeEventListener", "onfreeze() event listener"};
case WebSchedulerTrackedFeature::kResumeEventListener: case WebSchedulerTrackedFeature::kResumeEventListener:
return "onresume() event listener"; return {"ResumeEventListener", "onresume() event listener"};
case WebSchedulerTrackedFeature::kContainsPlugins: case WebSchedulerTrackedFeature::kContainsPlugins:
return "page contains plugins"; return {"ContainsPlugins", "page contains plugins"};
case WebSchedulerTrackedFeature::kDocumentLoaded: case WebSchedulerTrackedFeature::kDocumentLoaded:
return "document loaded"; return {"DocumentLoaded", "document loaded"};
case WebSchedulerTrackedFeature::kDedicatedWorkerOrWorklet: case WebSchedulerTrackedFeature::kDedicatedWorkerOrWorklet:
return "Dedicated worker or worklet present"; return {"DedicatedWorkerOrWorklet",
"Dedicated worker or worklet present"};
case WebSchedulerTrackedFeature::kSharedWorker: case WebSchedulerTrackedFeature::kSharedWorker:
return "Shared worker present"; return {"SharedWorker", "Shared worker present"};
case WebSchedulerTrackedFeature::kOutstandingNetworkRequestFetch: case WebSchedulerTrackedFeature::kOutstandingNetworkRequestFetch:
return "outstanding network request (fetch)"; return {"OutstandingNetworkRequestFetch",
"outstanding network request (fetch)"};
case WebSchedulerTrackedFeature::kOutstandingNetworkRequestXHR: case WebSchedulerTrackedFeature::kOutstandingNetworkRequestXHR:
return "outstanding network request (XHR)"; return {"OutstandingNetworkRequestXHR",
"outstanding network request (XHR)"};
case WebSchedulerTrackedFeature::kOutstandingNetworkRequestOthers: case WebSchedulerTrackedFeature::kOutstandingNetworkRequestOthers:
return "outstanding network request (others)"; return {"OutstandingNetworkRequestOthers",
"outstanding network request (others)"};
case WebSchedulerTrackedFeature::kOutstandingIndexedDBTransaction: case WebSchedulerTrackedFeature::kOutstandingIndexedDBTransaction:
return "outstanding IndexedDB transaction"; return {"OutstandingIndexedDBTransaction",
"outstanding IndexedDB transaction"};
case WebSchedulerTrackedFeature::kRequestedGeolocationPermission: case WebSchedulerTrackedFeature::kRequestedGeolocationPermission:
return "requested geolocation permission"; return {"RequestedGeolocationPermission",
"requested geolocation permission"};
case WebSchedulerTrackedFeature::kRequestedNotificationsPermission: case WebSchedulerTrackedFeature::kRequestedNotificationsPermission:
return "requested notifications permission"; return {"RequestedNotificationsPermission",
"requested notifications permission"};
case WebSchedulerTrackedFeature::kRequestedMIDIPermission: case WebSchedulerTrackedFeature::kRequestedMIDIPermission:
return "requested midi permission"; return {"RequestedMIDIPermission", "requested midi permission"};
case WebSchedulerTrackedFeature::kRequestedAudioCapturePermission: case WebSchedulerTrackedFeature::kRequestedAudioCapturePermission:
return "requested audio capture permission"; return {"RequestedAudioCapturePermission",
"requested audio capture permission"};
case WebSchedulerTrackedFeature::kRequestedVideoCapturePermission: case WebSchedulerTrackedFeature::kRequestedVideoCapturePermission:
return "requested video capture permission"; return {"RequestedVideoCapturePermission",
"requested video capture permission"};
case WebSchedulerTrackedFeature::kRequestedBackForwardCacheBlockedSensors: case WebSchedulerTrackedFeature::kRequestedBackForwardCacheBlockedSensors:
return "requested sensors permission"; return {"RequestedBackForwardCacheBlockedSensors",
"requested sensors permission"};
case WebSchedulerTrackedFeature::kRequestedBackgroundWorkPermission: case WebSchedulerTrackedFeature::kRequestedBackgroundWorkPermission:
return "requested background work permission"; return {"RequestedBackgroundWorkPermission",
"requested background work permission"};
case WebSchedulerTrackedFeature::kBroadcastChannel: case WebSchedulerTrackedFeature::kBroadcastChannel:
return "requested broadcast channel permission"; return {"BroadcastChannel", "requested broadcast channel permission"};
case WebSchedulerTrackedFeature::kIndexedDBConnection: case WebSchedulerTrackedFeature::kIndexedDBConnection:
return "IndexedDB connection present"; return {"IndexedDBConnection", "IndexedDB connection present"};
case WebSchedulerTrackedFeature::kWebVR: case WebSchedulerTrackedFeature::kWebVR:
return "WebVR"; return {"WebVR", "WebVR"};
case WebSchedulerTrackedFeature::kWebXR: case WebSchedulerTrackedFeature::kWebXR:
return "WebXR"; return {"WebXR", "WebXR"};
case WebSchedulerTrackedFeature::kWebLocks: case WebSchedulerTrackedFeature::kWebLocks:
return "WebLocks"; return {"WebLocks", "WebLocks"};
case WebSchedulerTrackedFeature::kWebHID: case WebSchedulerTrackedFeature::kWebHID:
return "WebHID"; return {"WebHID", "WebHID"};
case WebSchedulerTrackedFeature::kWakeLock: case WebSchedulerTrackedFeature::kWakeLock:
return "WakeLock"; return {"WakeLock", "WakeLock"};
case WebSchedulerTrackedFeature::kWebShare: case WebSchedulerTrackedFeature::kWebShare:
return "WebShare"; return {"WebShare", "WebShare"};
case WebSchedulerTrackedFeature::kRequestedStorageAccessGrant: case WebSchedulerTrackedFeature::kRequestedStorageAccessGrant:
return "requested storage access permission"; return {"RequestedStorageAccessGrant",
"requested storage access permission"};
case WebSchedulerTrackedFeature::kWebNfc: case WebSchedulerTrackedFeature::kWebNfc:
return "WebNfc"; return {"WebNfc", "WebNfc"};
case WebSchedulerTrackedFeature::kWebFileSystem: case WebSchedulerTrackedFeature::kWebFileSystem:
return "WebFileSystem"; return {"WebFileSystem", "WebFileSystem"};
case WebSchedulerTrackedFeature::kAppBanner: case WebSchedulerTrackedFeature::kAppBanner:
return "AppBanner"; return {"AppBanner", "AppBanner"};
case WebSchedulerTrackedFeature::kPrinting: case WebSchedulerTrackedFeature::kPrinting:
return "Printing"; return {"Printing", "Printing"};
case WebSchedulerTrackedFeature::kWebDatabase: case WebSchedulerTrackedFeature::kWebDatabase:
return "WebDatabase"; return {"WebDatabase", "WebDatabase"};
case WebSchedulerTrackedFeature::kPictureInPicture: case WebSchedulerTrackedFeature::kPictureInPicture:
return "PictureInPicture"; return {"PictureInPicture", "PictureInPicture"};
case WebSchedulerTrackedFeature::kPortal: case WebSchedulerTrackedFeature::kPortal:
return "Portal"; return {"Portal", "Portal"};
case WebSchedulerTrackedFeature::kSpeechRecognizer: case WebSchedulerTrackedFeature::kSpeechRecognizer:
return "SpeechRecognizer"; return {"SpeechRecognizer", "SpeechRecognizer"};
case WebSchedulerTrackedFeature::kIdleManager: case WebSchedulerTrackedFeature::kIdleManager:
return "IdleManager"; return {"IdleManager", "IdleManager"};
case WebSchedulerTrackedFeature::kPaymentManager: case WebSchedulerTrackedFeature::kPaymentManager:
return "PaymentManager"; return {"PaymentManager", "PaymentManager"};
case WebSchedulerTrackedFeature::kSpeechSynthesis: case WebSchedulerTrackedFeature::kSpeechSynthesis:
return "SpeechSynthesis"; return {"SpeechSynthesis", "SpeechSynthesis"};
case WebSchedulerTrackedFeature::kKeyboardLock: case WebSchedulerTrackedFeature::kKeyboardLock:
return "KeyboardLock"; return {"KeyboardLock", "KeyboardLock"};
case WebSchedulerTrackedFeature::kWebOTPService: case WebSchedulerTrackedFeature::kWebOTPService:
return "SMSService"; return {"WebOTPService", "SMSService"};
case WebSchedulerTrackedFeature::kOutstandingNetworkRequestDirectSocket: case WebSchedulerTrackedFeature::kOutstandingNetworkRequestDirectSocket:
return "outstanding network request (direct socket)"; return {"OutstandingNetworkRequestDirectSocket",
"outstanding network request (direct socket)"};
}
return {};
}
std::map<std::string, WebSchedulerTrackedFeature> MakeShortNameToFeature() {
std::map<std::string, WebSchedulerTrackedFeature> short_name_to_feature;
for (int i = 0; i <= static_cast<int>(WebSchedulerTrackedFeature::kMaxValue);
i++) {
WebSchedulerTrackedFeature feature =
static_cast<WebSchedulerTrackedFeature>(i);
FeatureNames strs = FeatureToNames(feature);
if (strs.short_name.size())
short_name_to_feature[strs.short_name] = feature;
}
return short_name_to_feature;
}
const std::map<std::string, WebSchedulerTrackedFeature>&
ShortStringToFeatureMap() {
static const std::map<std::string, WebSchedulerTrackedFeature>
short_name_to_feature = MakeShortNameToFeature();
return short_name_to_feature;
}
} // namespace
std::string FeatureToHumanReadableString(WebSchedulerTrackedFeature feature) {
return FeatureToNames(feature).human_readable;
}
base::Optional<WebSchedulerTrackedFeature> StringToFeature(
const std::string& str) {
auto map = ShortStringToFeatureMap();
auto it = map.find(str);
if (it == map.end()) {
return base::nullopt;
} }
return it->second;
} }
bool IsFeatureSticky(WebSchedulerTrackedFeature feature) { bool IsFeatureSticky(WebSchedulerTrackedFeature feature) {
......
// 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