0

Implement class to manage ConversionStorage / implement StorageDelegate

This CL adds a new UI thread class, ConversionManager, owned by the
StoragePartition. The ConversionManager initializes and owns
a ConversionStorage instance and also implements the
ConversionStorage::StorageDelegate.

Specific API constraints like delaying conversion reports, and setting
the maximum number of conversions are implemented in a separate
composable class ConversionPolicy to allow tests to easily mock certain
functionality, as well as centralize these constraints to a single
include.

Intended functionality of the ConversionManager includes:
  - ownership of the ConversionReporter, and timers for periodically
    fetching reports to send from storage.
  - methods to log new impressions / conversions to storage
  - ownership and usage of Report Cooldown throttling implementations
This functionality is intended to be implemented in follow-up CL's due
to dependencies, and to keep these changes small. A more complete
implementation can be seen on the prototype change below.

The functionality of the API is described on
https://github.com/csharrison/conversion-measurement-api

Design-doc(RVG): https://crbug.com/1039466

Reference prototype change:
https://chromium-review.googlesource.com/c/chromium/src/+/1967220

Bug: 1014604
Change-Id: If432b0046b8c6dcd12ce828aea3917cf887fbe08
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1994016
Reviewed-by: Avi Drissman <avi@chromium.org>
Reviewed-by: Charlie Harrison <csharrison@chromium.org>
Commit-Queue: John Delaney <johnidel@chromium.org>
Cr-Commit-Position: refs/heads/master@{#736136}
This commit is contained in:
John Delaney
2020-01-28 23:24:56 +00:00
committed by Commit Bot
parent c4d39657b9
commit 283b6a4712
15 changed files with 461 additions and 43 deletions

@ -671,6 +671,10 @@ jumbo_source_set("browser") {
"content_index/content_index_service_impl.h",
"content_service_delegate_impl.cc",
"content_service_delegate_impl.h",
"conversions/conversion_manager.cc",
"conversions/conversion_manager.h",
"conversions/conversion_policy.cc",
"conversions/conversion_policy.h",
"conversions/conversion_report.cc",
"conversions/conversion_report.h",
"conversions/conversion_storage.h",

@ -0,0 +1,59 @@
// 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 "content/browser/conversions/conversion_manager.h"
#include <memory>
#include "base/bind.h"
#include "base/task_runner_util.h"
#include "base/time/default_clock.h"
#include "content/browser/conversions/conversion_storage_sql.h"
namespace content {
ConversionManager::ConversionManager(
const base::FilePath& user_data_directory,
scoped_refptr<base::SequencedTaskRunner> task_runner)
: storage_task_runner_(std::move(task_runner)),
clock_(base::DefaultClock::GetInstance()),
storage_(new ConversionStorageSql(user_data_directory, this, clock_),
base::OnTaskRunnerDeleter(storage_task_runner_)),
conversion_policy_(std::make_unique<ConversionPolicy>()),
weak_factory_(this) {
// Unretained is safe because any task to delete |storage_| will be posted
// after this one.
base::PostTaskAndReplyWithResult(
storage_task_runner_.get(), FROM_HERE,
base::BindOnce(&ConversionStorage::Initialize,
base::Unretained(storage_.get())),
base::BindOnce(&ConversionManager::OnInitCompleted,
weak_factory_.GetWeakPtr()));
}
ConversionManager::~ConversionManager() = default;
const ConversionPolicy& ConversionManager::GetConversionPolicy() const {
return *conversion_policy_;
}
void ConversionManager::ProcessNewConversionReports(
std::vector<ConversionReport>* reports) {
for (ConversionReport& report : *reports) {
report.report_time = conversion_policy_->GetReportTimeForConversion(report);
}
conversion_policy_->AssignAttributionCredits(reports);
}
int ConversionManager::GetMaxConversionsPerImpression() const {
return conversion_policy_->GetMaxConversionsPerImpression();
}
void ConversionManager::OnInitCompleted(bool success) {
if (!success)
storage_.reset();
}
} // namespace content

@ -0,0 +1,69 @@
// 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 CONTENT_BROWSER_CONVERSIONS_CONVERSION_MANAGER_H_
#define CONTENT_BROWSER_CONVERSIONS_CONVERSION_MANAGER_H_
#include <memory>
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequenced_task_runner.h"
#include "content/browser/conversions/conversion_policy.h"
#include "content/browser/conversions/conversion_storage.h"
namespace base {
class Clock;
} // namespace base
namespace content {
class ConversionStorage;
// UI thread class that manages the lifetime of the underlying conversion
// storage. Owned by the storage partition.
class ConversionManager : public ConversionStorage::Delegate {
public:
// |storage_task_runner| should run with base::TaskPriority::BEST_EFFORT.
ConversionManager(
const base::FilePath& user_data_directory,
scoped_refptr<base::SequencedTaskRunner> storage_task_runner);
ConversionManager(const ConversionManager& other) = delete;
ConversionManager& operator=(const ConversionManager& other) = delete;
~ConversionManager() override;
const ConversionPolicy& GetConversionPolicy() const;
private:
// ConversionStorageDelegate
void ProcessNewConversionReports(
std::vector<ConversionReport>* reports) override;
int GetMaxConversionsPerImpression() const override;
void OnInitCompleted(bool success);
// Task runner used to perform operations on |storage_|. Runs with
// base::TaskPriority::BEST_EFFORT.
scoped_refptr<base::SequencedTaskRunner> storage_task_runner_;
base::Clock* clock_;
// ConversionStorage instance which is scoped to lifetime of
// |storage_task_runner_|. |storage_| should be accessed by calling
// base::PostTask with |storage_task_runner_|, and should not be accessed
// directly.
std::unique_ptr<ConversionStorage, base::OnTaskRunnerDeleter> storage_;
// Policy used for controlling API configurations such as reporting and
// attribution models. Unique ptr so it can be overridden for testing.
std::unique_ptr<ConversionPolicy> conversion_policy_;
base::WeakPtrFactory<ConversionManager> weak_factory_;
};
} // namespace content
#endif // CONTENT_BROWSER_CONVERSIONS_CONVERSION_MANAGER_H_

@ -0,0 +1,88 @@
// 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 "content/browser/conversions/conversion_policy.h"
#include "base/logging.h"
#include "base/time/time.h"
namespace content {
base::Time ConversionPolicy::GetReportTimeForConversion(
const ConversionReport& report) const {
// After the initial impression, a schedule of reporting windows and deadlines
// associated with that impression begins. The time between impression time
// and impression expiry is split into multiple reporting windows. At the end
// of each window, the browser will send all scheduled reports for that
// impression.
//
// Each reporting window has a deadline and only conversions registered before
// that deadline are sent in that window. Each deadline is one hour prior to
// the window report time. The deadlines relative to impression time are <2
// days minus 1 hour, 7 days minus 1 hour, impression expiry>. The impression
// expiry window is only used for conversions that occur after the 7 day
// deadline. For example, a conversion which happens one hour after an
// impression with an expiry of two hours, is still reported in the 2 day
// window.
constexpr base::TimeDelta kWindowDeadlineOffset =
base::TimeDelta::FromHours(1);
base::TimeDelta expiry_deadline =
report.impression.expiry_time() - report.impression.impression_time();
const base::TimeDelta kReportingWindowDeadlines[] = {
base::TimeDelta::FromDays(2) - kWindowDeadlineOffset,
base::TimeDelta::FromDays(7) - kWindowDeadlineOffset, expiry_deadline};
base::TimeDelta deadline_to_use;
// Given a conversion report that was created at |report.report_time|, find
// the first applicable reporting window this conversion should be reported
// at.
for (base::TimeDelta report_window_deadline : kReportingWindowDeadlines) {
// If this window is valid for the conversion, use it. |report.report_time|
// is roughly ~now, as the conversion time is used as the default value for
// newly created reports that have not had a report time set.
if (report.impression.impression_time() + report_window_deadline >=
report.report_time) {
deadline_to_use = report_window_deadline;
break;
}
}
// Valid conversion reports should always have a valid reporting deadline.
DCHECK(!deadline_to_use.is_zero());
// If the expiry deadline falls after the first window, but before another
// window, use it instead. For example, if expiry is at 3 days, we can send
// reports at the 2 day deadline and the expiry deadline instead of at the 7
// day deadline.
if (expiry_deadline > kReportingWindowDeadlines[0] &&
expiry_deadline < deadline_to_use) {
deadline_to_use = expiry_deadline;
}
return report.impression.impression_time() + deadline_to_use +
kWindowDeadlineOffset;
}
int ConversionPolicy::GetMaxConversionsPerImpression() const {
return 3;
}
void ConversionPolicy::AssignAttributionCredits(
std::vector<ConversionReport>* reports) const {
DCHECK(!reports->empty());
ConversionReport* last_report = &(reports->at(0));
// Give the latest impression an attribution of 100 and all the rest 0.
for (auto& report : *reports) {
report.attribution_credit = 0;
if (report.impression.impression_time() >
last_report->impression.impression_time())
last_report = &report;
}
last_report->attribution_credit = 100;
}
} // namespace content

@ -0,0 +1,44 @@
// 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 CONTENT_BROWSER_CONVERSIONS_CONVERSION_POLICY_H_
#define CONTENT_BROWSER_CONVERSIONS_CONVERSION_POLICY_H_
#include <vector>
#include "base/time/time.h"
#include "content/browser/conversions/conversion_report.h"
#include "content/common/content_export.h"
namespace content {
// Class for controlling certain constraints and configurations for handling,
// storing, and sending impressions and conversions.
class CONTENT_EXPORT ConversionPolicy {
public:
ConversionPolicy() = default;
ConversionPolicy(const ConversionPolicy& other) = delete;
ConversionPolicy& operator=(const ConversionPolicy& other) = delete;
virtual ~ConversionPolicy() = default;
// Get the time a conversion report should be sent, by batching reports into
// set reporting windows based on their impression time. This strictly delays
// the time a report will be sent.
virtual base::Time GetReportTimeForConversion(
const ConversionReport& report) const;
// Maximum number of times the an impression is allowed to convert.
virtual int GetMaxConversionsPerImpression() const;
// Given a set of conversion reports for a single conversion registrations,
// assigns attribution credits to each one which will be sent at report time.
// By default, this performs "last click" attribution which assigns the report
// for the most recent impression a credit of 100, and the rest a credit of 0.
virtual void AssignAttributionCredits(
std::vector<ConversionReport>* reports) const;
};
} // namespace content
#endif // CONTENT_BROWSER_CONVERSIONS_CONVERSION_POLICY_H_

@ -0,0 +1,131 @@
// 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 "content/browser/conversions/conversion_policy.h"
#include <vector>
#include "base/time/time.h"
#include "content/browser/conversions/conversion_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
namespace {
constexpr base::TimeDelta kDefaultExpiry = base::TimeDelta::FromDays(30);
ConversionReport GetReport(base::Time impression_time,
base::Time conversion_time,
base::TimeDelta expiry = kDefaultExpiry) {
return ConversionReport(
ImpressionBuilder(impression_time).SetExpiry(expiry).Build(),
/*conversion_data=*/"123", conversion_time,
/*conversion_id=*/base::nullopt);
}
} // namespace
class ConversionPolicyTest : public testing::Test {
public:
ConversionPolicyTest() = default;
};
TEST_F(ConversionPolicyTest, ImmediateConversion_FirstWindowUsed) {
base::Time impression_time = base::Time::Now();
auto report = GetReport(impression_time, /*conversion_time=*/impression_time);
EXPECT_EQ(impression_time + base::TimeDelta::FromDays(2),
ConversionPolicy().GetReportTimeForConversion(report));
}
TEST_F(ConversionPolicyTest, ConversionImmediatelyBeforeWindow_NextWindowUsed) {
base::Time impression_time = base::Time::Now();
base::Time conversion_time = impression_time + base::TimeDelta::FromDays(2) -
base::TimeDelta::FromMinutes(1);
auto report = GetReport(impression_time, conversion_time);
EXPECT_EQ(impression_time + base::TimeDelta::FromDays(7),
ConversionPolicy().GetReportTimeForConversion(report));
}
TEST_F(ConversionPolicyTest, ConversionBeforeWindowDelay_WindowUsed) {
base::Time impression_time = base::Time::Now();
// The deadline for a window is 1 hour before the window. Use a time just
// before the deadline.
base::Time conversion_time = impression_time + base::TimeDelta::FromDays(2) -
base::TimeDelta::FromMinutes(61);
auto report = GetReport(impression_time, conversion_time);
EXPECT_EQ(impression_time + base::TimeDelta::FromDays(2),
ConversionPolicy().GetReportTimeForConversion(report));
}
TEST_F(ConversionPolicyTest,
ImpressionExpiryBeforeTwoDayWindow_TwoDayWindowUsed) {
base::Time impression_time = base::Time::Now();
base::Time conversion_time = impression_time + base::TimeDelta::FromHours(1);
// Set the impression to expire before the two day window.
auto report = GetReport(impression_time, conversion_time,
/*expiry=*/base::TimeDelta::FromHours(2));
EXPECT_EQ(impression_time + base::TimeDelta::FromDays(2),
ConversionPolicy().GetReportTimeForConversion(report));
}
TEST_F(ConversionPolicyTest,
ImpressionExpiryBeforeSevenDayWindow_ExpiryWindowUsed) {
base::Time impression_time = base::Time::Now();
base::Time conversion_time = impression_time + base::TimeDelta::FromDays(3);
// Set the impression to expire before the two day window.
auto report = GetReport(impression_time, conversion_time,
/*expiry=*/base::TimeDelta::FromDays(4));
// The expiry window is reported one hour after expiry time.
EXPECT_EQ(impression_time + base::TimeDelta::FromDays(4) +
base::TimeDelta::FromHours(1),
ConversionPolicy().GetReportTimeForConversion(report));
}
TEST_F(ConversionPolicyTest,
ImpressionExpiryAfterSevenDayWindow_ExpiryWindowUsed) {
base::Time impression_time = base::Time::Now();
base::Time conversion_time = impression_time + base::TimeDelta::FromDays(7);
// Set the impression to expire before the two day window.
auto report = GetReport(impression_time, conversion_time,
/*expiry=*/base::TimeDelta::FromDays(9));
// The expiry window is reported one hour after expiry time.
EXPECT_EQ(impression_time + base::TimeDelta::FromDays(9) +
base::TimeDelta::FromHours(1),
ConversionPolicy().GetReportTimeForConversion(report));
}
TEST_F(ConversionPolicyTest,
SingleReportForConversion_AttributionCreditAssigned) {
base::Time now = base::Time::Now();
std::vector<ConversionReport> reports = {
GetReport(/*impression_time=*/now, /*conversion_time=*/now)};
ConversionPolicy().AssignAttributionCredits(&reports);
EXPECT_EQ(1u, reports.size());
EXPECT_EQ(100, reports[0].attribution_credit);
}
TEST_F(ConversionPolicyTest, TwoReportsForConversion_LastReceivesCredit) {
base::Time now = base::Time::Now();
std::vector<ConversionReport> reports = {
GetReport(/*impression_time=*/now, /*conversion_time=*/now),
GetReport(/*impression_time=*/now + base::TimeDelta::FromHours(100),
/*conversion_time=*/now)};
ConversionPolicy().AssignAttributionCredits(&reports);
EXPECT_EQ(2u, reports.size());
EXPECT_EQ(0, reports[0].attribution_credit);
EXPECT_EQ(100, reports[1].attribution_credit);
// Ensure the reports were not rearranged.
EXPECT_EQ(now + base::TimeDelta::FromHours(100),
reports[1].impression.impression_time());
}
} // namespace content

@ -23,6 +23,8 @@ class ConversionStorage {
// functionality like annotating conversion reports.
class Delegate {
public:
virtual ~Delegate() = default;
// New conversions will be sent through this callback for
// pruning/modification before they are added to storage. This will be
// called during the execution of

@ -40,7 +40,7 @@ using AttributionCredits = std::list<int>;
class MockStorageDelegate : public ConversionStorage::Delegate {
public:
MockStorageDelegate() = default;
virtual ~MockStorageDelegate() = default;
~MockStorageDelegate() override = default;
// ConversionStorage::Delegate
void ProcessNewConversionReports(

@ -21,7 +21,7 @@ namespace content {
class EmptyStorageDelegate : public ConversionStorage::Delegate {
public:
EmptyStorageDelegate() = default;
virtual ~EmptyStorageDelegate() = default;
~EmptyStorageDelegate() override = default;
// ConversionStorage::Delegate
void ProcessNewConversionReports(

@ -23,6 +23,8 @@ StorableImpression::StorableImpression(
impression_time_(impression_time),
expiry_time_(expiry_time),
impression_id_(impression_id) {
// 30 days is the max allowed expiry for an impression.
DCHECK_GE(base::TimeDelta::FromDays(30), expiry_time - impression_time);
DCHECK(!impression_origin.opaque());
DCHECK(!reporting_origin.opaque());
DCHECK(!conversion_origin.opaque());

@ -16,6 +16,7 @@
#include "base/bind_helpers.h"
#include "base/callback_helpers.h"
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/location.h"
#include "base/optional.h"
#include "base/run_loop.h"
@ -37,6 +38,7 @@
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/code_cache/generated_code_cache.h"
#include "content/browser/code_cache/generated_code_cache_context.h"
#include "content/browser/conversions/conversion_manager.h"
#include "content/browser/cookie_store/cookie_store_context.h"
#include "content/browser/devtools/devtools_url_loader_interceptor.h"
#include "content/browser/file_system/browser_file_system_helper.h"
@ -1327,6 +1329,15 @@ void StoragePartitionImpl::Initialize() {
browser_context_->GetNativeFileSystemPermissionContext(),
browser_context_->IsOffTheRecord());
// The Conversion Measurement API is not available in Incognito mode.
if (!is_in_memory_ &&
base::FeatureList::IsEnabled(features::kConversionMeasurement)) {
conversion_manager_ = std::make_unique<ConversionManager>(
path,
base::CreateSequencedTaskRunner({base::ThreadPool(), base::MayBlock(),
base::TaskPriority::BEST_EFFORT}));
}
GeneratedCodeCacheSettings settings =
GetContentClient()->browser()->GetGeneratedCodeCacheSettings(
browser_context_);

@ -61,6 +61,7 @@ class ProtoDatabaseProvider;
namespace content {
class BackgroundFetchContext;
class ConversionManager;
class CookieStoreContext;
class BlobRegistryWrapper;
class PrefetchURLLoaderService;
@ -463,6 +464,7 @@ class CONTENT_EXPORT StoragePartitionImpl
std::unique_ptr<leveldb_proto::ProtoDatabaseProvider>
proto_database_provider_;
scoped_refptr<ContentIndexContextImpl> content_index_context_;
std::unique_ptr<ConversionManager> conversion_manager_;
// ReceiverSet for StoragePartitionService, using the process id as the
// binding context type. The process id can subsequently be used during

@ -73,22 +73,20 @@ const base::Feature kBackForwardCache{"BackForwardCache",
const base::Feature kBackForwardCacheMemoryControl{
"BackForwardCacheMemoryControls", base::FEATURE_DISABLED_BY_DEFAULT};
// Allows swipe left/right from touchpad change browser navigation. Currently
// only enabled by default on CrOS.
const base::Feature kTouchpadOverscrollHistoryNavigation {
"TouchpadOverscrollHistoryNavigation",
#if defined(OS_CHROMEOS) || defined(OS_WIN)
base::FEATURE_ENABLED_BY_DEFAULT
#else
base::FEATURE_DISABLED_BY_DEFAULT
#endif
};
// Block subresource requests whose URLs contain embedded credentials (e.g.
// `https://user:pass@example.com/resource`).
const base::Feature kBlockCredentialedSubresources{
"BlockCredentialedSubresources", base::FEATURE_ENABLED_BY_DEFAULT};
// Use ThreadPriority::DISPLAY for browser UI and IO threads.
#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
const base::Feature kBrowserUseDisplayThreadPriority{
"BrowserUseDisplayThreadPriority", base::FEATURE_ENABLED_BY_DEFAULT};
#else
const base::Feature kBrowserUseDisplayThreadPriority{
"BrowserUseDisplayThreadPriority", base::FEATURE_DISABLED_BY_DEFAULT};
#endif
// When enabled, keyboard user activation will be verified by the browser side.
const base::Feature kBrowserVerifiedUserActivationKeyboard{
"BrowserVerifiedUserActivationKeyboard", base::FEATURE_DISABLED_BY_DEFAULT};
@ -132,6 +130,10 @@ const base::Feature kCanvas2DImageChromium {
const base::Feature kConsolidatedMovementXY{"ConsolidatedMovementXY",
base::FEATURE_ENABLED_BY_DEFAULT};
// Controls whether the Conversion Measurement API is enabled.
const base::Feature kConversionMeasurement{"ConversionMeasurement",
base::FEATURE_DISABLED_BY_DEFAULT};
// Show messages in the DevTools console about upcoming deprecations
// that would affect sent/received cookies.
const base::Feature kCookieDeprecationMessages{
@ -181,6 +183,10 @@ const base::Feature kExtraSafelistedRequestHeadersForOutOfBlinkCors{
"ExtraSafelistedRequestHeadersForOutOfBlinkCors",
base::FEATURE_DISABLED_BY_DEFAULT};
// Controls whether Client Hints are guarded by FeaturePolicy.
const base::Feature kFeaturePolicyForClientHints{
"FeaturePolicyForClientHints", base::FEATURE_DISABLED_BY_DEFAULT};
// When enabled Feature Policy propagation is similar to sandbox flags and,
// sandbox flags are implemented on top of Feature Policy.
const base::Feature kFeaturePolicyForSandbox{"FeaturePolicyForSandbox",
@ -470,6 +476,10 @@ const base::Feature kRunVideoCaptureServiceInBrowserProcess{
const base::Feature kSavePageAsWebBundle{"SavePageAsWebBundle",
base::FEATURE_DISABLED_BY_DEFAULT};
// Start streaming scripts on script preload.
const base::Feature kScriptStreamingOnPreload{"ScriptStreamingOnPreload",
base::FEATURE_ENABLED_BY_DEFAULT};
// Make sendBeacon throw for a Blob with a non simple type.
const base::Feature kSendBeaconThrowForBlobWithNonSimpleType{
"SendBeaconThrowForBlobWithNonSimpleType",
@ -573,6 +583,21 @@ const base::Feature kTimerThrottlingForHiddenFrames{
const base::Feature kTouchpadAsyncPinchEvents{"TouchpadAsyncPinchEvents",
base::FEATURE_ENABLED_BY_DEFAULT};
// Allows swipe left/right from touchpad change browser navigation. Currently
// only enabled by default on CrOS.
const base::Feature kTouchpadOverscrollHistoryNavigation {
"TouchpadOverscrollHistoryNavigation",
#if defined(OS_CHROMEOS) || defined(OS_WIN)
base::FEATURE_ENABLED_BY_DEFAULT
#else
base::FEATURE_DISABLED_BY_DEFAULT
#endif
};
// Controls whether the Trusted Types API is available.
const base::Feature kTrustedDOMTypes{"TrustedDOMTypes",
base::FEATURE_DISABLED_BY_DEFAULT};
// Controls whether the RenderProcessHost uses its frames' priorities for
// determining if it should be backgrounded. When all frames associated with a
// RenderProcessHost are low priority, that process may be backgrounded even if
@ -597,6 +622,10 @@ const base::Feature kUserActivationSameOriginVisibility{
const base::Feature kUserAgentClientHint{"UserAgentClientHint",
base::FEATURE_DISABLED_BY_DEFAULT};
// Controls whether the <video>.getVideoPlaybackQuality() API is enabled.
const base::Feature kVideoPlaybackQuality{"VideoPlaybackQuality",
base::FEATURE_ENABLED_BY_DEFAULT};
// Enables V8's low memory mode for subframes. This is used only
// in conjunction with the --site-per-process feature.
const base::Feature kV8LowMemoryModeForSubframes{
@ -738,31 +767,6 @@ const base::Feature kWebXrIncubations{"WebXRIncubations",
const base::Feature kWebXrPermissionsApi{"WebXrPermissionsApi",
base::FEATURE_DISABLED_BY_DEFAULT};
// Start streaming scripts on script preload.
const base::Feature kScriptStreamingOnPreload{"ScriptStreamingOnPreload",
base::FEATURE_ENABLED_BY_DEFAULT};
// Controls whether the Trusted Types API is available.
const base::Feature kTrustedDOMTypes{"TrustedDOMTypes",
base::FEATURE_DISABLED_BY_DEFAULT};
// Controls whether Client Hints are guarded by FeaturePolicy.
const base::Feature kFeaturePolicyForClientHints{
"FeaturePolicyForClientHints", base::FEATURE_DISABLED_BY_DEFAULT};
// Controls whether the <video>.getVideoPlaybackQuality() API is enabled.
const base::Feature kVideoPlaybackQuality{"VideoPlaybackQuality",
base::FEATURE_ENABLED_BY_DEFAULT};
// Use ThreadPriority::DISPLAY for browser UI and IO threads.
#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
const base::Feature kBrowserUseDisplayThreadPriority{
"BrowserUseDisplayThreadPriority", base::FEATURE_ENABLED_BY_DEFAULT};
#else
const base::Feature kBrowserUseDisplayThreadPriority{
"BrowserUseDisplayThreadPriority", base::FEATURE_DISABLED_BY_DEFAULT};
#endif
#if defined(OS_ANDROID)
// Autofill Accessibility in Android.
// crbug.com/627860

@ -28,6 +28,7 @@ CONTENT_EXPORT extern const base::Feature kBackgroundFetch;
CONTENT_EXPORT extern const base::Feature kBackForwardCache;
CONTENT_EXPORT extern const base::Feature kBackForwardCacheMemoryControl;
CONTENT_EXPORT extern const base::Feature kBlockCredentialedSubresources;
CONTENT_EXPORT extern const base::Feature kBrowserUseDisplayThreadPriority;
CONTENT_EXPORT extern const base::Feature
kBrowserVerifiedUserActivationKeyboard;
CONTENT_EXPORT extern const base::Feature kBrowserVerifiedUserActivationMouse;
@ -37,6 +38,7 @@ CONTENT_EXPORT extern const base::Feature kCacheStorageEagerReading;
CONTENT_EXPORT extern const base::Feature kCacheStorageHighPriorityMatch;
CONTENT_EXPORT extern const base::Feature kCanvas2DImageChromium;
CONTENT_EXPORT extern const base::Feature kConsolidatedMovementXY;
CONTENT_EXPORT extern const base::Feature kConversionMeasurement;
CONTENT_EXPORT extern const base::Feature kCookieDeprecationMessages;
CONTENT_EXPORT extern const base::Feature kCooperativeScheduling;
CONTENT_EXPORT extern const base::Feature kCrashReporting;
@ -49,6 +51,7 @@ CONTENT_EXPORT extern const base::Feature kExperimentalProductivityFeatures;
CONTENT_EXPORT extern const base::Feature kExpensiveBackgroundTimerThrottling;
CONTENT_EXPORT extern const base::Feature
kExtraSafelistedRequestHeadersForOutOfBlinkCors;
CONTENT_EXPORT extern const base::Feature kFeaturePolicyForClientHints;
CONTENT_EXPORT extern const base::Feature kFeaturePolicyForSandbox;
CONTENT_EXPORT extern const base::Feature kFontSrcLocalMatching;
CONTENT_EXPORT extern const base::Feature kForcedColors;
@ -104,6 +107,7 @@ CONTENT_EXPORT extern const base::Feature kResamplingInputEvents;
CONTENT_EXPORT extern const base::Feature
kRunVideoCaptureServiceInBrowserProcess;
CONTENT_EXPORT extern const base::Feature kSavePageAsWebBundle;
CONTENT_EXPORT extern const base::Feature kScriptStreamingOnPreload;
CONTENT_EXPORT extern const base::Feature
kSendBeaconThrowForBlobWithNonSimpleType;
CONTENT_EXPORT extern const base::Feature kServiceWorkerOnUI;
@ -127,10 +131,12 @@ CONTENT_EXPORT extern const base::Feature kSyntheticPointerActions;
CONTENT_EXPORT extern const base::Feature kTimerThrottlingForHiddenFrames;
CONTENT_EXPORT extern const base::Feature kTouchpadAsyncPinchEvents;
CONTENT_EXPORT extern const base::Feature kTouchpadOverscrollHistoryNavigation;
CONTENT_EXPORT extern const base::Feature kTrustedDOMTypes;
CONTENT_EXPORT extern const base::Feature kUseFramePriorityInRenderProcessHost;
CONTENT_EXPORT extern const base::Feature kUserActivationPostMessageTransfer;
CONTENT_EXPORT extern const base::Feature kUserActivationSameOriginVisibility;
CONTENT_EXPORT extern const base::Feature kUserAgentClientHint;
CONTENT_EXPORT extern const base::Feature kVideoPlaybackQuality;
CONTENT_EXPORT extern const base::Feature kV8LowMemoryModeForSubframes;
CONTENT_EXPORT extern const base::Feature kV8VmFuture;
CONTENT_EXPORT extern const base::Feature kWebAssemblyBaseline;
@ -155,11 +161,6 @@ CONTENT_EXPORT extern const base::Feature kWebXrArModule;
CONTENT_EXPORT extern const base::Feature kWebXrHitTest;
CONTENT_EXPORT extern const base::Feature kWebXrIncubations;
CONTENT_EXPORT extern const base::Feature kWebXrPermissionsApi;
CONTENT_EXPORT extern const base::Feature kScriptStreamingOnPreload;
CONTENT_EXPORT extern const base::Feature kTrustedDOMTypes;
CONTENT_EXPORT extern const base::Feature kBrowserUseDisplayThreadPriority;
CONTENT_EXPORT extern const base::Feature kFeaturePolicyForClientHints;
CONTENT_EXPORT extern const base::Feature kVideoPlaybackQuality;
#if defined(OS_ANDROID)
CONTENT_EXPORT extern const base::Feature kAndroidAutofillAccessibility;

@ -1556,6 +1556,7 @@ test("content_unittests") {
"../browser/code_cache/generated_code_cache_unittest.cc",
"../browser/content_index/content_index_database_unittest.cc",
"../browser/content_index/content_index_service_impl_unittest.cc",
"../browser/conversions/conversion_policy_unittest.cc",
"../browser/conversions/conversion_storage_sql_unittest.cc",
"../browser/conversions/conversion_storage_unittest.cc",
"../browser/cookie_store/cookie_store_manager_unittest.cc",