diff --git a/.vpython3 b/.vpython3
index fc530f6..45fd1b7 100644
--- a/.vpython3
+++ b/.vpython3
@@ -54,14 +54,11 @@
 >
 
 # Common utilities.
-# For Python 2, this version needed to be compatible with the version range
-# specified by
-# //third_party/catapult/telemetry/telemetry/internal/util/external_modules.py
-# However, the hope is that Telemetry's Python 3 migration will fix this, so
-# use the newer version that's currently available in CIPD for now.
+# Use the same versions specified by //third_party/catapult/.vpython3 so that
+# Chromium tests using Telemetry function properly.
 wheel: <
   name: "infra/python/wheels/numpy/${vpython_platform}"
-  version: "version:1.19.5"
+  version: "version:1.20.3"
 >
 wheel: <
   name: "infra/python/wheels/psutil/${vpython_platform}"
@@ -286,3 +283,13 @@
     platform: "win_amd64"
   >
 >
+
+# Used by:
+#   //content/test/gpu/gpu_tests/color_profile_manager_mac.py
+wheel: <
+  name: "infra/python/wheels/pyobjc/${vpython_platform}"
+  version: "version:7.3.chromium.1"
+  match_tag: <
+    platform: "macosx_10_10_intel"
+  >
+>
diff --git a/DEPS b/DEPS
index 7dad1b3..b0f5faca 100644
--- a/DEPS
+++ b/DEPS
@@ -228,11 +228,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '92ae58f33874af1d308ce27dd7df9d029dc858e3',
+  'skia_revision': 'd71fac66edf1dd38a7c0e35d7710b2f82e6e36da',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '7130623b570abb3505aad6e24bec00234d6ae99e',
+  'v8_revision': '15d13e153994fc94e57e771bb93137ef1ce7f2ec',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
@@ -244,7 +244,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': 'a3f2028fc4266c5c67ed4e00a6649bc4ed647f49',
+  'pdfium_revision': 'c9a13c890e61e79c8c5cc4f29d7f18c8966567f1',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
@@ -295,7 +295,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '818a24d7bac8e3008f8f43b20cbda61b7addfb25',
+  'catapult_revision': '3d49e1ccfd129f8c8426b9d97185f84a636880cd',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -303,7 +303,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling devtools-frontend
   # and whatever else without interference from each other.
-  'devtools_frontend_revision': '13d8667574e82576d5848212f8dbec3b7f77f85b',
+  'devtools_frontend_revision': 'fae6bd0cb73c7f4368971fd164e12ed4a26b38e4',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libprotobuf-mutator
   # and whatever else without interference from each other.
@@ -343,7 +343,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': '999cc24209657701e42dd7ef7a2c95be1ad73f2b',
+  'dawn_revision': 'ba662950338abc0ad985b43fa4aa91486ee04786',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -410,7 +410,7 @@
   'libcxx_revision':       '79a2e924d96e2fc1e4b937c42efd08898fa472d7',
 
   # GN CIPD package version.
-  'gn_version': 'git_revision:69ec4fca1fa69ddadae13f9e6b7507efa0675263',
+  'gn_version': 'git_revision:de86ec4176235871a7cb335756987e41246dae4a',
 }
 
 # Only these hosts are allowed for dependencies in this DEPS file.
@@ -773,7 +773,7 @@
     'packages': [
       {
           'package': 'chromium/third_party/androidx',
-          'version': 'Ir7leZbNYFv-M5uP3eJVCMEUNMwpgAtftX1lvGA-XMIC',
+          'version': 'wKA9jIpyBbuq6zmaiAE4Zck1k0PzGf4wsEKeYsmq3EoC',
       },
     ],
     'condition': 'checkout_android',
@@ -1012,7 +1012,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '04d9c83459364333b8f4859559654cd24d032447',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'a6baf70a45b04731ed99f47a0fbfcb5f28a1f03e',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -1677,7 +1677,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@dcb507e9822d05ce2ca6e63e7d4e70d2c075f209',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@a4113d198829c2dcfed55f20cb811572f5354b3e',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/android_webview/browser/aw_autofill_client.h b/android_webview/browser/aw_autofill_client.h
index e1bb0bc..1ff209a2 100644
--- a/android_webview/browser/aw_autofill_client.h
+++ b/android_webview/browser/aw_autofill_client.h
@@ -54,6 +54,9 @@
 class AwAutofillClient : public autofill::AutofillClient,
                          public content::WebContentsUserData<AwAutofillClient> {
  public:
+  AwAutofillClient(const AwAutofillClient&) = delete;
+  AwAutofillClient& operator=(const AwAutofillClient&) = delete;
+
   ~AwAutofillClient() override;
 
   void SetSaveFormData(bool enabled);
@@ -161,8 +164,6 @@
   base::WeakPtr<autofill::AutofillPopupDelegate> delegate_;
 
   WEB_CONTENTS_USER_DATA_KEY_DECL();
-
-  DISALLOW_COPY_AND_ASSIGN(AwAutofillClient);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/aw_browser_context.h b/android_webview/browser/aw_browser_context.h
index 6e9b355..ee57711 100644
--- a/android_webview/browser/aw_browser_context.h
+++ b/android_webview/browser/aw_browser_context.h
@@ -51,6 +51,10 @@
                          public visitedlink::VisitedLinkDelegate {
  public:
   AwBrowserContext();
+
+  AwBrowserContext(const AwBrowserContext&) = delete;
+  AwBrowserContext& operator=(const AwBrowserContext&) = delete;
+
   ~AwBrowserContext() override;
 
   // Currently only one instance per process is supported.
@@ -146,8 +150,6 @@
   SimpleFactoryKey simple_factory_key_;
 
   base::android::ScopedJavaGlobalRef<jobject> obj_;
-
-  DISALLOW_COPY_AND_ASSIGN(AwBrowserContext);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/aw_browser_main_parts.h b/android_webview/browser/aw_browser_main_parts.h
index 4fe381526..f1e6f0b9 100644
--- a/android_webview/browser/aw_browser_main_parts.h
+++ b/android_webview/browser/aw_browser_main_parts.h
@@ -25,6 +25,10 @@
 class AwBrowserMainParts : public content::BrowserMainParts {
  public:
   explicit AwBrowserMainParts(AwContentBrowserClient* browser_client);
+
+  AwBrowserMainParts(const AwBrowserMainParts&) = delete;
+  AwBrowserMainParts& operator=(const AwBrowserMainParts&) = delete;
+
   ~AwBrowserMainParts() override;
 
   // Overriding methods from content::BrowserMainParts.
@@ -46,8 +50,6 @@
   std::unique_ptr<metrics::MemoryMetricsLogger> metrics_logger_;
 
   std::unique_ptr<AwBrowserProcess> browser_process_;
-
-  DISALLOW_COPY_AND_ASSIGN(AwBrowserMainParts);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/aw_browser_policy_connector.h b/android_webview/browser/aw_browser_policy_connector.h
index 65b2cce5..7b51d4b 100644
--- a/android_webview/browser/aw_browser_policy_connector.h
+++ b/android_webview/browser/aw_browser_policy_connector.h
@@ -15,15 +15,16 @@
 class AwBrowserPolicyConnector : public policy::BrowserPolicyConnectorBase {
  public:
   AwBrowserPolicyConnector();
+
+  AwBrowserPolicyConnector(const AwBrowserPolicyConnector&) = delete;
+  AwBrowserPolicyConnector& operator=(const AwBrowserPolicyConnector&) = delete;
+
   ~AwBrowserPolicyConnector() override;
 
  protected:
   // policy::BrowserPolicyConnectorBase:
   std::vector<std::unique_ptr<policy::ConfigurationPolicyProvider>>
   CreatePolicyProviders() override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(AwBrowserPolicyConnector);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/aw_browser_process.h b/android_webview/browser/aw_browser_process.h
index 055e3ba..703bd40 100644
--- a/android_webview/browser/aw_browser_process.h
+++ b/android_webview/browser/aw_browser_process.h
@@ -38,6 +38,10 @@
 class AwBrowserProcess {
  public:
   AwBrowserProcess(AwFeatureListCreator* aw_feature_list_creator);
+
+  AwBrowserProcess(const AwBrowserProcess&) = delete;
+  AwBrowserProcess& operator=(const AwBrowserProcess&) = delete;
+
   ~AwBrowserProcess();
 
   static AwBrowserProcess* GetInstance();
@@ -113,8 +117,6 @@
 
   std::unique_ptr<VisibilityMetricsLogger> visibility_metrics_logger_;
   std::unique_ptr<AwContentsLifecycleNotifier> aw_contents_lifecycle_notifier_;
-
-  DISALLOW_COPY_AND_ASSIGN(AwBrowserProcess);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/aw_browser_terminator.h b/android_webview/browser/aw_browser_terminator.h
index 5f79809..122d360 100644
--- a/android_webview/browser/aw_browser_terminator.h
+++ b/android_webview/browser/aw_browser_terminator.h
@@ -16,14 +16,15 @@
 class AwBrowserTerminator : public crash_reporter::ChildExitObserver::Client {
  public:
   AwBrowserTerminator();
+
+  AwBrowserTerminator(const AwBrowserTerminator&) = delete;
+  AwBrowserTerminator& operator=(const AwBrowserTerminator&) = delete;
+
   ~AwBrowserTerminator() override;
 
   // crash_reporter::ChildExitObserver::Client
   void OnChildExit(
       const crash_reporter::ChildExitObserver::TerminationInfo& info) override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(AwBrowserTerminator);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc
index ae2ce5cb..af229d1d 100644
--- a/android_webview/browser/aw_content_browser_client.cc
+++ b/android_webview/browser/aw_content_browser_client.cc
@@ -143,6 +143,9 @@
  public:
   explicit AwContentsMessageFilter(int process_id);
 
+  AwContentsMessageFilter(const AwContentsMessageFilter&) = delete;
+  AwContentsMessageFilter& operator=(const AwContentsMessageFilter&) = delete;
+
   // BrowserMessageFilter methods.
   bool OnMessageReceived(const IPC::Message& message) override;
 
@@ -154,8 +157,6 @@
   ~AwContentsMessageFilter() override;
 
   int process_id_;
-
-  DISALLOW_COPY_AND_ASSIGN(AwContentsMessageFilter);
 };
 
 AwContentsMessageFilter::AwContentsMessageFilter(int process_id)
@@ -905,7 +906,8 @@
   return 1u;
 }
 
-bool AwContentBrowserClient::ShouldDisableSiteIsolation() {
+bool AwContentBrowserClient::ShouldDisableSiteIsolation(
+    content::SiteIsolationMode site_isolation_mode) {
   // Since AW does not yet support OOPIFs, we must return true here to disable
   // features that may trigger OOPIFs, such as origin isolation.
   //
diff --git a/android_webview/browser/aw_content_browser_client.h b/android_webview/browser/aw_content_browser_client.h
index 41265c4..4b2cc96 100644
--- a/android_webview/browser/aw_content_browser_client.h
+++ b/android_webview/browser/aw_content_browser_client.h
@@ -56,6 +56,10 @@
   // |aw_feature_list_creator| should not be null.
   explicit AwContentBrowserClient(
       AwFeatureListCreator* aw_feature_list_creator);
+
+  AwContentBrowserClient(const AwContentBrowserClient&) = delete;
+  AwContentBrowserClient& operator=(const AwContentBrowserClient&) = delete;
+
   ~AwContentBrowserClient() override;
 
   // Allows AwBrowserMainParts to initialize a BrowserContext at the right
@@ -196,7 +200,8 @@
       NonNetworkURLLoaderFactoryMap* factories) override;
   bool ShouldIsolateErrorPage(bool in_main_frame) override;
   bool ShouldEnableStrictSiteIsolation() override;
-  bool ShouldDisableSiteIsolation() override;
+  bool ShouldDisableSiteIsolation(
+      content::SiteIsolationMode site_isolation_mode) override;
   bool ShouldLockProcessToSite(content::BrowserContext* browser_context,
                                const GURL& effective_url) override;
   size_t GetMaxRendererProcessCountOverride() override;
@@ -260,8 +265,6 @@
 
   // The AwFeatureListCreator is owned by AwMainDelegate.
   AwFeatureListCreator* const aw_feature_list_creator_;
-
-  DISALLOW_COPY_AND_ASSIGN(AwContentBrowserClient);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/aw_contents.h b/android_webview/browser/aw_contents.h
index 2bdc973..f20a466e 100644
--- a/android_webview/browser/aw_contents.h
+++ b/android_webview/browser/aw_contents.h
@@ -70,6 +70,10 @@
   static std::string GetLocaleList();
 
   AwContents(std::unique_ptr<content::WebContents> web_contents);
+
+  AwContents(const AwContents&) = delete;
+  AwContents& operator=(const AwContents&) = delete;
+
   ~AwContents() override;
 
   AwRenderViewHostExt* render_view_host_ext() {
@@ -432,8 +436,6 @@
   typedef std::pair<const GURL, PermissionCallback> OriginCallback;
   // The first element in the list is always the currently pending request.
   std::list<OriginCallback> pending_geolocation_prompts_;
-
-  DISALLOW_COPY_AND_ASSIGN(AwContents);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/aw_contents_client_bridge.cc b/android_webview/browser/aw_contents_client_bridge.cc
index 07bb7b6..733a5cb 100644
--- a/android_webview/browser/aw_contents_client_bridge.cc
+++ b/android_webview/browser/aw_contents_client_bridge.cc
@@ -64,10 +64,11 @@
 
   explicit UserData(AwContentsClientBridge* ptr) : contents_(ptr) {}
 
+  UserData(const UserData&) = delete;
+  UserData& operator=(const UserData&) = delete;
+
  private:
   AwContentsClientBridge* contents_;
-
-  DISALLOW_COPY_AND_ASSIGN(UserData);
 };
 
 }  // namespace
diff --git a/android_webview/browser/aw_contents_client_bridge_unittest.cc b/android_webview/browser/aw_contents_client_bridge_unittest.cc
index 6b58ed7..8e8c398 100644
--- a/android_webview/browser/aw_contents_client_bridge_unittest.cc
+++ b/android_webview/browser/aw_contents_client_bridge_unittest.cc
@@ -64,6 +64,10 @@
   explicit TestClientCertificateDelegate(AwContentsClientBridgeTest* test)
       : test_(test) {}
 
+  TestClientCertificateDelegate(const TestClientCertificateDelegate&) = delete;
+  TestClientCertificateDelegate& operator=(
+      const TestClientCertificateDelegate&) = delete;
+
   // content::ClientCertificateDelegate.
   void ContinueWithCertificate(scoped_refptr<net::X509Certificate> cert,
                                scoped_refptr<net::SSLPrivateKey> key) override {
@@ -73,8 +77,6 @@
 
  private:
   AwContentsClientBridgeTest* test_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestClientCertificateDelegate);
 };
 
 }  // namespace
diff --git a/android_webview/browser/aw_contents_io_thread_client.h b/android_webview/browser/aw_contents_io_thread_client.h
index 8fc44e59..eb17bc20 100644
--- a/android_webview/browser/aw_contents_io_thread_client.h
+++ b/android_webview/browser/aw_contents_io_thread_client.h
@@ -72,6 +72,10 @@
   // Java object.
   AwContentsIoThreadClient(bool pending_associate,
                            const base::android::JavaRef<jobject>& jclient);
+
+  AwContentsIoThreadClient(const AwContentsIoThreadClient&) = delete;
+  AwContentsIoThreadClient& operator=(const AwContentsIoThreadClient&) = delete;
+
   ~AwContentsIoThreadClient();
 
   // Implementation of AwContentsIoThreadClient.
@@ -137,8 +141,6 @@
   base::android::ScopedJavaGlobalRef<jobject> bg_thread_client_object_;
   scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner_ =
       base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()});
-
-  DISALLOW_COPY_AND_ASSIGN(AwContentsIoThreadClient);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/aw_cookie_access_policy.h b/android_webview/browser/aw_cookie_access_policy.h
index 053cc72b..3bc7467 100644
--- a/android_webview/browser/aw_cookie_access_policy.h
+++ b/android_webview/browser/aw_cookie_access_policy.h
@@ -24,6 +24,9 @@
  public:
   static AwCookieAccessPolicy* GetInstance();
 
+  AwCookieAccessPolicy(const AwCookieAccessPolicy&) = delete;
+  AwCookieAccessPolicy& operator=(const AwCookieAccessPolicy&) = delete;
+
   // Can we read/write any cookies? Can be called from any thread.
   bool GetShouldAcceptCookies();
   void SetShouldAcceptCookies(bool allow);
@@ -55,8 +58,6 @@
                         bool accept_third_party_cookies);
   bool accept_cookies_;
   base::Lock lock_;
-
-  DISALLOW_COPY_AND_ASSIGN(AwCookieAccessPolicy);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/aw_devtools_manager_delegate.h b/android_webview/browser/aw_devtools_manager_delegate.h
index 08d6990..2f57307 100644
--- a/android_webview/browser/aw_devtools_manager_delegate.h
+++ b/android_webview/browser/aw_devtools_manager_delegate.h
@@ -20,15 +20,17 @@
 class AwDevToolsManagerDelegate : public content::DevToolsManagerDelegate {
  public:
   AwDevToolsManagerDelegate();
+
+  AwDevToolsManagerDelegate(const AwDevToolsManagerDelegate&) = delete;
+  AwDevToolsManagerDelegate& operator=(const AwDevToolsManagerDelegate&) =
+      delete;
+
   ~AwDevToolsManagerDelegate() override;
 
   // content::DevToolsManagerDelegate implementation.
   std::string GetTargetDescription(content::WebContents* web_contents) override;
   std::string GetDiscoveryPageHTML() override;
   bool IsBrowserTargetDiscoverable() override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(AwDevToolsManagerDelegate);
 };
 
 } //  namespace android_webview
diff --git a/android_webview/browser/aw_devtools_server.cc b/android_webview/browser/aw_devtools_server.cc
index 6d5ab98..6606fb08 100644
--- a/android_webview/browser/aw_devtools_server.cc
+++ b/android_webview/browser/aw_devtools_server.cc
@@ -38,6 +38,10 @@
   explicit UnixDomainServerSocketFactory(const std::string& socket_name)
       : socket_name_(socket_name), last_tethering_socket_(0) {}
 
+  UnixDomainServerSocketFactory(const UnixDomainServerSocketFactory&) = delete;
+  UnixDomainServerSocketFactory& operator=(
+      const UnixDomainServerSocketFactory&) = delete;
+
  private:
   // content::DevToolsAgentHost::ServerSocketFactory.
   std::unique_ptr<net::ServerSocket> CreateForHttpServer() override {
@@ -67,8 +71,6 @@
 
   std::string socket_name_;
   int last_tethering_socket_;
-
-  DISALLOW_COPY_AND_ASSIGN(UnixDomainServerSocketFactory);
 };
 
 class TCPServerSocketFactory : public content::DevToolsSocketFactory {
@@ -76,6 +78,9 @@
   TCPServerSocketFactory(const std::string& address, uint16_t port)
       : address_(address), port_(port) {}
 
+  TCPServerSocketFactory(const TCPServerSocketFactory&) = delete;
+  TCPServerSocketFactory& operator=(const TCPServerSocketFactory&) = delete;
+
  private:
   // content::DevToolsSocketFactory.
   std::unique_ptr<net::ServerSocket> CreateForHttpServer() override {
@@ -95,8 +100,6 @@
 
   std::string address_;
   uint16_t port_;
-
-  DISALLOW_COPY_AND_ASSIGN(TCPServerSocketFactory);
 };
 
 std::unique_ptr<content::DevToolsSocketFactory> CreateSocketFactory() {
diff --git a/android_webview/browser/aw_devtools_server.h b/android_webview/browser/aw_devtools_server.h
index 8cdbb13..5564cc5 100644
--- a/android_webview/browser/aw_devtools_server.h
+++ b/android_webview/browser/aw_devtools_server.h
@@ -13,6 +13,10 @@
 class AwDevToolsServer {
  public:
   AwDevToolsServer();
+
+  AwDevToolsServer(const AwDevToolsServer&) = delete;
+  AwDevToolsServer& operator=(const AwDevToolsServer&) = delete;
+
   ~AwDevToolsServer();
 
   // Opens linux abstract socket to be ready for remote debugging.
@@ -25,7 +29,6 @@
 
  private:
   bool is_started_;
-  DISALLOW_COPY_AND_ASSIGN(AwDevToolsServer);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/aw_download_manager_delegate.h b/android_webview/browser/aw_download_manager_delegate.h
index 25337e39..9009b14 100644
--- a/android_webview/browser/aw_download_manager_delegate.h
+++ b/android_webview/browser/aw_download_manager_delegate.h
@@ -25,6 +25,11 @@
                                   public base::SupportsUserData::Data {
  public:
   AwDownloadManagerDelegate();
+
+  AwDownloadManagerDelegate(const AwDownloadManagerDelegate&) = delete;
+  AwDownloadManagerDelegate& operator=(const AwDownloadManagerDelegate&) =
+      delete;
+
   ~AwDownloadManagerDelegate() override;
 
   // content::DownloadManagerDelegate implementation.
@@ -37,9 +42,6 @@
       int64_t content_length,
       bool is_transient,
       content::WebContents* web_contents) override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(AwDownloadManagerDelegate);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/aw_feature_list_creator.h b/android_webview/browser/aw_feature_list_creator.h
index 3624284..eb96a0e 100644
--- a/android_webview/browser/aw_feature_list_creator.h
+++ b/android_webview/browser/aw_feature_list_creator.h
@@ -23,6 +23,10 @@
 class AwFeatureListCreator {
  public:
   AwFeatureListCreator();
+
+  AwFeatureListCreator(const AwFeatureListCreator&) = delete;
+  AwFeatureListCreator& operator=(const AwFeatureListCreator&) = delete;
+
   ~AwFeatureListCreator();
 
   // Initializes all necessary parameters to create the feature list and setup
@@ -67,8 +71,6 @@
   std::unique_ptr<AwVariationsServiceClient> client_;
 
   std::unique_ptr<AwBrowserPolicyConnector> browser_policy_connector_;
-
-  DISALLOW_COPY_AND_ASSIGN(AwFeatureListCreator);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/aw_field_trials.h b/android_webview/browser/aw_field_trials.h
index fb5ac5a3..78b9840 100644
--- a/android_webview/browser/aw_field_trials.h
+++ b/android_webview/browser/aw_field_trials.h
@@ -13,6 +13,10 @@
 class AwFieldTrials : public variations::PlatformFieldTrials {
  public:
   AwFieldTrials() = default;
+
+  AwFieldTrials(const AwFieldTrials&) = delete;
+  AwFieldTrials& operator=(const AwFieldTrials&) = delete;
+
   ~AwFieldTrials() override = default;
 
   // variations::PlatformFieldTrials:
@@ -21,9 +25,6 @@
       bool has_seed,
       const base::FieldTrial::EntropyProvider* low_entropy_provider,
       base::FeatureList* feature_list) override {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(AwFieldTrials);
 };
 
 #endif  // ANDROID_WEBVIEW_BROWSER_AW_FIELD_TRIALS_H_
diff --git a/android_webview/browser/aw_form_database_service.h b/android_webview/browser/aw_form_database_service.h
index 3b8591f..1113d34 100644
--- a/android_webview/browser/aw_form_database_service.h
+++ b/android_webview/browser/aw_form_database_service.h
@@ -22,6 +22,9 @@
  public:
   AwFormDatabaseService(const base::FilePath path);
 
+  AwFormDatabaseService(const AwFormDatabaseService&) = delete;
+  AwFormDatabaseService& operator=(const AwFormDatabaseService&) = delete;
+
   ~AwFormDatabaseService() override;
 
   void Shutdown();
@@ -47,8 +50,6 @@
 
   scoped_refptr<autofill::AutofillWebDataService> autofill_data_;
   scoped_refptr<WebDatabaseService> web_database_;
-
-  DISALLOW_COPY_AND_ASSIGN(AwFormDatabaseService);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/aw_javascript_dialog_manager.h b/android_webview/browser/aw_javascript_dialog_manager.h
index d8b3daf..4dfdfab 100644
--- a/android_webview/browser/aw_javascript_dialog_manager.h
+++ b/android_webview/browser/aw_javascript_dialog_manager.h
@@ -13,6 +13,11 @@
 class AwJavaScriptDialogManager : public content::JavaScriptDialogManager {
  public:
   AwJavaScriptDialogManager();
+
+  AwJavaScriptDialogManager(const AwJavaScriptDialogManager&) = delete;
+  AwJavaScriptDialogManager& operator=(const AwJavaScriptDialogManager&) =
+      delete;
+
   ~AwJavaScriptDialogManager() override;
 
   // Overridden from content::JavaScriptDialogManager:
@@ -29,9 +34,6 @@
                              DialogClosedCallback callback) override;
   void CancelDialogs(content::WebContents* web_contents,
                      bool reset_state) override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(AwJavaScriptDialogManager);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/aw_pdf_exporter.h b/android_webview/browser/aw_pdf_exporter.h
index 3adb070..c8c0265 100644
--- a/android_webview/browser/aw_pdf_exporter.h
+++ b/android_webview/browser/aw_pdf_exporter.h
@@ -27,6 +27,9 @@
                 const base::android::JavaRef<jobject>& obj,
                 content::WebContents* web_contents);
 
+  AwPdfExporter(const AwPdfExporter&) = delete;
+  AwPdfExporter& operator=(const AwPdfExporter&) = delete;
+
   ~AwPdfExporter();
 
   void ExportToPdf(JNIEnv* env,
@@ -44,8 +47,6 @@
 
   JavaObjectWeakGlobalRef java_ref_;
   content::WebContents* web_contents_;
-
-  DISALLOW_COPY_AND_ASSIGN(AwPdfExporter);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/aw_permission_manager.cc b/android_webview/browser/aw_permission_manager.cc
index 15407a2a..c7e5c9d 100644
--- a/android_webview/browser/aw_permission_manager.cc
+++ b/android_webview/browser/aw_permission_manager.cc
@@ -44,6 +44,9 @@
  public:
   LastRequestResultCache() = default;
 
+  LastRequestResultCache(const LastRequestResultCache&) = delete;
+  LastRequestResultCache& operator=(const LastRequestResultCache&) = delete;
+
   void SetResult(PermissionType permission,
                  const GURL& requesting_origin,
                  const GURL& embedding_origin,
@@ -147,8 +150,6 @@
 
   using StatusMap = std::unordered_map<std::string, PermissionStatus>;
   StatusMap pmi_result_cache_;
-
-  DISALLOW_COPY_AND_ASSIGN(LastRequestResultCache);
 };
 
 class AwPermissionManager::PendingRequest {
diff --git a/android_webview/browser/aw_permission_manager.h b/android_webview/browser/aw_permission_manager.h
index b9d9879..4adc7df 100644
--- a/android_webview/browser/aw_permission_manager.h
+++ b/android_webview/browser/aw_permission_manager.h
@@ -21,6 +21,10 @@
 class AwPermissionManager : public content::PermissionControllerDelegate {
  public:
   AwPermissionManager();
+
+  AwPermissionManager(const AwPermissionManager&) = delete;
+  AwPermissionManager& operator=(const AwPermissionManager&) = delete;
+
   ~AwPermissionManager() override;
 
   // PermissionControllerDelegate implementation.
@@ -87,8 +91,6 @@
   std::unique_ptr<LastRequestResultCache> result_cache_;
 
   base::WeakPtrFactory<AwPermissionManager> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(AwPermissionManager);
 };
 
 } // namespace android_webview
diff --git a/android_webview/browser/aw_print_manager.h b/android_webview/browser/aw_print_manager.h
index c11ac76..9f87301 100644
--- a/android_webview/browser/aw_print_manager.h
+++ b/android_webview/browser/aw_print_manager.h
@@ -18,6 +18,9 @@
 class AwPrintManager : public printing::PrintManager,
     public content::WebContentsUserData<AwPrintManager> {
  public:
+  AwPrintManager(const AwPrintManager&) = delete;
+  AwPrintManager& operator=(const AwPrintManager&) = delete;
+
   ~AwPrintManager() override;
 
   static void BindPrintManagerHost(
@@ -59,8 +62,6 @@
   int fd_ = -1;
 
   WEB_CONTENTS_USER_DATA_KEY_DECL();
-
-  DISALLOW_COPY_AND_ASSIGN(AwPrintManager);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/aw_quota_manager_bridge.cc b/android_webview/browser/aw_quota_manager_bridge.cc
index 41e201b..1972275a5 100644
--- a/android_webview/browser/aw_quota_manager_bridge.cc
+++ b/android_webview/browser/aw_quota_manager_bridge.cc
@@ -46,6 +46,9 @@
   GetStorageKeysTask(AwQuotaManagerBridge::GetOriginsCallback callback,
                      QuotaManager* quota_manager);
 
+  GetStorageKeysTask(const GetStorageKeysTask&) = delete;
+  GetStorageKeysTask& operator=(const GetStorageKeysTask&) = delete;
+
   void Run();
 
  private:
@@ -72,8 +75,6 @@
 
   size_t num_callbacks_to_wait_;
   size_t num_callbacks_received_;
-
-  DISALLOW_COPY_AND_ASSIGN(GetStorageKeysTask);
 };
 
 GetStorageKeysTask::GetStorageKeysTask(
diff --git a/android_webview/browser/aw_quota_manager_bridge.h b/android_webview/browser/aw_quota_manager_bridge.h
index 85fbd67..efbf724 100644
--- a/android_webview/browser/aw_quota_manager_bridge.h
+++ b/android_webview/browser/aw_quota_manager_bridge.h
@@ -33,6 +33,9 @@
 class AwQuotaManagerBridge
     : public base::RefCountedThreadSafe<AwQuotaManagerBridge> {
  public:
+  AwQuotaManagerBridge(const AwQuotaManagerBridge&) = delete;
+  AwQuotaManagerBridge& operator=(const AwQuotaManagerBridge&) = delete;
+
   static scoped_refptr<AwQuotaManagerBridge> Create(
       AwBrowserContext* browser_context);
 
@@ -89,8 +92,6 @@
   JavaObjectWeakGlobalRef java_ref_;
 
   base::WeakPtrFactory<AwQuotaManagerBridge> weak_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(AwQuotaManagerBridge);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/aw_quota_permission_context.h b/android_webview/browser/aw_quota_permission_context.h
index 9857651..998c64e6 100644
--- a/android_webview/browser/aw_quota_permission_context.h
+++ b/android_webview/browser/aw_quota_permission_context.h
@@ -15,14 +15,15 @@
  public:
   AwQuotaPermissionContext();
 
+  AwQuotaPermissionContext(const AwQuotaPermissionContext&) = delete;
+  AwQuotaPermissionContext& operator=(const AwQuotaPermissionContext&) = delete;
+
   void RequestQuotaPermission(const content::StorageQuotaParams& params,
                               int render_process_id,
                               PermissionCallback callback) override;
 
  private:
   ~AwQuotaPermissionContext() override;
-
-  DISALLOW_COPY_AND_ASSIGN(AwQuotaPermissionContext);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/aw_render_process.h b/android_webview/browser/aw_render_process.h
index cd0ec4fa..a01b952 100644
--- a/android_webview/browser/aw_render_process.h
+++ b/android_webview/browser/aw_render_process.h
@@ -30,6 +30,10 @@
       const base::android::JavaParamRef<jobject>& obj);
 
   explicit AwRenderProcess(content::RenderProcessHost* render_process_host);
+
+  AwRenderProcess(const AwRenderProcess&) = delete;
+  AwRenderProcess& operator=(const AwRenderProcess&) = delete;
+
   ~AwRenderProcess() override;
 
   void ClearCache();
@@ -57,7 +61,6 @@
   mojo::AssociatedRemote<mojom::Renderer> renderer_remote_;
 
   base::WeakPtrFactory<AwRenderProcess> weak_factory_{this};
-  DISALLOW_COPY_AND_ASSIGN(AwRenderProcess);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/aw_resource_context.h b/android_webview/browser/aw_resource_context.h
index 2095d8e..71dc35a8 100644
--- a/android_webview/browser/aw_resource_context.h
+++ b/android_webview/browser/aw_resource_context.h
@@ -19,6 +19,10 @@
 class AwResourceContext : public content::ResourceContext {
  public:
   AwResourceContext();
+
+  AwResourceContext(const AwResourceContext&) = delete;
+  AwResourceContext& operator=(const AwResourceContext&) = delete;
+
   ~AwResourceContext() override;
 
   void SetExtraHeaders(const GURL& url, const std::string& headers);
@@ -27,8 +31,6 @@
  private:
   base::Lock extra_headers_lock_;
   std::map<std::string, std::string> extra_headers_;
-
-  DISALLOW_COPY_AND_ASSIGN(AwResourceContext);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/aw_speech_recognition_manager_delegate.h b/android_webview/browser/aw_speech_recognition_manager_delegate.h
index c791e312..9fcb57f3 100644
--- a/android_webview/browser/aw_speech_recognition_manager_delegate.h
+++ b/android_webview/browser/aw_speech_recognition_manager_delegate.h
@@ -20,6 +20,12 @@
       public content::SpeechRecognitionEventListener {
  public:
   AwSpeechRecognitionManagerDelegate();
+
+  AwSpeechRecognitionManagerDelegate(
+      const AwSpeechRecognitionManagerDelegate&) = delete;
+  AwSpeechRecognitionManagerDelegate& operator=(
+      const AwSpeechRecognitionManagerDelegate&) = delete;
+
   ~AwSpeechRecognitionManagerDelegate() override;
 
  protected:
@@ -57,8 +63,6 @@
       base::OnceCallback<void(bool ask_user, bool is_allowed)> callback,
       int render_process_id,
       int render_frame_id);
-
-  DISALLOW_COPY_AND_ASSIGN(AwSpeechRecognitionManagerDelegate);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/aw_ssl_host_state_delegate.h b/android_webview/browser/aw_ssl_host_state_delegate.h
index 9d44c44..65695fc 100644
--- a/android_webview/browser/aw_ssl_host_state_delegate.h
+++ b/android_webview/browser/aw_ssl_host_state_delegate.h
@@ -44,6 +44,10 @@
 class AwSSLHostStateDelegate : public content::SSLHostStateDelegate {
  public:
   AwSSLHostStateDelegate();
+
+  AwSSLHostStateDelegate(const AwSSLHostStateDelegate&) = delete;
+  AwSSLHostStateDelegate& operator=(const AwSSLHostStateDelegate&) = delete;
+
   ~AwSSLHostStateDelegate() override;
 
   // Records that |cert| is permitted to be used for |host| in the future, for
@@ -93,8 +97,6 @@
  private:
   // Certificate policies for each host.
   std::map<std::string, internal::CertPolicy> cert_policy_for_host_;
-
-  DISALLOW_COPY_AND_ASSIGN(AwSSLHostStateDelegate);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/aw_web_contents_view_delegate.h b/android_webview/browser/aw_web_contents_view_delegate.h
index 8ef322c..b904ab9 100644
--- a/android_webview/browser/aw_web_contents_view_delegate.h
+++ b/android_webview/browser/aw_web_contents_view_delegate.h
@@ -20,6 +20,10 @@
   static content::WebContentsViewDelegate* Create(
       content::WebContents* web_contents);
 
+  AwWebContentsViewDelegate(const AwWebContentsViewDelegate&) = delete;
+  AwWebContentsViewDelegate& operator=(const AwWebContentsViewDelegate&) =
+      delete;
+
   ~AwWebContentsViewDelegate() override;
 
   // content::WebContentsViewDelegate implementation.
@@ -27,8 +31,6 @@
 
  private:
   AwWebContentsViewDelegate(content::WebContents* web_contents);
-
-  DISALLOW_COPY_AND_ASSIGN(AwWebContentsViewDelegate);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/aw_web_ui_controller_factory.h b/android_webview/browser/aw_web_ui_controller_factory.h
index 5953bc4..8c56f54 100644
--- a/android_webview/browser/aw_web_ui_controller_factory.h
+++ b/android_webview/browser/aw_web_ui_controller_factory.h
@@ -15,6 +15,9 @@
  public:
   static AwWebUIControllerFactory* GetInstance();
 
+  AwWebUIControllerFactory(const AwWebUIControllerFactory&) = delete;
+  AwWebUIControllerFactory& operator=(const AwWebUIControllerFactory&) = delete;
+
   // content::WebUIControllerFactory overrides
   content::WebUI::TypeID GetWebUIType(content::BrowserContext* browser_context,
                                       const GURL& url) override;
@@ -29,8 +32,6 @@
 
   AwWebUIControllerFactory();
   ~AwWebUIControllerFactory() override;
-
-  DISALLOW_COPY_AND_ASSIGN(AwWebUIControllerFactory);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/cookie_manager.h b/android_webview/browser/cookie_manager.h
index 02635639..6f1287ca 100644
--- a/android_webview/browser/cookie_manager.h
+++ b/android_webview/browser/cookie_manager.h
@@ -86,6 +86,9 @@
  public:
   static CookieManager* GetInstance();
 
+  CookieManager(const CookieManager&) = delete;
+  CookieManager& operator=(const CookieManager&) = delete;
+
   // Passes a |cookie_manager_remote|, which this will use for CookieManager
   // APIs going forward. Only called in the Network Service path, with the
   // intention this is called once during content initialization (when we create
@@ -271,8 +274,6 @@
 
   // The CookieManager shared with the NetworkContext.
   mojo::Remote<network::mojom::CookieManager> mojo_cookie_manager_;
-
-  DISALLOW_COPY_AND_ASSIGN(CookieManager);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/find_helper.h b/android_webview/browser/find_helper.h
index 442af6ec..978227c 100644
--- a/android_webview/browser/find_helper.h
+++ b/android_webview/browser/find_helper.h
@@ -25,6 +25,10 @@
   };
 
   explicit FindHelper(content::WebContents* web_contents);
+
+  FindHelper(const FindHelper&) = delete;
+  FindHelper& operator=(const FindHelper&) = delete;
+
   ~FindHelper() override;
 
   // Sets the listener to receive find result updates.
@@ -66,8 +70,6 @@
   std::u16string last_search_string_;
   int last_match_count_;
   int last_active_ordinal_;
-
-  DISALLOW_COPY_AND_ASSIGN(FindHelper);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/gfx/aw_draw_fn_impl.h b/android_webview/browser/gfx/aw_draw_fn_impl.h
index a88111d..699fc8e6 100644
--- a/android_webview/browser/gfx/aw_draw_fn_impl.h
+++ b/android_webview/browser/gfx/aw_draw_fn_impl.h
@@ -23,6 +23,10 @@
   static bool IsUsingVulkan();
 
   AwDrawFnImpl();
+
+  AwDrawFnImpl(const AwDrawFnImpl&) = delete;
+  AwDrawFnImpl& operator=(const AwDrawFnImpl&) = delete;
+
   ~AwDrawFnImpl();
 
   void ReleaseHandle(JNIEnv* env,
@@ -67,8 +71,6 @@
       scoped_secondary_cb_draw_;
 
   absl::optional<VulkanGLInterop> interop_;
-
-  DISALLOW_COPY_AND_ASSIGN(AwDrawFnImpl);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/gfx/aw_gl_surface.h b/android_webview/browser/gfx/aw_gl_surface.h
index 5762e73..824d4ee5 100644
--- a/android_webview/browser/gfx/aw_gl_surface.h
+++ b/android_webview/browser/gfx/aw_gl_surface.h
@@ -20,6 +20,9 @@
   explicit AwGLSurface(bool is_angle);
   explicit AwGLSurface(scoped_refptr<gl::GLSurface> surface);
 
+  AwGLSurface(const AwGLSurface&) = delete;
+  AwGLSurface& operator=(const AwGLSurface&) = delete;
+
   // Implement GLSurface.
   bool Initialize(gl::GLSurfaceFormat format) override;
   void Destroy() override;
@@ -62,7 +65,6 @@
   PresentationCallback pending_presentation_callback_;
   gfx::Size size_{1, 1};
   EGLSurface surface_ = nullptr;
-  DISALLOW_COPY_AND_ASSIGN(AwGLSurface);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/gfx/aw_picture.h b/android_webview/browser/gfx/aw_picture.h
index 800bfff42..73f368d 100644
--- a/android_webview/browser/gfx/aw_picture.h
+++ b/android_webview/browser/gfx/aw_picture.h
@@ -16,6 +16,11 @@
 class AwPicture {
  public:
   AwPicture(sk_sp<SkPicture> picture);
+
+  AwPicture() = delete;
+  AwPicture(const AwPicture&) = delete;
+  AwPicture& operator=(const AwPicture&) = delete;
+
   ~AwPicture();
 
   // Methods called from Java.
@@ -28,8 +33,6 @@
 
  private:
   sk_sp<SkPicture> picture_;
-
-  DISALLOW_IMPLICIT_CONSTRUCTORS(AwPicture);
 };
 
 }  // android_webview
diff --git a/android_webview/browser/gfx/aw_vulkan_context_provider.h b/android_webview/browser/gfx/aw_vulkan_context_provider.h
index b7d16d0e..26579f7 100644
--- a/android_webview/browser/gfx/aw_vulkan_context_provider.h
+++ b/android_webview/browser/gfx/aw_vulkan_context_provider.h
@@ -36,14 +36,19 @@
         : provider_(provider) {
       provider_->SecondaryCBDrawBegin(std::move(draw_context));
     }
+
+    ScopedSecondaryCBDraw(const ScopedSecondaryCBDraw&) = delete;
+    ScopedSecondaryCBDraw& operator=(const ScopedSecondaryCBDraw&) = delete;
+
     ~ScopedSecondaryCBDraw() { provider_->SecondaryCMBDrawSubmitted(); }
 
    private:
     AwVulkanContextProvider* const provider_;
-
-    DISALLOW_COPY_AND_ASSIGN(ScopedSecondaryCBDraw);
   };
 
+  AwVulkanContextProvider(const AwVulkanContextProvider&) = delete;
+  AwVulkanContextProvider& operator=(const AwVulkanContextProvider&) = delete;
+
   static scoped_refptr<AwVulkanContextProvider> Create(
       AwDrawFn_InitVkParams* params);
 
@@ -92,8 +97,6 @@
   sk_sp<GrVkSecondaryCBDrawContext> draw_context_;
   std::vector<base::OnceClosure> post_submit_tasks_;
   std::vector<VkSemaphore> post_submit_semaphores_;
-
-  DISALLOW_COPY_AND_ASSIGN(AwVulkanContextProvider);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/gfx/browser_view_renderer.h b/android_webview/browser/gfx/browser_view_renderer.h
index 7a60b8d81..244aadb 100644
--- a/android_webview/browser/gfx/browser_view_renderer.h
+++ b/android_webview/browser/gfx/browser_view_renderer.h
@@ -57,6 +57,9 @@
       BrowserViewRendererClient* client,
       const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner);
 
+  BrowserViewRenderer(const BrowserViewRenderer&) = delete;
+  BrowserViewRenderer& operator=(const BrowserViewRenderer&) = delete;
+
   ~BrowserViewRenderer() override;
 
   void RegisterWithWebContents(content::WebContents* web_contents);
@@ -278,8 +281,6 @@
   std::unique_ptr<BeginFrameSourceWebView> begin_frame_source_;
 
   base::WeakPtrFactory<CompositorFrameProducer> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(BrowserViewRenderer);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/gfx/child_frame.h b/android_webview/browser/gfx/child_frame.h
index 12539613..11dc71347 100644
--- a/android_webview/browser/gfx/child_frame.h
+++ b/android_webview/browser/gfx/child_frame.h
@@ -38,6 +38,10 @@
       float device_scale_factor,
       CopyOutputRequestQueue copy_requests,
       bool did_invalidate);
+
+  ChildFrame(const ChildFrame&) = delete;
+  ChildFrame& operator=(const ChildFrame&) = delete;
+
   ~ChildFrame();
 
   // Helper to move frame from |frame_future| to |frame|.
@@ -63,9 +67,6 @@
 
   // Used for metrics, indicates that we invalidated for this frame.
   const bool did_invalidate;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ChildFrame);
 };
 
 using ChildFrameQueue = base::circular_deque<std::unique_ptr<ChildFrame>>;
diff --git a/android_webview/browser/gfx/deferred_gpu_command_service.h b/android_webview/browser/gfx/deferred_gpu_command_service.h
index ffc6da7..06c7b5b 100644
--- a/android_webview/browser/gfx/deferred_gpu_command_service.h
+++ b/android_webview/browser/gfx/deferred_gpu_command_service.h
@@ -22,6 +22,10 @@
  public:
   static DeferredGpuCommandService* GetInstance();
 
+  DeferredGpuCommandService(const DeferredGpuCommandService&) = delete;
+  DeferredGpuCommandService& operator=(const DeferredGpuCommandService&) =
+      delete;
+
   // gpu::CommandBufferTaskExecutor implementation.
   bool ForceVirtualizedGLContexts() const override;
   bool ShouldCreateMemoryTracker() const override;
@@ -46,8 +50,6 @@
   TaskQueueWebView* task_queue_;
   GpuServiceWebView* gpu_service_;
   scoped_refptr<gl::GLShareGroup> share_group_;
-
-  DISALLOW_COPY_AND_ASSIGN(DeferredGpuCommandService);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/gfx/hardware_renderer.h b/android_webview/browser/gfx/hardware_renderer.h
index 7ad997df..554b0fc 100644
--- a/android_webview/browser/gfx/hardware_renderer.h
+++ b/android_webview/browser/gfx/hardware_renderer.h
@@ -61,6 +61,9 @@
   // * Append new frame without waiting on it.
   static ChildFrameQueue WaitAndPruneFrameQueue(ChildFrameQueue* child_frames);
 
+  HardwareRenderer(const HardwareRenderer&) = delete;
+  HardwareRenderer& operator=(const HardwareRenderer&) = delete;
+
   virtual ~HardwareRenderer();
 
   void Draw(const HardwareRendererDrawParams& params,
@@ -111,8 +114,6 @@
 
   // Draw params that was used in previous draw. Used in reporting draw metric.
   HardwareRendererDrawParams last_draw_params_ = {};
-
-  DISALLOW_COPY_AND_ASSIGN(HardwareRenderer);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/gfx/hardware_renderer_viz.cc b/android_webview/browser/gfx/hardware_renderer_viz.cc
index b1d4f9d..93759eb 100644
--- a/android_webview/browser/gfx/hardware_renderer_viz.cc
+++ b/android_webview/browser/gfx/hardware_renderer_viz.cc
@@ -67,6 +67,10 @@
  public:
   OnViz(OutputSurfaceProviderWebView* output_surface_provider,
         const scoped_refptr<RootFrameSink>& root_frame_sink);
+
+  OnViz(const OnViz&) = delete;
+  OnViz& operator=(const OnViz&) = delete;
+
   ~OnViz() override;
 
   void DrawAndSwapOnViz(const gfx::Size& viewport,
@@ -120,8 +124,6 @@
   OverlayProcessorWebView* overlay_processor_webview_ = nullptr;
 
   THREAD_CHECKER(viz_thread_checker_);
-
-  DISALLOW_COPY_AND_ASSIGN(OnViz);
 };
 
 HardwareRendererViz::OnViz::OnViz(
diff --git a/android_webview/browser/gfx/hardware_renderer_viz.h b/android_webview/browser/gfx/hardware_renderer_viz.h
index 5430a9b98..09041e560 100644
--- a/android_webview/browser/gfx/hardware_renderer_viz.h
+++ b/android_webview/browser/gfx/hardware_renderer_viz.h
@@ -23,6 +23,10 @@
   HardwareRendererViz(RenderThreadManager* state,
                       RootFrameSinkGetter root_frame_sink_getter,
                       AwVulkanContextProvider* context_provider);
+
+  HardwareRendererViz(const HardwareRendererViz&) = delete;
+  HardwareRendererViz& operator=(const HardwareRendererViz&) = delete;
+
   ~HardwareRendererViz() override;
 
   // HardwareRenderer overrides.
@@ -52,8 +56,6 @@
   std::unique_ptr<OnViz> on_viz_;
 
   THREAD_CHECKER(render_thread_checker_);
-
-  DISALLOW_COPY_AND_ASSIGN(HardwareRendererViz);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/gfx/java_browser_view_renderer_helper.cc b/android_webview/browser/gfx/java_browser_view_renderer_helper.cc
index 0a05fed..f69787f 100644
--- a/android_webview/browser/gfx/java_browser_view_renderer_helper.cc
+++ b/android_webview/browser/gfx/java_browser_view_renderer_helper.cc
@@ -30,6 +30,10 @@
   JavaCanvasHolder(JNIEnv* env,
                    jobject java_canvas,
                    const gfx::Vector2d& scroll_correction);
+
+  JavaCanvasHolder(const JavaCanvasHolder&) = delete;
+  JavaCanvasHolder& operator=(const JavaCanvasHolder&) = delete;
+
   ~JavaCanvasHolder() override;
 
   SkCanvas* GetCanvas() override;
@@ -37,7 +41,6 @@
  private:
   AwPixelInfo* pixels_;
   std::unique_ptr<SkCanvas> canvas_;
-  DISALLOW_COPY_AND_ASSIGN(JavaCanvasHolder);
 };
 
 JavaCanvasHolder::JavaCanvasHolder(JNIEnv* env,
@@ -79,6 +82,10 @@
                         jobject java_canvas,
                         const gfx::Vector2d& scroll_correction,
                         const gfx::Size size);
+
+  AuxiliaryCanvasHolder(const AuxiliaryCanvasHolder&) = delete;
+  AuxiliaryCanvasHolder& operator=(const AuxiliaryCanvasHolder&) = delete;
+
   ~AuxiliaryCanvasHolder() override;
 
   SkCanvas* GetCanvas() override;
@@ -89,7 +96,6 @@
   gfx::Vector2d scroll_;
   std::unique_ptr<SkBitmap> bitmap_;
   std::unique_ptr<SkCanvas> canvas_;
-  DISALLOW_COPY_AND_ASSIGN(AuxiliaryCanvasHolder);
 };
 
 AuxiliaryCanvasHolder::AuxiliaryCanvasHolder(
diff --git a/android_webview/browser/gfx/render_thread_manager.h b/android_webview/browser/gfx/render_thread_manager.h
index 6f1f5ce..6c3f122 100644
--- a/android_webview/browser/gfx/render_thread_manager.h
+++ b/android_webview/browser/gfx/render_thread_manager.h
@@ -30,6 +30,10 @@
  public:
   explicit RenderThreadManager(
       const scoped_refptr<base::SingleThreadTaskRunner>& ui_loop);
+
+  RenderThreadManager(const RenderThreadManager&) = delete;
+  RenderThreadManager& operator=(const RenderThreadManager&) = delete;
+
   ~RenderThreadManager() override;
 
   // CompositorFrameConsumer methods.
@@ -126,8 +130,6 @@
   uint32_t presented_frame_token_ = 0u;
 
   base::WeakPtrFactory<RenderThreadManager> weak_factory_on_ui_thread_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(RenderThreadManager);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/gfx/root_frame_sink.h b/android_webview/browser/gfx/root_frame_sink.h
index 54aafc9..c0c9ea4 100644
--- a/android_webview/browser/gfx/root_frame_sink.h
+++ b/android_webview/browser/gfx/root_frame_sink.h
@@ -48,6 +48,9 @@
   using SetNeedsBeginFrameCallback = base::RepeatingCallback<void(bool)>;
   RootFrameSink(RootFrameSinkClient* client);
 
+  RootFrameSink(const RootFrameSink&) = delete;
+  RootFrameSink& operator=(const RootFrameSink&) = delete;
+
   const viz::FrameSinkId& root_frame_sink_id() const {
     return root_frame_sink_id_;
   }
@@ -109,8 +112,6 @@
   RootFrameSinkClient* client_;
 
   THREAD_CHECKER(thread_checker_);
-
-  DISALLOW_COPY_AND_ASSIGN(RootFrameSink);
 };
 
 using RootFrameSinkGetter =
diff --git a/android_webview/browser/gfx/root_frame_sink_proxy.h b/android_webview/browser/gfx/root_frame_sink_proxy.h
index a64b6350..f84b39e1 100644
--- a/android_webview/browser/gfx/root_frame_sink_proxy.h
+++ b/android_webview/browser/gfx/root_frame_sink_proxy.h
@@ -34,6 +34,10 @@
       const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner,
       RootFrameSinkProxyClient* client,
       viz::BeginFrameSource* begin_frame_source);
+
+  RootFrameSinkProxy(const RootFrameSinkProxy&) = delete;
+  RootFrameSinkProxy& operator=(const RootFrameSinkProxy&) = delete;
+
   ~RootFrameSinkProxy() override;
 
   void AddChildFrameSinkId(const viz::FrameSinkId& frame_sink_id);
@@ -86,8 +90,6 @@
 
   base::WeakPtrFactory<RootFrameSinkProxy> weak_ptr_factory_{this};
   base::WeakPtrFactory<RootFrameSinkProxy> weak_ptr_factory_on_viz_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(RootFrameSinkProxy);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/gfx/scoped_app_gl_state_restore.h b/android_webview/browser/gfx/scoped_app_gl_state_restore.h
index f05fdf44..5813fa4 100644
--- a/android_webview/browser/gfx/scoped_app_gl_state_restore.h
+++ b/android_webview/browser/gfx/scoped_app_gl_state_restore.h
@@ -42,6 +42,10 @@
   static ScopedAppGLStateRestore* Current();
 
   ScopedAppGLStateRestore(CallMode mode, bool save_restore);
+
+  ScopedAppGLStateRestore(const ScopedAppGLStateRestore&) = delete;
+  ScopedAppGLStateRestore& operator=(const ScopedAppGLStateRestore&) = delete;
+
   ~ScopedAppGLStateRestore();
 
   StencilState stencil_state() const;
@@ -62,8 +66,6 @@
 
  private:
   std::unique_ptr<Impl> impl_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedAppGLStateRestore);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/gfx/scoped_app_gl_state_restore_impl.cc b/android_webview/browser/gfx/scoped_app_gl_state_restore_impl.cc
index 625da2a..22cb614 100644
--- a/android_webview/browser/gfx/scoped_app_gl_state_restore_impl.cc
+++ b/android_webview/browser/gfx/scoped_app_gl_state_restore_impl.cc
@@ -43,14 +43,16 @@
         context_(gl::init::CreateGLContext(nullptr,
                                            surface_.get(),
                                            gl::GLContextAttribs())) {}
+
+  AppContextSurface(const AppContextSurface&) = delete;
+  AppContextSurface& operator=(const AppContextSurface&) = delete;
+
   void MakeCurrent() { context_->MakeCurrent(surface_.get()); }
   void ReleaseCurrent() { context_->ReleaseCurrent(surface_.get()); }
 
  private:
   scoped_refptr<gl::GLSurface> surface_;
   scoped_refptr<gl::GLContext> context_;
-
-  DISALLOW_COPY_AND_ASSIGN(AppContextSurface);
 };
 
 base::LazyInstance<AppContextSurface>::DestructorAtExit g_app_context_surface =
diff --git a/android_webview/browser/gfx/scoped_app_gl_state_restore_impl.h b/android_webview/browser/gfx/scoped_app_gl_state_restore_impl.h
index f8648eab..209a26e 100644
--- a/android_webview/browser/gfx/scoped_app_gl_state_restore_impl.h
+++ b/android_webview/browser/gfx/scoped_app_gl_state_restore_impl.h
@@ -19,6 +19,11 @@
  public:
   ScopedAppGLStateRestoreImpl(ScopedAppGLStateRestore::CallMode mode,
                               bool save_restore);
+
+  ScopedAppGLStateRestoreImpl(const ScopedAppGLStateRestoreImpl&) = delete;
+  ScopedAppGLStateRestoreImpl& operator=(const ScopedAppGLStateRestoreImpl&) =
+      delete;
+
   ~ScopedAppGLStateRestoreImpl() override;
 
  protected:
@@ -96,8 +101,6 @@
   std::vector<TextureBindings> texture_bindings_;
 
   GLint vertex_array_bindings_oes_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedAppGLStateRestoreImpl);
 };
 
 }  // namespace internal
diff --git a/android_webview/browser/gfx/scoped_app_gl_state_restore_impl_angle.h b/android_webview/browser/gfx/scoped_app_gl_state_restore_impl_angle.h
index 76fba15..89345e8 100644
--- a/android_webview/browser/gfx/scoped_app_gl_state_restore_impl_angle.h
+++ b/android_webview/browser/gfx/scoped_app_gl_state_restore_impl_angle.h
@@ -18,13 +18,18 @@
  public:
   ScopedAppGLStateRestoreImplAngle(ScopedAppGLStateRestore::CallMode mode,
                                    bool save_restore);
+
+  ScopedAppGLStateRestoreImplAngle(const ScopedAppGLStateRestoreImplAngle&) =
+      delete;
+  ScopedAppGLStateRestoreImplAngle& operator=(
+      const ScopedAppGLStateRestoreImplAngle&) = delete;
+
   ~ScopedAppGLStateRestoreImplAngle() override;
 
  protected:
 #if DCHECK_IS_ON()
   EGLContext egl_context_ = EGL_NO_CONTEXT;
 #endif
-  DISALLOW_COPY_AND_ASSIGN(ScopedAppGLStateRestoreImplAngle);
 };
 
 }  // namespace internal
diff --git a/android_webview/browser/gfx/skia_output_surface_dependency_webview.h b/android_webview/browser/gfx/skia_output_surface_dependency_webview.h
index e677e45..e3df5d80 100644
--- a/android_webview/browser/gfx/skia_output_surface_dependency_webview.h
+++ b/android_webview/browser/gfx/skia_output_surface_dependency_webview.h
@@ -26,6 +26,12 @@
       gpu::SharedContextState* shared_context_state,
       gl::GLSurface* gl_surface,
       AwVulkanContextProvider* vulkan_context_provider);
+
+  SkiaOutputSurfaceDependencyWebView(
+      const SkiaOutputSurfaceDependencyWebView&) = delete;
+  SkiaOutputSurfaceDependencyWebView& operator=(
+      const SkiaOutputSurfaceDependencyWebView&) = delete;
+
   ~SkiaOutputSurfaceDependencyWebView() override;
 
   std::unique_ptr<gpu::SingleTaskSequence> CreateSequence() override;
@@ -64,8 +70,6 @@
   GpuServiceWebView* gpu_service_;
   gpu::GpuDriverBugWorkarounds workarounds_;
   gpu::SharedContextState* const shared_context_state_;
-
-  DISALLOW_COPY_AND_ASSIGN(SkiaOutputSurfaceDependencyWebView);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/gfx/task_forwarding_sequence.h b/android_webview/browser/gfx/task_forwarding_sequence.h
index c4029ee..05a4baf 100644
--- a/android_webview/browser/gfx/task_forwarding_sequence.h
+++ b/android_webview/browser/gfx/task_forwarding_sequence.h
@@ -27,6 +27,10 @@
  public:
   explicit TaskForwardingSequence(TaskQueueWebView* task_queue,
                                   gpu::SyncPointManager* sync_point_manager);
+
+  TaskForwardingSequence(const TaskForwardingSequence&) = delete;
+  TaskForwardingSequence& operator=(const TaskForwardingSequence&) = delete;
+
   ~TaskForwardingSequence() override;
 
   // SingleTaskSequence implementation.
@@ -62,8 +66,6 @@
   TaskQueueWebView* const task_queue_;
   gpu::SyncPointManager* const sync_point_manager_;
   scoped_refptr<gpu::SyncPointOrderData> sync_point_order_data_;
-
-  DISALLOW_COPY_AND_ASSIGN(TaskForwardingSequence);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/gfx/task_queue_webview.cc b/android_webview/browser/gfx/task_queue_webview.cc
index 62bae79..e5cb6dc 100644
--- a/android_webview/browser/gfx/task_queue_webview.cc
+++ b/android_webview/browser/gfx/task_queue_webview.cc
@@ -33,6 +33,10 @@
 class TaskQueueViz : public TaskQueueWebView {
  public:
   TaskQueueViz();
+
+  TaskQueueViz(const TaskQueueViz&) = delete;
+  TaskQueueViz& operator=(const TaskQueueViz&) = delete;
+
   ~TaskQueueViz() override;
 
   // TaskQueueWebView overrides.
@@ -62,8 +66,6 @@
   base::ConditionVariable condvar_{&lock_};
   bool done_ GUARDED_BY(lock_) = true;
   base::circular_deque<base::OnceClosure> tasks_ GUARDED_BY(lock_);
-
-  DISALLOW_COPY_AND_ASSIGN(TaskQueueViz);
 };
 
 TaskQueueViz::TaskQueueViz() {
diff --git a/android_webview/browser/gfx/test/fake_window.h b/android_webview/browser/gfx/test/fake_window.h
index 3d612448..bfffbf7a 100644
--- a/android_webview/browser/gfx/test/fake_window.h
+++ b/android_webview/browser/gfx/test/fake_window.h
@@ -46,6 +46,10 @@
 class FakeWindow {
  public:
   FakeWindow(BrowserViewRenderer* view, WindowHooks* hooks, gfx::Rect location);
+
+  FakeWindow(const FakeWindow&) = delete;
+  FakeWindow& operator=(const FakeWindow&) = delete;
+
   ~FakeWindow();
 
   void Detach();
@@ -94,8 +98,6 @@
   bool context_current_;
 
   base::WeakPtrFactory<FakeWindow> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(FakeWindow);
 };
 
 class FakeFunctor {
diff --git a/android_webview/browser/gfx/test/rendering_test.h b/android_webview/browser/gfx/test/rendering_test.h
index fa88eac..0942a1b 100644
--- a/android_webview/browser/gfx/test/rendering_test.h
+++ b/android_webview/browser/gfx/test/rendering_test.h
@@ -45,6 +45,9 @@
                       public BrowserViewRendererClient,
                       public WindowHooks {
  public:
+  RenderingTest(const RenderingTest&) = delete;
+  RenderingTest& operator=(const RenderingTest&) = delete;
+
   // BrowserViewRendererClient overrides.
   void OnNewPicture() override;
   void PostInvalidate() override;
@@ -100,8 +103,6 @@
  private:
   std::unique_ptr<base::test::TaskEnvironment> task_environment_;
   base::RunLoop run_loop_;
-
-  DISALLOW_COPY_AND_ASSIGN(RenderingTest);
 };
 
 #define RENDERING_TEST_F(TEST_FIXTURE_NAME)         \
diff --git a/android_webview/browser/gfx/viz_compositor_thread_runner_webview.h b/android_webview/browser/gfx/viz_compositor_thread_runner_webview.h
index 1082a768..c4449b1 100644
--- a/android_webview/browser/gfx/viz_compositor_thread_runner_webview.h
+++ b/android_webview/browser/gfx/viz_compositor_thread_runner_webview.h
@@ -40,6 +40,11 @@
  public:
   static VizCompositorThreadRunnerWebView* GetInstance();
 
+  VizCompositorThreadRunnerWebView(const VizCompositorThreadRunnerWebView&) =
+      delete;
+  VizCompositorThreadRunnerWebView& operator=(
+      const VizCompositorThreadRunnerWebView&) = delete;
+
   viz::FrameSinkManagerImpl* GetFrameSinkManager();
 
   // Must be called from the TaskQueueWebView thread. |task| is allowed to call
@@ -80,8 +85,6 @@
   std::unique_ptr<viz::ServerSharedBitmapManager> server_shared_bitmap_manager_;
   std::unique_ptr<viz::FrameSinkManagerImpl> frame_sink_manager_;
   viz::GpuServiceImpl* gpu_service_impl_ = nullptr;
-
-  DISALLOW_COPY_AND_ASSIGN(VizCompositorThreadRunnerWebView);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/gfx/vulkan_gl_interop.cc b/android_webview/browser/gfx/vulkan_gl_interop.cc
index c13e65e1..0abdaafa 100644
--- a/android_webview/browser/gfx/vulkan_gl_interop.cc
+++ b/android_webview/browser/gfx/vulkan_gl_interop.cc
@@ -62,6 +62,11 @@
     g_gl_context = this;
   }
 
+  GLNonOwnedCompatibilityContext(const GLNonOwnedCompatibilityContext&) =
+      delete;
+  GLNonOwnedCompatibilityContext& operator=(
+      const GLNonOwnedCompatibilityContext&) = delete;
+
   bool MakeCurrentImpl(gl::GLSurface* surface) override {
     // A GLNonOwnedCompatibilityContext may have set the GetRealCurrent()
     // pointer to itself, while re-using our EGL context. In these cases just
@@ -95,8 +100,6 @@
   }
 
   scoped_refptr<gl::GLSurface> surface_;
-
-  DISALLOW_COPY_AND_ASSIGN(GLNonOwnedCompatibilityContext);
 };
 
 VulkanGLInterop::InFlightInteropDraw::InFlightInteropDraw(
diff --git a/android_webview/browser/icon_helper.h b/android_webview/browser/icon_helper.h
index a8818623..830be08 100644
--- a/android_webview/browser/icon_helper.h
+++ b/android_webview/browser/icon_helper.h
@@ -39,6 +39,10 @@
   };
 
   explicit IconHelper(content::WebContents* web_contents);
+
+  IconHelper(const IconHelper&) = delete;
+  IconHelper& operator=(const IconHelper&) = delete;
+
   ~IconHelper() override;
 
   void SetListener(Listener* listener);
@@ -65,8 +69,6 @@
 
   using MissingFaviconURLHash = size_t;
   std::unordered_set<MissingFaviconURLHash> missing_favicon_urls_;
-
-  DISALLOW_COPY_AND_ASSIGN(IconHelper);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/js_java_interaction/js_reply_proxy.h b/android_webview/browser/js_java_interaction/js_reply_proxy.h
index fd453ba..8bd6814 100644
--- a/android_webview/browser/js_java_interaction/js_reply_proxy.h
+++ b/android_webview/browser/js_java_interaction/js_reply_proxy.h
@@ -17,6 +17,10 @@
 class JsReplyProxy {
  public:
   explicit JsReplyProxy(js_injection::WebMessageReplyProxy* reply_proxy);
+
+  JsReplyProxy(const JsReplyProxy&) = delete;
+  JsReplyProxy& operator=(const JsReplyProxy&) = delete;
+
   ~JsReplyProxy();
 
   base::android::ScopedJavaLocalRef<jobject> GetJavaPeer();
@@ -27,8 +31,6 @@
  private:
   js_injection::WebMessageReplyProxy* reply_proxy_;
   base::android::ScopedJavaGlobalRef<jobject> java_ref_;
-
-  DISALLOW_COPY_AND_ASSIGN(JsReplyProxy);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/lifecycle/aw_contents_lifecycle_notifier.h b/android_webview/browser/lifecycle/aw_contents_lifecycle_notifier.h
index a8456b6..ddc52e7b 100644
--- a/android_webview/browser/lifecycle/aw_contents_lifecycle_notifier.h
+++ b/android_webview/browser/lifecycle/aw_contents_lifecycle_notifier.h
@@ -38,6 +38,11 @@
   // lose foreground.
   explicit AwContentsLifecycleNotifier(
       OnLoseForegroundCallback on_lose_foreground_callback);
+
+  AwContentsLifecycleNotifier(const AwContentsLifecycleNotifier&) = delete;
+  AwContentsLifecycleNotifier& operator=(const AwContentsLifecycleNotifier&) =
+      delete;
+
   virtual ~AwContentsLifecycleNotifier();
 
   void OnWebViewCreated(const AwContents* aw_contents);
@@ -60,14 +65,14 @@
   struct AwContentsData {
     AwContentsData();
     AwContentsData(AwContentsData&& data);
+
+    AwContentsData(const AwContentsData&) = delete;
+
     ~AwContentsData();
 
     bool attached_to_window = false;
     bool window_visible = false;
     AwContentsState aw_content_state = AwContentsState::kDetached;
-
-   private:
-    DISALLOW_COPY(AwContentsData);
   };
 
   friend class TestAwContentsLifecycleNotifier;
@@ -104,8 +109,6 @@
       WebViewAppStateObserver::State::kDestroyed;
 
   SEQUENCE_CHECKER(sequence_checker_);
-
-  DISALLOW_COPY_AND_ASSIGN(AwContentsLifecycleNotifier);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/metrics/aw_metrics_service_client.h b/android_webview/browser/metrics/aw_metrics_service_client.h
index 1299cff..de8621a 100644
--- a/android_webview/browser/metrics/aw_metrics_service_client.h
+++ b/android_webview/browser/metrics/aw_metrics_service_client.h
@@ -150,6 +150,10 @@
   static void RegisterMetricsPrefs(PrefRegistrySimple* registry);
 
   AwMetricsServiceClient(std::unique_ptr<Delegate> delegate);
+
+  AwMetricsServiceClient(const AwMetricsServiceClient&) = delete;
+  AwMetricsServiceClient& operator=(const AwMetricsServiceClient&) = delete;
+
   ~AwMetricsServiceClient() override;
 
   // Initializes, but does not necessarily start, the MetricsService.
@@ -207,8 +211,6 @@
   absl::optional<AppPackageNameLoggingRule> cached_package_name_record_;
   AppPackageNameLoggingRuleStatus package_name_record_status_ =
       AppPackageNameLoggingRuleStatus::kNotLoadedNoCache;
-
-  DISALLOW_COPY_AND_ASSIGN(AwMetricsServiceClient);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/network_service/aw_network_change_notifier.h b/android_webview/browser/network_service/aw_network_change_notifier.h
index aabcf79..7119908a 100644
--- a/android_webview/browser/network_service/aw_network_change_notifier.h
+++ b/android_webview/browser/network_service/aw_network_change_notifier.h
@@ -24,6 +24,9 @@
     : public net::NetworkChangeNotifier,
       public net::NetworkChangeNotifierDelegateAndroid::Observer {
  public:
+  AwNetworkChangeNotifier(const AwNetworkChangeNotifier&) = delete;
+  AwNetworkChangeNotifier& operator=(const AwNetworkChangeNotifier&) = delete;
+
   ~AwNetworkChangeNotifier() override;
 
   // NetworkChangeNotifier:
@@ -57,8 +60,6 @@
   static NetworkChangeCalculatorParams DefaultNetworkChangeCalculatorParams();
 
   net::NetworkChangeNotifierDelegateAndroid* const delegate_;
-
-  DISALLOW_COPY_AND_ASSIGN(AwNetworkChangeNotifier);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/network_service/aw_network_change_notifier_factory.h b/android_webview/browser/network_service/aw_network_change_notifier_factory.h
index 2857fee..8a2b40d 100644
--- a/android_webview/browser/network_service/aw_network_change_notifier_factory.h
+++ b/android_webview/browser/network_service/aw_network_change_notifier_factory.h
@@ -24,6 +24,11 @@
   // Must be called on the JNI thread.
   AwNetworkChangeNotifierFactory();
 
+  AwNetworkChangeNotifierFactory(const AwNetworkChangeNotifierFactory&) =
+      delete;
+  AwNetworkChangeNotifierFactory& operator=(
+      const AwNetworkChangeNotifierFactory&) = delete;
+
   // Must be called on the JNI thread.
   ~AwNetworkChangeNotifierFactory() override;
 
@@ -33,8 +38,6 @@
  private:
   // Delegate passed to the instances created by this class.
   net::NetworkChangeNotifierDelegateAndroid delegate_;
-
-  DISALLOW_COPY_AND_ASSIGN(AwNetworkChangeNotifierFactory);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/network_service/aw_proxying_restricted_cookie_manager.h b/android_webview/browser/network_service/aw_proxying_restricted_cookie_manager.h
index 22a9f08..9d55d68 100644
--- a/android_webview/browser/network_service/aw_proxying_restricted_cookie_manager.h
+++ b/android_webview/browser/network_service/aw_proxying_restricted_cookie_manager.h
@@ -35,6 +35,11 @@
       int frame_id,
       mojo::PendingReceiver<network::mojom::RestrictedCookieManager> receiver);
 
+  AwProxyingRestrictedCookieManager(const AwProxyingRestrictedCookieManager&) =
+      delete;
+  AwProxyingRestrictedCookieManager& operator=(
+      const AwProxyingRestrictedCookieManager&) = delete;
+
   ~AwProxyingRestrictedCookieManager() override;
 
   // network::mojom::RestrictedCookieManager interface:
@@ -98,8 +103,6 @@
   int frame_id_;
 
   base::WeakPtrFactory<AwProxyingRestrictedCookieManager> weak_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(AwProxyingRestrictedCookieManager);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/network_service/aw_proxying_url_loader_factory.cc b/android_webview/browser/network_service/aw_proxying_url_loader_factory.cc
index 320c17c..56f239f 100644
--- a/android_webview/browser/network_service/aw_proxying_url_loader_factory.cc
+++ b/android_webview/browser/network_service/aw_proxying_url_loader_factory.cc
@@ -66,6 +66,10 @@
       bool intercept_only,
       absl::optional<AwProxyingURLLoaderFactory::SecurityOptions>
           security_options);
+
+  InterceptedRequest(const InterceptedRequest&) = delete;
+  InterceptedRequest& operator=(const InterceptedRequest&) = delete;
+
   ~InterceptedRequest() override;
 
   void Restart();
@@ -162,8 +166,6 @@
   mojo::Remote<network::mojom::URLLoaderFactory> target_factory_;
 
   base::WeakPtrFactory<InterceptedRequest> weak_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(InterceptedRequest);
 };
 
 // A ResponseDelegate for responses returned by shouldInterceptRequest.
diff --git a/android_webview/browser/network_service/aw_proxying_url_loader_factory.h b/android_webview/browser/network_service/aw_proxying_url_loader_factory.h
index 093d328..61639f22 100644
--- a/android_webview/browser/network_service/aw_proxying_url_loader_factory.h
+++ b/android_webview/browser/network_service/aw_proxying_url_loader_factory.h
@@ -71,6 +71,10 @@
       bool intercept_only,
       absl::optional<SecurityOptions> security_options);
 
+  AwProxyingURLLoaderFactory(const AwProxyingURLLoaderFactory&) = delete;
+  AwProxyingURLLoaderFactory& operator=(const AwProxyingURLLoaderFactory&) =
+      delete;
+
   ~AwProxyingURLLoaderFactory() override;
 
   // static
@@ -109,8 +113,6 @@
   absl::optional<SecurityOptions> security_options_;
 
   base::WeakPtrFactory<AwProxyingURLLoaderFactory> weak_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(AwProxyingURLLoaderFactory);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/network_service/aw_url_loader_throttle.h b/android_webview/browser/network_service/aw_url_loader_throttle.h
index 5f9a3e4..e11a910 100644
--- a/android_webview/browser/network_service/aw_url_loader_throttle.h
+++ b/android_webview/browser/network_service/aw_url_loader_throttle.h
@@ -24,6 +24,10 @@
 class AwURLLoaderThrottle : public blink::URLLoaderThrottle {
  public:
   explicit AwURLLoaderThrottle(AwResourceContext* aw_resource_context);
+
+  AwURLLoaderThrottle(const AwURLLoaderThrottle&) = delete;
+  AwURLLoaderThrottle& operator=(const AwURLLoaderThrottle&) = delete;
+
   ~AwURLLoaderThrottle() override;
 
   // blink::URLLoaderThrottle implementation:
@@ -44,8 +48,6 @@
   AwResourceContext* aw_resource_context_;
   std::vector<std::string> added_headers_;
   url::Origin original_origin_;
-
-  DISALLOW_COPY_AND_ASSIGN(AwURLLoaderThrottle);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/network_service/aw_web_resource_intercept_response.h b/android_webview/browser/network_service/aw_web_resource_intercept_response.h
index 90659da..ba1e388 100644
--- a/android_webview/browser/network_service/aw_web_resource_intercept_response.h
+++ b/android_webview/browser/network_service/aw_web_resource_intercept_response.h
@@ -27,6 +27,12 @@
   // org.chromium.android_webview.AwWebResourceInterceptResponse class.
   explicit AwWebResourceInterceptResponse(
       const base::android::JavaRef<jobject>& obj);
+
+  AwWebResourceInterceptResponse(const AwWebResourceInterceptResponse&) =
+      delete;
+  AwWebResourceInterceptResponse& operator=(
+      const AwWebResourceInterceptResponse&) = delete;
+
   ~AwWebResourceInterceptResponse();
 
   // True if the call to shouldInterceptRequest raised an exception.
@@ -43,8 +49,6 @@
 
  private:
   base::android::ScopedJavaGlobalRef<jobject> java_object_;
-
-  DISALLOW_COPY_AND_ASSIGN(AwWebResourceInterceptResponse);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/page_load_metrics/aw_page_load_metrics_provider.h b/android_webview/browser/page_load_metrics/aw_page_load_metrics_provider.h
index 2c01605..7328d22 100644
--- a/android_webview/browser/page_load_metrics/aw_page_load_metrics_provider.h
+++ b/android_webview/browser/page_load_metrics/aw_page_load_metrics_provider.h
@@ -14,13 +14,15 @@
 class AwPageLoadMetricsProvider : public metrics::MetricsProvider {
  public:
   AwPageLoadMetricsProvider();
+
+  AwPageLoadMetricsProvider(const AwPageLoadMetricsProvider&) = delete;
+  AwPageLoadMetricsProvider& operator=(const AwPageLoadMetricsProvider&) =
+      delete;
+
   ~AwPageLoadMetricsProvider() override;
 
   // metrics:MetricsProvider:
   void OnAppEnterBackground() override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(AwPageLoadMetricsProvider);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/page_load_metrics/page_load_metrics_initialize.cc b/android_webview/browser/page_load_metrics/page_load_metrics_initialize.cc
index 16fc586..2a6a6f6 100644
--- a/android_webview/browser/page_load_metrics/page_load_metrics_initialize.cc
+++ b/android_webview/browser/page_load_metrics/page_load_metrics_initialize.cc
@@ -26,6 +26,10 @@
     : public page_load_metrics::PageLoadMetricsEmbedderBase {
  public:
   explicit PageLoadMetricsEmbedder(content::WebContents* web_contents);
+
+  PageLoadMetricsEmbedder(const PageLoadMetricsEmbedder&) = delete;
+  PageLoadMetricsEmbedder& operator=(const PageLoadMetricsEmbedder&) = delete;
+
   ~PageLoadMetricsEmbedder() override;
 
   // page_load_metrics::PageLoadMetricsEmbedderBase:
@@ -40,9 +44,6 @@
   // page_load_metrics::PageLoadMetricsEmbedderBase:
   void RegisterEmbedderObservers(
       page_load_metrics::PageLoadTracker* tracker) override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(PageLoadMetricsEmbedder);
 };
 
 PageLoadMetricsEmbedder::PageLoadMetricsEmbedder(
diff --git a/android_webview/browser/permission/aw_permission_request.h b/android_webview/browser/permission/aw_permission_request.h
index 2a25fcb..e616a6d 100644
--- a/android_webview/browser/permission/aw_permission_request.h
+++ b/android_webview/browser/permission/aw_permission_request.h
@@ -39,6 +39,9 @@
       std::unique_ptr<AwPermissionRequestDelegate> delegate,
       base::WeakPtr<AwPermissionRequest>* weak_ptr);
 
+  AwPermissionRequest(const AwPermissionRequest&) = delete;
+  AwPermissionRequest& operator=(const AwPermissionRequest&) = delete;
+
   // Return the Java peer. Must be null-checked.
   base::android::ScopedJavaLocalRef<jobject> GetJavaObject();
 
@@ -76,8 +79,6 @@
 
   bool processed_;
   base::WeakPtrFactory<AwPermissionRequest> weak_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(AwPermissionRequest);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/permission/aw_permission_request_delegate.h b/android_webview/browser/permission/aw_permission_request_delegate.h
index ea5c8d49..ab024c52 100644
--- a/android_webview/browser/permission/aw_permission_request_delegate.h
+++ b/android_webview/browser/permission/aw_permission_request_delegate.h
@@ -16,6 +16,11 @@
 class AwPermissionRequestDelegate {
  public:
   AwPermissionRequestDelegate();
+
+  AwPermissionRequestDelegate(const AwPermissionRequestDelegate&) = delete;
+  AwPermissionRequestDelegate& operator=(const AwPermissionRequestDelegate&) =
+      delete;
+
   virtual ~AwPermissionRequestDelegate();
 
   // Get the origin which initiated the permission request.
@@ -26,8 +31,6 @@
 
   // Notify the permission request is allowed or not.
   virtual void NotifyRequestResult(bool allowed) = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(AwPermissionRequestDelegate);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/permission/media_access_permission_request.h b/android_webview/browser/permission/media_access_permission_request.h
index cf86450..358fcb9f 100644
--- a/android_webview/browser/permission/media_access_permission_request.h
+++ b/android_webview/browser/permission/media_access_permission_request.h
@@ -21,6 +21,11 @@
  public:
   MediaAccessPermissionRequest(const content::MediaStreamRequest& request,
                                content::MediaResponseCallback callback);
+
+  MediaAccessPermissionRequest(const MediaAccessPermissionRequest&) = delete;
+  MediaAccessPermissionRequest& operator=(const MediaAccessPermissionRequest&) =
+      delete;
+
   ~MediaAccessPermissionRequest() override;
 
   // AwPermissionRequestDelegate implementation.
@@ -37,8 +42,6 @@
   // For test only.
   blink::MediaStreamDevices audio_test_devices_;
   blink::MediaStreamDevices video_test_devices_;
-
-  DISALLOW_COPY_AND_ASSIGN(MediaAccessPermissionRequest);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/permission/permission_request_handler.h b/android_webview/browser/permission/permission_request_handler.h
index c7037980..8f6ee5a 100644
--- a/android_webview/browser/permission/permission_request_handler.h
+++ b/android_webview/browser/permission/permission_request_handler.h
@@ -30,6 +30,10 @@
  public:
   PermissionRequestHandler(PermissionRequestHandlerClient* client,
                            content::WebContents* aw_contents);
+
+  PermissionRequestHandler(const PermissionRequestHandler&) = delete;
+  PermissionRequestHandler& operator=(const PermissionRequestHandler&) = delete;
+
   ~PermissionRequestHandler() override;
 
   // Send the given |request| to PermissionRequestHandlerClient.
@@ -75,8 +79,6 @@
   // The unique id of the active NavigationEntry of the WebContents that we were
   // opened for. Used to help expire on requests.
   int contents_unique_id_;
-
-  DISALLOW_COPY_AND_ASSIGN(PermissionRequestHandler);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/permission/simple_permission_request.h b/android_webview/browser/permission/simple_permission_request.h
index f714083..41dfc138 100644
--- a/android_webview/browser/permission/simple_permission_request.h
+++ b/android_webview/browser/permission/simple_permission_request.h
@@ -21,6 +21,10 @@
   SimplePermissionRequest(const GURL& origin,
                           int64_t resources,
                           PermissionCallback callback);
+
+  SimplePermissionRequest(const SimplePermissionRequest&) = delete;
+  SimplePermissionRequest& operator=(const SimplePermissionRequest&) = delete;
+
   ~SimplePermissionRequest() override;
 
   // AwPermissionRequestDelegate implementation.
@@ -32,8 +36,6 @@
   const GURL origin_;
   int64_t resources_;
   PermissionCallback callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(SimplePermissionRequest);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/popup_touch_handle_drawable.h b/android_webview/browser/popup_touch_handle_drawable.h
index 15a363a..c85d2cf9 100644
--- a/android_webview/browser/popup_touch_handle_drawable.h
+++ b/android_webview/browser/popup_touch_handle_drawable.h
@@ -18,6 +18,10 @@
   PopupTouchHandleDrawable(JNIEnv* env,
                            jobject obj,
                            float horizontal_padding_ratio);
+
+  PopupTouchHandleDrawable(const PopupTouchHandleDrawable&) = delete;
+  PopupTouchHandleDrawable& operator=(const PopupTouchHandleDrawable&) = delete;
+
   ~PopupTouchHandleDrawable() override;
 
   // ui::TouchHandleDrawable implementation.
@@ -34,8 +38,6 @@
   JavaObjectWeakGlobalRef java_ref_;
 
   const float drawable_horizontal_padding_ratio_;
-
-  DISALLOW_COPY_AND_ASSIGN(PopupTouchHandleDrawable);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/renderer_host/aw_render_view_host_ext.h b/android_webview/browser/renderer_host/aw_render_view_host_ext.h
index 8735504..9c6a2be 100644
--- a/android_webview/browser/renderer_host/aw_render_view_host_ext.h
+++ b/android_webview/browser/renderer_host/aw_render_view_host_ext.h
@@ -48,6 +48,10 @@
   // as it internally handles RenderViewHost instances changing underneath us.
   AwRenderViewHostExt(
       AwRenderViewHostExtClient* client, content::WebContents* contents);
+
+  AwRenderViewHostExt(const AwRenderViewHostExt&) = delete;
+  AwRenderViewHostExt& operator=(const AwRenderViewHostExt&) = delete;
+
   ~AwRenderViewHostExt() override;
 
   // |result| will be invoked with the outcome of the request.
@@ -122,8 +126,6 @@
   mojo::AssociatedRemote<mojom::LocalMainFrame> local_main_frame_remote_;
 
   SEQUENCE_CHECKER(sequence_checker_);
-
-  DISALLOW_COPY_AND_ASSIGN(AwRenderViewHostExt);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/safe_browsing/aw_safe_browsing_allowlist_manager.h b/android_webview/browser/safe_browsing/aw_safe_browsing_allowlist_manager.h
index 33ab054..6e06980a 100644
--- a/android_webview/browser/safe_browsing/aw_safe_browsing_allowlist_manager.h
+++ b/android_webview/browser/safe_browsing/aw_safe_browsing_allowlist_manager.h
@@ -59,6 +59,12 @@
   AwSafeBrowsingAllowlistManager(
       const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
       const scoped_refptr<base::SequencedTaskRunner>& io_task_runner);
+
+  AwSafeBrowsingAllowlistManager(const AwSafeBrowsingAllowlistManager&) =
+      delete;
+  AwSafeBrowsingAllowlistManager& operator=(
+      const AwSafeBrowsingAllowlistManager&) = delete;
+
   virtual ~AwSafeBrowsingAllowlistManager();
 
   // Returns true if |url| is allowed by the current allowlist. Must be
@@ -81,8 +87,6 @@
   scoped_refptr<base::SequencedTaskRunner> ui_task_runner_;
 
   std::unique_ptr<TrieNode> allowlist_;
-
-  DISALLOW_COPY_AND_ASSIGN(AwSafeBrowsingAllowlistManager);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/safe_browsing/aw_safe_browsing_subresource_helper.h b/android_webview/browser/safe_browsing/aw_safe_browsing_subresource_helper.h
index c1a33005..edb51960 100644
--- a/android_webview/browser/safe_browsing/aw_safe_browsing_subresource_helper.h
+++ b/android_webview/browser/safe_browsing/aw_safe_browsing_subresource_helper.h
@@ -22,6 +22,11 @@
     : public content::WebContentsObserver,
       public content::WebContentsUserData<AwSafeBrowsingSubresourceHelper> {
  public:
+  AwSafeBrowsingSubresourceHelper(const AwSafeBrowsingSubresourceHelper&) =
+      delete;
+  AwSafeBrowsingSubresourceHelper& operator=(
+      const AwSafeBrowsingSubresourceHelper&) = delete;
+
   ~AwSafeBrowsingSubresourceHelper() override;
 
   // WebContentsObserver::
@@ -33,7 +38,6 @@
   friend class content::WebContentsUserData<AwSafeBrowsingSubresourceHelper>;
 
   WEB_CONTENTS_USER_DATA_KEY_DECL();
-  DISALLOW_COPY_AND_ASSIGN(AwSafeBrowsingSubresourceHelper);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/safe_browsing/aw_safe_browsing_ui_manager.h b/android_webview/browser/safe_browsing/aw_safe_browsing_ui_manager.h
index d602619..a7ec452f 100644
--- a/android_webview/browser/safe_browsing/aw_safe_browsing_ui_manager.h
+++ b/android_webview/browser/safe_browsing/aw_safe_browsing_ui_manager.h
@@ -46,6 +46,9 @@
   // Construction needs to happen on the UI thread.
   AwSafeBrowsingUIManager();
 
+  AwSafeBrowsingUIManager(const AwSafeBrowsingUIManager&) = delete;
+  AwSafeBrowsingUIManager& operator=(const AwSafeBrowsingUIManager&) = delete;
+
   // Gets the correct ErrorUiType for the web contents
   int GetErrorUiType(content::WebContents* web_contents) const;
 
@@ -87,8 +90,6 @@
   mojo::Remote<network::mojom::URLLoaderFactory> url_loader_factory_on_io_;
   scoped_refptr<network::WeakWrapperSharedURLLoaderFactory>
       shared_url_loader_factory_on_io_;
-
-  DISALLOW_COPY_AND_ASSIGN(AwSafeBrowsingUIManager);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/safe_browsing/aw_url_checker_delegate_impl.h b/android_webview/browser/safe_browsing/aw_url_checker_delegate_impl.h
index 93021ad..cfb3363 100644
--- a/android_webview/browser/safe_browsing/aw_url_checker_delegate_impl.h
+++ b/android_webview/browser/safe_browsing/aw_url_checker_delegate_impl.h
@@ -33,6 +33,9 @@
       scoped_refptr<AwSafeBrowsingUIManager> ui_manager,
       AwSafeBrowsingAllowlistManager* allowlist_manager);
 
+  AwUrlCheckerDelegateImpl(const AwUrlCheckerDelegateImpl&) = delete;
+  AwUrlCheckerDelegateImpl& operator=(const AwUrlCheckerDelegateImpl&) = delete;
+
  private:
   ~AwUrlCheckerDelegateImpl() override;
 
@@ -87,8 +90,6 @@
   scoped_refptr<AwSafeBrowsingUIManager> ui_manager_;
   safe_browsing::SBThreatTypeSet threat_types_;
   AwSafeBrowsingAllowlistManager* allowlist_manager_;
-
-  DISALLOW_COPY_AND_ASSIGN(AwUrlCheckerDelegateImpl);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/scoped_add_feature_flags.h b/android_webview/browser/scoped_add_feature_flags.h
index 9f95828..1e56e35e 100644
--- a/android_webview/browser/scoped_add_feature_flags.h
+++ b/android_webview/browser/scoped_add_feature_flags.h
@@ -19,6 +19,10 @@
 class ScopedAddFeatureFlags {
  public:
   explicit ScopedAddFeatureFlags(base::CommandLine* cl);
+
+  ScopedAddFeatureFlags(const ScopedAddFeatureFlags&) = delete;
+  ScopedAddFeatureFlags& operator=(const ScopedAddFeatureFlags&) = delete;
+
   ~ScopedAddFeatureFlags();
 
   // Any existing (user set) enable/disable takes precedence.
@@ -33,8 +37,6 @@
   base::CommandLine* const cl_;
   std::vector<std::string> enabled_features_;
   std::vector<std::string> disabled_features_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedAddFeatureFlags);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/state_serializer_unittest.cc b/android_webview/browser/state_serializer_unittest.cc
index ab1fc1c..48a2482a 100644
--- a/android_webview/browser/state_serializer_unittest.cc
+++ b/android_webview/browser/state_serializer_unittest.cc
@@ -68,6 +68,11 @@
     content::SetBrowserClientForTesting(&browser_client_);
   }
 
+  AndroidWebViewStateSerializerTest(const AndroidWebViewStateSerializerTest&) =
+      delete;
+  AndroidWebViewStateSerializerTest& operator=(
+      const AndroidWebViewStateSerializerTest&) = delete;
+
   ~AndroidWebViewStateSerializerTest() override {
     content::SetBrowserClientForTesting(nullptr);
     content::SetContentClient(nullptr);
@@ -76,8 +81,6 @@
  private:
   content::ContentClient content_client_;
   content::ContentBrowserClient browser_client_;
-
-  DISALLOW_COPY_AND_ASSIGN(AndroidWebViewStateSerializerTest);
 };
 
 }  // namespace
diff --git a/android_webview/browser/tracing/aw_tracing_controller.cc b/android_webview/browser/tracing/aw_tracing_controller.cc
index 78175f9..f825afc7 100644
--- a/android_webview/browser/tracing/aw_tracing_controller.cc
+++ b/android_webview/browser/tracing/aw_tracing_controller.cc
@@ -55,13 +55,14 @@
       : received_chunk_callback_(std::move(received_chunk_callback)),
         completed_callback_(std::move(completed_callback)) {}
 
+  AwTraceDataEndpoint(const AwTraceDataEndpoint&) = delete;
+  AwTraceDataEndpoint& operator=(const AwTraceDataEndpoint&) = delete;
+
  private:
   ~AwTraceDataEndpoint() override {}
 
   ReceivedChunkCallback received_chunk_callback_;
   base::OnceClosure completed_callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(AwTraceDataEndpoint);
 };
 
 }  // namespace
diff --git a/android_webview/browser/tracing/aw_tracing_controller.h b/android_webview/browser/tracing/aw_tracing_controller.h
index 053a5f4..3c2dc77 100644
--- a/android_webview/browser/tracing/aw_tracing_controller.h
+++ b/android_webview/browser/tracing/aw_tracing_controller.h
@@ -15,6 +15,9 @@
  public:
   AwTracingController(JNIEnv* env, jobject obj);
 
+  AwTracingController(const AwTracingController&) = delete;
+  AwTracingController& operator=(const AwTracingController&) = delete;
+
   bool Start(JNIEnv* env,
              const base::android::JavaParamRef<jobject>& obj,
              const base::android::JavaParamRef<jstring>& categories,
@@ -31,8 +34,6 @@
 
   JavaObjectWeakGlobalRef weak_java_object_;
   base::WeakPtrFactory<AwTracingController> weak_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(AwTracingController);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/variations/aw_variations_service_client.h b/android_webview/browser/variations/aw_variations_service_client.h
index 8dc03f2..86a7685 100644
--- a/android_webview/browser/variations/aw_variations_service_client.h
+++ b/android_webview/browser/variations/aw_variations_service_client.h
@@ -22,6 +22,11 @@
 class AwVariationsServiceClient : public variations::VariationsServiceClient {
  public:
   AwVariationsServiceClient();
+
+  AwVariationsServiceClient(const AwVariationsServiceClient&) = delete;
+  AwVariationsServiceClient& operator=(const AwVariationsServiceClient&) =
+      delete;
+
   ~AwVariationsServiceClient() override;
 
  private:
@@ -31,8 +36,6 @@
   version_info::Channel GetChannel() override;
   bool OverridesRestrictParameter(std::string* parameter) override;
   bool IsEnterprise() override;
-
-  DISALLOW_COPY_AND_ASSIGN(AwVariationsServiceClient);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/common/aw_media_drm_bridge_client.h b/android_webview/common/aw_media_drm_bridge_client.h
index a68e845..8c728b39 100644
--- a/android_webview/common/aw_media_drm_bridge_client.h
+++ b/android_webview/common/aw_media_drm_bridge_client.h
@@ -17,6 +17,10 @@
   // pairs, in the format "key system name,UUID as string".
   explicit AwMediaDrmBridgeClient(
       const std::vector<std::string>& key_system_uuid_mappings);
+
+  AwMediaDrmBridgeClient(const AwMediaDrmBridgeClient&) = delete;
+  AwMediaDrmBridgeClient& operator=(const AwMediaDrmBridgeClient&) = delete;
+
   ~AwMediaDrmBridgeClient() override;
 
  private:
@@ -27,8 +31,6 @@
 
   std::vector<std::string> key_system_uuid_mappings_;
   cdm::WidevineDrmDelegateAndroid widevine_delegate_;
-
-  DISALLOW_COPY_AND_ASSIGN(AwMediaDrmBridgeClient);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/common/crash_reporter/aw_crash_reporter_client.cc b/android_webview/common/crash_reporter/aw_crash_reporter_client.cc
index 55b2096..dee4c64 100644
--- a/android_webview/common/crash_reporter/aw_crash_reporter_client.cc
+++ b/android_webview/common/crash_reporter/aw_crash_reporter_client.cc
@@ -39,6 +39,9 @@
  public:
   AwCrashReporterClient() = default;
 
+  AwCrashReporterClient(const AwCrashReporterClient&) = delete;
+  AwCrashReporterClient& operator=(const AwCrashReporterClient&) = delete;
+
   // crash_reporter::CrashReporterClient implementation.
   bool IsRunningUnattended() override { return false; }
   bool GetCollectStatsConsent() override {
@@ -104,9 +107,6 @@
     static base::NoDestructor<AwCrashReporterClient> crash_reporter_client;
     return crash_reporter_client.get();
   }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(AwCrashReporterClient);
 };
 
 #if defined(ARCH_CPU_X86_FAMILY)
diff --git a/android_webview/common/devtools_instrumentation.h b/android_webview/common/devtools_instrumentation.h
index abb95dc..38f8ae5 100644
--- a/android_webview/common/devtools_instrumentation.h
+++ b/android_webview/common/devtools_instrumentation.h
@@ -27,12 +27,14 @@
     TRACE_EVENT_BEGIN1(internal::Category(), internal::kEmbedderCallback,
                        internal::kCallbackNameArgument, callback_name);
   }
+
+  ScopedEmbedderCallbackTask(const ScopedEmbedderCallbackTask&) = delete;
+  ScopedEmbedderCallbackTask& operator=(const ScopedEmbedderCallbackTask&) =
+      delete;
+
   ~ScopedEmbedderCallbackTask() {
     TRACE_EVENT_END0(internal::Category(), internal::kEmbedderCallback);
   }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ScopedEmbedderCallbackTask);
 };
 
 }  // namespace devtools_instrumentation
diff --git a/android_webview/gpu/aw_content_gpu_client.h b/android_webview/gpu/aw_content_gpu_client.h
index 381fed2..a893fa46 100644
--- a/android_webview/gpu/aw_content_gpu_client.h
+++ b/android_webview/gpu/aw_content_gpu_client.h
@@ -25,6 +25,10 @@
       const GetSharedImageManagerCallback& shared_image_manager_callback,
       const GetVizCompositorThreadRunnerCallback&
           viz_compositor_thread_runner_callback);
+
+  AwContentGpuClient(const AwContentGpuClient&) = delete;
+  AwContentGpuClient& operator=(const AwContentGpuClient&) = delete;
+
   ~AwContentGpuClient() override;
 
   // content::ContentGpuClient implementation.
@@ -36,7 +40,6 @@
   GetSyncPointManagerCallback sync_point_manager_callback_;
   GetSharedImageManagerCallback shared_image_manager_callback_;
   GetVizCompositorThreadRunnerCallback viz_compositor_thread_runner_callback_;
-  DISALLOW_COPY_AND_ASSIGN(AwContentGpuClient);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/lib/aw_main_delegate.h b/android_webview/lib/aw_main_delegate.h
index a8a06f0..cdc9c956 100644
--- a/android_webview/lib/aw_main_delegate.h
+++ b/android_webview/lib/aw_main_delegate.h
@@ -34,6 +34,10 @@
 class AwMainDelegate : public content::ContentMainDelegate {
  public:
   AwMainDelegate();
+
+  AwMainDelegate(const AwMainDelegate&) = delete;
+  AwMainDelegate& operator=(const AwMainDelegate&) = delete;
+
   ~AwMainDelegate() override;
 
  private:
@@ -63,8 +67,6 @@
   std::unique_ptr<AwContentRendererClient> content_renderer_client_;
   std::unique_ptr<safe_browsing::SafeBrowsingApiHandler>
       safe_browsing_api_handler_;
-
-  DISALLOW_COPY_AND_ASSIGN(AwMainDelegate);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/renderer/aw_content_renderer_client.h b/android_webview/renderer/aw_content_renderer_client.h
index 18b3208..f9a78a55 100644
--- a/android_webview/renderer/aw_content_renderer_client.h
+++ b/android_webview/renderer/aw_content_renderer_client.h
@@ -32,6 +32,10 @@
                                 public service_manager::LocalInterfaceProvider {
  public:
   AwContentRendererClient();
+
+  AwContentRendererClient(const AwContentRendererClient&) = delete;
+  AwContentRendererClient& operator=(const AwContentRendererClient&) = delete;
+
   ~AwContentRendererClient() override;
 
   // ContentRendererClient implementation.
@@ -84,8 +88,6 @@
 #if BUILDFLAG(ENABLE_SPELLCHECK)
   std::unique_ptr<SpellCheck> spellcheck_;
 #endif
-
-  DISALLOW_COPY_AND_ASSIGN(AwContentRendererClient);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/renderer/aw_content_settings_client.h b/android_webview/renderer/aw_content_settings_client.h
index 6aaf789..b30b3eb 100644
--- a/android_webview/renderer/aw_content_settings_client.h
+++ b/android_webview/renderer/aw_content_settings_client.h
@@ -17,6 +17,9 @@
  public:
   explicit AwContentSettingsClient(content::RenderFrame* render_view);
 
+  AwContentSettingsClient(const AwContentSettingsClient&) = delete;
+  AwContentSettingsClient& operator=(const AwContentSettingsClient&) = delete;
+
  private:
   ~AwContentSettingsClient() override;
 
@@ -32,8 +35,6 @@
   bool ShouldAutoupgradeMixedContent() override;
 
   bool ShouldAllowlistForContentSettings() const;
-
-  DISALLOW_COPY_AND_ASSIGN(AwContentSettingsClient);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/renderer/aw_print_render_frame_helper_delegate.h b/android_webview/renderer/aw_print_render_frame_helper_delegate.h
index e5541b6..2f6fd0b 100644
--- a/android_webview/renderer/aw_print_render_frame_helper_delegate.h
+++ b/android_webview/renderer/aw_print_render_frame_helper_delegate.h
@@ -14,6 +14,12 @@
     : public printing::PrintRenderFrameHelper::Delegate {
  public:
   AwPrintRenderFrameHelperDelegate();
+
+  AwPrintRenderFrameHelperDelegate(const AwPrintRenderFrameHelperDelegate&) =
+      delete;
+  AwPrintRenderFrameHelperDelegate& operator=(
+      const AwPrintRenderFrameHelperDelegate&) = delete;
+
   ~AwPrintRenderFrameHelperDelegate() override;
 
  private:
@@ -22,8 +28,6 @@
   bool IsPrintPreviewEnabled() override;
   bool IsScriptedPrintEnabled() override;
   bool OverridePrint(blink::WebLocalFrame* frame) override;
-
-  DISALLOW_COPY_AND_ASSIGN(AwPrintRenderFrameHelperDelegate);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/renderer/aw_render_frame_ext.h b/android_webview/renderer/aw_render_frame_ext.h
index e8e6752..340ed35 100644
--- a/android_webview/renderer/aw_render_frame_ext.h
+++ b/android_webview/renderer/aw_render_frame_ext.h
@@ -33,6 +33,9 @@
  public:
   explicit AwRenderFrameExt(content::RenderFrame* render_frame);
 
+  AwRenderFrameExt(const AwRenderFrameExt&) = delete;
+  AwRenderFrameExt& operator=(const AwRenderFrameExt&) = delete;
+
   static AwRenderFrameExt* FromRenderFrame(content::RenderFrame* render_frame);
 
  private:
@@ -73,8 +76,6 @@
       this};
 
   mojo::AssociatedRemote<mojom::FrameHost> frame_host_remote_;
-
-  DISALLOW_COPY_AND_ASSIGN(AwRenderFrameExt);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/renderer/aw_render_view_ext.h b/android_webview/renderer/aw_render_view_ext.h
index a9092db5..e8371ab 100644
--- a/android_webview/renderer/aw_render_view_ext.h
+++ b/android_webview/renderer/aw_render_view_ext.h
@@ -20,6 +20,9 @@
 // WebKit directly to implement (and that aren't needed in the chrome app).
 class AwRenderViewExt : public blink::WebViewObserver {
  public:
+  AwRenderViewExt(const AwRenderViewExt&) = delete;
+  AwRenderViewExt& operator=(const AwRenderViewExt&) = delete;
+
   static void WebViewCreated(blink::WebView* web_view);
 
  private:
@@ -38,8 +41,6 @@
   // Whether the contents size may have changed and |UpdateContentsSize| needs
   // to be called.
   bool needs_contents_size_update_ = true;
-
-  DISALLOW_COPY_AND_ASSIGN(AwRenderViewExt);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/renderer/aw_url_loader_throttle_provider.h b/android_webview/renderer/aw_url_loader_throttle_provider.h
index 3d2fc81..0069d30 100644
--- a/android_webview/renderer/aw_url_loader_throttle_provider.h
+++ b/android_webview/renderer/aw_url_loader_throttle_provider.h
@@ -22,6 +22,9 @@
       blink::ThreadSafeBrowserInterfaceBrokerProxy* broker,
       blink::URLLoaderThrottleProviderType type);
 
+  AwURLLoaderThrottleProvider& operator=(const AwURLLoaderThrottleProvider&) =
+      delete;
+
   ~AwURLLoaderThrottleProvider() override;
 
   // blink::URLLoaderThrottleProvider implementation.
@@ -42,8 +45,6 @@
   mojo::Remote<safe_browsing::mojom::SafeBrowsing> safe_browsing_;
 
   THREAD_CHECKER(thread_checker_);
-
-  DISALLOW_ASSIGN(AwURLLoaderThrottleProvider);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/renderer/aw_websocket_handshake_throttle_provider.h b/android_webview/renderer/aw_websocket_handshake_throttle_provider.h
index c21e1e8..942af29c 100644
--- a/android_webview/renderer/aw_websocket_handshake_throttle_provider.h
+++ b/android_webview/renderer/aw_websocket_handshake_throttle_provider.h
@@ -24,6 +24,10 @@
  public:
   explicit AwWebSocketHandshakeThrottleProvider(
       blink::ThreadSafeBrowserInterfaceBrokerProxy* broker);
+
+  AwWebSocketHandshakeThrottleProvider& operator=(
+      const AwWebSocketHandshakeThrottleProvider&) = delete;
+
   ~AwWebSocketHandshakeThrottleProvider() override;
 
   // Implements blink::WebSocketHandshakeThrottleProvider.
@@ -43,8 +47,6 @@
   mojo::Remote<safe_browsing::mojom::SafeBrowsing> safe_browsing_;
 
   THREAD_CHECKER(thread_checker_);
-
-  DISALLOW_ASSIGN(AwWebSocketHandshakeThrottleProvider);
 };
 
 }  // namespace android_webview
diff --git a/apps/app_lifetime_monitor.cc b/apps/app_lifetime_monitor.cc
index 87b9c98e..467ff6a 100644
--- a/apps/app_lifetime_monitor.cc
+++ b/apps/app_lifetime_monitor.cc
@@ -5,11 +5,8 @@
 #include "apps/app_lifetime_monitor.h"
 
 #include "content/public/browser/browser_context.h"
-#include "content/public/browser/notification_details.h"
-#include "content/public/browser/notification_service.h"
 #include "extensions/browser/app_window/app_window.h"
 #include "extensions/browser/extension_host.h"
-#include "extensions/browser/notification_types.h"
 #include "extensions/common/extension.h"
 
 namespace apps {
@@ -21,10 +18,6 @@
 
 AppLifetimeMonitor::AppLifetimeMonitor(content::BrowserContext* context)
     : context_(context) {
-  registrar_.Add(this,
-                 extensions::NOTIFICATION_EXTENSION_HOST_DID_STOP_FIRST_LOAD,
-                 content::NotificationService::AllSources());
-
   extension_host_registry_observation_.Observe(
       extensions::ExtensionHostRegistry::Get(context_));
 
@@ -45,11 +38,9 @@
   observers_.RemoveObserver(observer);
 }
 
-void AppLifetimeMonitor::Observe(int type,
-                                const content::NotificationSource& source,
-                                const content::NotificationDetails& details) {
-  DCHECK_EQ(extensions::NOTIFICATION_EXTENSION_HOST_DID_STOP_FIRST_LOAD, type);
-  ExtensionHost* host = content::Details<ExtensionHost>(details).ptr();
+void AppLifetimeMonitor::OnExtensionHostCompletedFirstLoad(
+    content::BrowserContext* browser_context,
+    ExtensionHost* host) {
   const Extension* extension = host->extension();
   if (!extension || !extension->is_platform_app())
     return;
diff --git a/apps/app_lifetime_monitor.h b/apps/app_lifetime_monitor.h
index 1d2eecd..f817ec2 100644
--- a/apps/app_lifetime_monitor.h
+++ b/apps/app_lifetime_monitor.h
@@ -11,8 +11,6 @@
 #include "base/observer_list.h"
 #include "base/scoped_observation.h"
 #include "components/keyed_service/core/keyed_service.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
 #include "extensions/browser/app_window/app_window_registry.h"
 #include "extensions/browser/extension_host_registry.h"
 
@@ -25,7 +23,6 @@
 // Observes startup of apps and their windows and notifies observers of these
 // events.
 class AppLifetimeMonitor : public KeyedService,
-                           public content::NotificationObserver,
                            public extensions::AppWindowRegistry::Observer,
                            public extensions::ExtensionHostRegistry::Observer {
  public:
@@ -59,11 +56,6 @@
   void RemoveObserver(Observer* observer);
 
  private:
-  // content::NotificationObserver overrides:
-  void Observe(int type,
-               const content::NotificationSource& source,
-               const content::NotificationDetails& details) override;
-
   // extensions::AppWindowRegistry::Observer overrides:
   void OnAppWindowRemoved(extensions::AppWindow* app_window) override;
   void OnAppWindowHidden(extensions::AppWindow* app_window) override;
@@ -71,6 +63,9 @@
                         bool was_hidden) override;
 
   // extensions::ExtensionHostRegistry::Observer:
+  void OnExtensionHostCompletedFirstLoad(
+      content::BrowserContext* browser_context,
+      extensions::ExtensionHost* host) override;
   void OnExtensionHostDestroyed(content::BrowserContext* browser_context,
                                 extensions::ExtensionHost* host) override;
 
@@ -84,7 +79,6 @@
   void NotifyAppDeactivated(const std::string& app_id);
   void NotifyAppStop(const std::string& app_id);
 
-  content::NotificationRegistrar registrar_;
   content::BrowserContext* context_;
   base::ObserverList<Observer>::Unchecked observers_;
   base::ScopedObservation<extensions::ExtensionHostRegistry,
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 54e59d4..0071a5db 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -1636,10 +1636,6 @@
     "wm/drag_window_resizer.h",
     "wm/event_client_impl.cc",
     "wm/event_client_impl.h",
-    "wm/full_restore/full_restore_controller.cc",
-    "wm/full_restore/full_restore_controller.h",
-    "wm/full_restore/full_restore_util.cc",
-    "wm/full_restore/full_restore_util.h",
     "wm/fullscreen_window_finder.cc",
     "wm/fullscreen_window_finder.h",
     "wm/gestures/back_gesture/back_gesture_affordance.cc",
@@ -1832,6 +1828,10 @@
     "wm/window_properties.h",
     "wm/window_resizer.cc",
     "wm/window_resizer.h",
+    "wm/window_restore/window_restore_controller.cc",
+    "wm/window_restore/window_restore_controller.h",
+    "wm/window_restore/window_restore_util.cc",
+    "wm/window_restore/window_restore_util.h",
     "wm/window_state.cc",
     "wm/window_state.h",
     "wm/window_state_delegate.cc",
@@ -2345,6 +2345,7 @@
     "shelf/test/widget_animation_smoothness_inspector.cc",
     "shelf/test/widget_animation_smoothness_inspector.h",
     "shell_unittest.cc",
+    "style/ash_color_provider_unittests.cc",
     "system/accessibility/accessibility_feature_pod_controller_unittest.cc",
     "system/accessibility/autoclick_menu_bubble_controller_unittest.cc",
     "system/accessibility/dictation_button_tray_unittest.cc",
@@ -2493,7 +2494,6 @@
     "wm/desks/desks_unittests.cc",
     "wm/desks/root_window_desk_switch_animator_unittest.cc",
     "wm/drag_window_resizer_unittest.cc",
-    "wm/full_restore/full_restore_controller_unittest.cc",
     "wm/fullscreen_window_finder_unittest.cc",
     "wm/gestures/back_gesture/back_gesture_affordance_unittest.cc",
     "wm/gestures/back_gesture/back_gesture_contextual_nudge_controller_impl_unittest.cc",
@@ -2553,6 +2553,7 @@
     "wm/window_positioner_unittest.cc",
     "wm/window_positioning_utils_unittest.cc",
     "wm/window_preview_view_unittest.cc",
+    "wm/window_restore/window_restore_controller_unittest.cc",
     "wm/window_state_unittest.cc",
     "wm/window_transient_descendant_iterator_unittest.cc",
     "wm/window_util_unittest.cc",
diff --git a/ash/accelerators/accelerator_controller_unittest.cc b/ash/accelerators/accelerator_controller_unittest.cc
index c6cd647..709a79f 100644
--- a/ash/accelerators/accelerator_controller_unittest.cc
+++ b/ash/accelerators/accelerator_controller_unittest.cc
@@ -2627,6 +2627,9 @@
  public:
   FakeMagnificationManager() = default;
 
+  FakeMagnificationManager(const FakeMagnificationManager&) = delete;
+  FakeMagnificationManager& operator=(const FakeMagnificationManager&) = delete;
+
   void SetPrefs(PrefService* prefs) {
     pref_change_registrar_ = std::make_unique<PrefChangeRegistrar>();
     pref_change_registrar_->Init(prefs);
@@ -2645,8 +2648,6 @@
  private:
   std::unique_ptr<PrefChangeRegistrar> pref_change_registrar_;
   PrefService* prefs_;
-
-  DISALLOW_COPY_AND_ASSIGN(FakeMagnificationManager);
 };
 
 TEST_F(MagnifiersAcceleratorsTester, TestToggleFullscreenMagnifier) {
diff --git a/ash/accelerators/accelerator_unittest.cc b/ash/accelerators/accelerator_unittest.cc
index 8aa5db3e..7fced5b2 100644
--- a/ash/accelerators/accelerator_unittest.cc
+++ b/ash/accelerators/accelerator_unittest.cc
@@ -63,6 +63,9 @@
  public:
   AcceleratorTest() : is_in_overview_mode_(false) {}
 
+  AcceleratorTest(const AcceleratorTest&) = delete;
+  AcceleratorTest& operator=(const AcceleratorTest&) = delete;
+
   void SetUp() override {
     ui_controls::InstallUIControlsAura(test::CreateAshUIControls());
 
@@ -98,9 +101,6 @@
 
  protected:
   bool is_in_overview_mode_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(AcceleratorTest);
 };
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/ash/accelerators/exit_warning_handler.cc b/ash/accelerators/exit_warning_handler.cc
index f00918d..913936b 100644
--- a/ash/accelerators/exit_warning_handler.cc
+++ b/ash/accelerators/exit_warning_handler.cc
@@ -65,6 +65,10 @@
     SetLayoutManager(std::make_unique<views::FillLayout>());
   }
 
+  ExitWarningWidgetDelegateView(const ExitWarningWidgetDelegateView&) = delete;
+  ExitWarningWidgetDelegateView& operator=(
+      const ExitWarningWidgetDelegateView&) = delete;
+
   void OnPaint(gfx::Canvas* canvas) override {
     cc::PaintFlags flags;
     flags.setStyle(cc::PaintFlags::kFill_Style);
@@ -82,8 +86,6 @@
   std::u16string text_;
   std::u16string accessible_name_;
   int text_width_;
-
-  DISALLOW_COPY_AND_ASSIGN(ExitWarningWidgetDelegateView);
 };
 
 }  // namespace
diff --git a/ash/accessibility/accessibility_controller_impl.h b/ash/accessibility/accessibility_controller_impl.h
index 193d836..6a6535b 100644
--- a/ash/accessibility/accessibility_controller_impl.h
+++ b/ash/accessibility/accessibility_controller_impl.h
@@ -195,6 +195,11 @@
   };
 
   AccessibilityControllerImpl();
+
+  AccessibilityControllerImpl(const AccessibilityControllerImpl&) = delete;
+  AccessibilityControllerImpl& operator=(const AccessibilityControllerImpl&) =
+      delete;
+
   ~AccessibilityControllerImpl() override;
 
   // See Shell::RegisterProfilePrefs().
@@ -579,8 +584,6 @@
   base::WeakPtr<AccessibilityConfirmationDialog> confirmation_dialog_;
 
   base::WeakPtrFactory<AccessibilityControllerImpl> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(AccessibilityControllerImpl);
 };
 
 }  // namespace ash
diff --git a/ash/accessibility/chromevox/touch_exploration_controller_unittest.cc b/ash/accessibility/chromevox/touch_exploration_controller_unittest.cc
index 5bac394..acafab4 100644
--- a/ash/accessibility/chromevox/touch_exploration_controller_unittest.cc
+++ b/ash/accessibility/chromevox/touch_exploration_controller_unittest.cc
@@ -85,6 +85,11 @@
     touch_exploration_controller_.reset(touch_exploration_controller);
   }
 
+  TouchExplorationControllerTestApi(const TouchExplorationControllerTestApi&) =
+      delete;
+  TouchExplorationControllerTestApi& operator=(
+      const TouchExplorationControllerTestApi&) = delete;
+
   void CallTapTimerNowForTesting() {
     DCHECK(touch_exploration_controller_->tap_timer_.IsRunning());
     touch_exploration_controller_->tap_timer_.Stop();
@@ -157,8 +162,6 @@
 
  private:
   std::unique_ptr<TouchExplorationController> touch_exploration_controller_;
-
-  DISALLOW_COPY_AND_ASSIGN(TouchExplorationControllerTestApi);
 };
 
 class TouchExplorationTest : public aura::test::AuraTestBase {
diff --git a/ash/accessibility/sticky_keys/sticky_keys_unittest.cc b/ash/accessibility/sticky_keys/sticky_keys_unittest.cc
index 5c43314..57b64d63 100644
--- a/ash/accessibility/sticky_keys/sticky_keys_unittest.cc
+++ b/ash/accessibility/sticky_keys/sticky_keys_unittest.cc
@@ -16,6 +16,10 @@
 namespace ash {
 
 class StickyKeysTest : public AshTestBase {
+ public:
+  StickyKeysTest(const StickyKeysTest&) = delete;
+  StickyKeysTest& operator=(const StickyKeysTest&) = delete;
+
  protected:
   StickyKeysTest() : target_(NULL), root_window_(NULL) {}
 
@@ -163,8 +167,6 @@
   aura::Window* target_;
   // The root window of |target_|. Not owned.
   aura::Window* root_window_;
-
-  DISALLOW_COPY_AND_ASSIGN(StickyKeysTest);
 };
 
 TEST_F(StickyKeysTest, BasicOneshotScenarioTest) {
diff --git a/ash/accessibility/switch_access/point_scan_controller_unittest.cc b/ash/accessibility/switch_access/point_scan_controller_unittest.cc
index d2a1f25..45303bd 100644
--- a/ash/accessibility/switch_access/point_scan_controller_unittest.cc
+++ b/ash/accessibility/switch_access/point_scan_controller_unittest.cc
@@ -20,6 +20,10 @@
 namespace ash {
 
 class PointScanControllerTest : public AshTestBase {
+ public:
+  PointScanControllerTest(const PointScanControllerTest&) = delete;
+  PointScanControllerTest& operator=(const PointScanControllerTest&) = delete;
+
  protected:
   PointScanControllerTest() = default;
   ~PointScanControllerTest() override = default;
@@ -117,8 +121,6 @@
   int diff_count_ = 0;
   int row_diff_count_ = 0;
   int col_diff_count_ = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(PointScanControllerTest);
 };
 
 TEST_F(PointScanControllerTest, StartScanning) {
diff --git a/ash/accessibility/ui/accessibility_highlight_controller_unittest.cc b/ash/accessibility/ui/accessibility_highlight_controller_unittest.cc
index 885fec3..3668c6f 100644
--- a/ash/accessibility/ui/accessibility_highlight_controller_unittest.cc
+++ b/ash/accessibility/ui/accessibility_highlight_controller_unittest.cc
@@ -54,6 +54,12 @@
 }  // namespace
 
 class AccessibilityHighlightControllerTest : public AshTestBase {
+ public:
+  AccessibilityHighlightControllerTest(
+      const AccessibilityHighlightControllerTest&) = delete;
+  AccessibilityHighlightControllerTest& operator=(
+      const AccessibilityHighlightControllerTest&) = delete;
+
  protected:
   AccessibilityHighlightControllerTest() = default;
   ~AccessibilityHighlightControllerTest() override = default;
@@ -130,8 +136,6 @@
   gfx::Image after_;
   int diff_count_ = 0;
   SkColor average_diff_color_ = SK_ColorTRANSPARENT;
-
-  DISALLOW_COPY_AND_ASSIGN(AccessibilityHighlightControllerTest);
 };
 
 TEST_F(AccessibilityHighlightControllerTest, TestCaretRingDrawsBluePixels) {
diff --git a/ash/app_list/app_list_controller_impl.cc b/ash/app_list/app_list_controller_impl.cc
index 294c6bc..a541854e 100644
--- a/ash/app_list/app_list_controller_impl.cc
+++ b/ash/app_list/app_list_controller_impl.cc
@@ -382,12 +382,6 @@
   model_->DeleteUninstalledItem(id);
 }
 
-void AppListControllerImpl::MoveItemToFolder(const std::string& id,
-                                             const std::string& folder_id) {
-  AppListItem* item = model_->FindItem(id);
-  model_->MoveItemToFolder(item, folder_id);
-}
-
 void AppListControllerImpl::SetStatus(AppListModelStatus status) {
   model_->SetStatus(status);
 }
@@ -419,6 +413,9 @@
   if (!item)
     return;
 
+  // TODO(https://crbug.com/1252433): refactor this function because the current
+  // implementation is bug prone.
+
   // data may not contain valid position or icon. Preserve it in this case.
   if (!data->position.IsValid())
     data->position = item->position();
@@ -442,6 +439,9 @@
   if (data->icon.isNull())
     data->icon = item->GetDefaultIcon();
 
+  if (data->folder_id != item->folder_id())
+    model_->MoveItemToFolder(item, data->folder_id);
+
   item->SetMetadata(std::move(data));
 }
 
diff --git a/ash/app_list/app_list_controller_impl.h b/ash/app_list/app_list_controller_impl.h
index 9ce2a5c08..e9dc74b 100644
--- a/ash/app_list/app_list_controller_impl.h
+++ b/ash/app_list/app_list_controller_impl.h
@@ -105,8 +105,6 @@
                        const std::string& folder_id) override;
   void RemoveItem(const std::string& id) override;
   void RemoveUninstalledItem(const std::string& id) override;
-  void MoveItemToFolder(const std::string& id,
-                        const std::string& folder_id) override;
   void SetStatus(AppListModelStatus status) override;
   void SetSearchEngineIsGoogle(bool is_google) override;
   void UpdateSearchBox(const std::u16string& text,
diff --git a/ash/app_list/folder_image_unittest.cc b/ash/app_list/folder_image_unittest.cc
index 7e610e57..bc73224 100644
--- a/ash/app_list/folder_image_unittest.cc
+++ b/ash/app_list/folder_image_unittest.cc
@@ -39,6 +39,9 @@
  public:
   TestFolderImageObserver() : updated_flag_(false) {}
 
+  TestFolderImageObserver(const TestFolderImageObserver&) = delete;
+  TestFolderImageObserver& operator=(const TestFolderImageObserver&) = delete;
+
   bool updated() const { return updated_flag_; }
 
   void Reset() { updated_flag_ = false; }
@@ -50,8 +53,6 @@
 
  private:
   bool updated_flag_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestFolderImageObserver);
 };
 
 }  // namespace
diff --git a/ash/app_list/model/app_list_test_model.h b/ash/app_list/model/app_list_test_model.h
index 6998d73..c7c47ab 100644
--- a/ash/app_list/model/app_list_test_model.h
+++ b/ash/app_list/model/app_list_test_model.h
@@ -46,6 +46,9 @@
 
   AppListTestModel();
 
+  AppListTestModel(const AppListTestModel&) = delete;
+  AppListTestModel& operator=(const AppListTestModel&) = delete;
+
   // Raw pointer version convenience versions of AppListModel methods.
   AppListItem* AddItem(AppListItem* item);
   AppListItem* AddItemToFolder(AppListItem* item, const std::string& folder_id);
@@ -87,8 +90,6 @@
   int activate_count_ = 0;
   AppListItem* last_activated_ = nullptr;
   int naming_index_ = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(AppListTestModel);
 };
 
 }  // namespace test
diff --git a/ash/app_list/views/app_list_folder_view.cc b/ash/app_list/views/app_list_folder_view.cc
index 59bb7ba..33a69f5e 100644
--- a/ash/app_list/views/app_list_folder_view.cc
+++ b/ash/app_list/views/app_list_folder_view.cc
@@ -760,19 +760,6 @@
   PreferredSizeChanged();
 }
 
-bool AppListFolderView::OnKeyPressed(const ui::KeyEvent& event) {
-  // Let the FocusManager handle Left/Right keys.
-  if (!IsUnhandledUpDownKeyEvent(event))
-    return false;
-
-  if (folder_header_view_->HasTextFocus() && event.key_code() == ui::VKEY_UP) {
-    // Move focus to the last app list item view in the selected page.
-    items_grid_view_->GetCurrentPageLastItemViewInFolder()->RequestFocus();
-    return true;
-  }
-  return false;
-}
-
 void AppListFolderView::OnViewIsDeleting(views::View* view) {
   DCHECK_EQ(view, folder_item_view_);
 
diff --git a/ash/app_list/views/app_list_folder_view.h b/ash/app_list/views/app_list_folder_view.h
index 4fc0d46..9c59e49b 100644
--- a/ash/app_list/views/app_list_folder_view.h
+++ b/ash/app_list/views/app_list_folder_view.h
@@ -95,7 +95,6 @@
   // views::View
   void Layout() override;
   void ChildPreferredSizeChanged(View* child) override;
-  bool OnKeyPressed(const ui::KeyEvent& event) override;
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
 
   // AppListModelObserver
diff --git a/ash/app_list/views/app_list_page.cc b/ash/app_list/views/app_list_page.cc
index aca7bcf..0493c90 100644
--- a/ash/app_list/views/app_list_page.cc
+++ b/ash/app_list/views/app_list_page.cc
@@ -6,6 +6,7 @@
 
 #include "ash/app_list/views/contents_view.h"
 #include "ui/compositor/scoped_layer_animation_settings.h"
+#include "ui/views/focus/focus_manager.h"
 
 namespace ash {
 
@@ -42,11 +43,13 @@
 }
 
 views::View* AppListPage::GetFirstFocusableView() {
-  return nullptr;
+  return GetFocusManager()->GetNextFocusableView(
+      this, GetWidget(), false /* reverse */, false /* dont_loop */);
 }
 
 views::View* AppListPage::GetLastFocusableView() {
-  return nullptr;
+  return GetFocusManager()->GetNextFocusableView(
+      this, GetWidget(), true /* reverse */, false /* dont_loop */);
 }
 
 void AppListPage::AnimateOpacity(float current_progress,
diff --git a/ash/app_list/views/app_list_page.h b/ash/app_list/views/app_list_page.h
index 21646e0..ca09719 100644
--- a/ash/app_list/views/app_list_page.h
+++ b/ash/app_list/views/app_list_page.h
@@ -106,10 +106,10 @@
   }
 
   // Returns the first focusable view in this page.
-  virtual views::View* GetFirstFocusableView();
+  views::View* GetFirstFocusableView();
 
   // Returns the last focusable view in this page.
-  virtual views::View* GetLastFocusableView();
+  views::View* GetLastFocusableView();
 
   // Called when the app list view state changes to |target_view_state| to
   // animate the app list page opacity.
diff --git a/ash/app_list/views/app_list_view.h b/ash/app_list/views/app_list_view.h
index 51e3532..9fc06d5 100644
--- a/ash/app_list/views/app_list_view.h
+++ b/ash/app_list/views/app_list_view.h
@@ -160,6 +160,10 @@
 
   // Does not take ownership of |delegate|.
   explicit AppListView(AppListViewDelegate* delegate);
+
+  AppListView(const AppListView&) = delete;
+  AppListView& operator=(const AppListView&) = delete;
+
   ~AppListView() override;
 
   // Prevents handling input events for the |window| in context of handling in
@@ -653,8 +657,6 @@
   // detects that `SetState()` got called again (in which case the weak ptr will
   // be invalidated).
   base::WeakPtrFactory<AppListView> set_state_weak_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(AppListView);
 };
 
 }  // namespace ash
diff --git a/ash/app_list/views/app_list_view_unittest.cc b/ash/app_list/views/app_list_view_unittest.cc
index 4ca8329d..b75a37b 100644
--- a/ash/app_list/views/app_list_view_unittest.cc
+++ b/ash/app_list/views/app_list_view_unittest.cc
@@ -1196,7 +1196,7 @@
   std::vector<views::View*> forward_view_list;
   const views::ViewModelT<AppListItemView>* view_model =
       app_list_folder_view()->items_grid_view()->view_model();
-  for (size_t i = 0; i < GetAppListConfig().max_folder_items_per_page();
+  for (int i = 0; i < view_model->view_size();
        i += app_list_folder_view()->items_grid_view()->cols()) {
     forward_view_list.push_back(view_model->view_at(i));
   }
@@ -1213,7 +1213,7 @@
   backward_view_list.push_back(search_box_view()->search_box());
   backward_view_list.push_back(
       app_list_folder_view()->folder_header_view()->GetFolderNameViewForTest());
-  for (int i = GetAppListConfig().max_folder_items_per_page() - 1; i >= 0;
+  for (int i = view_model->view_size() - 1; i >= 0;
        i -= app_list_folder_view()->items_grid_view()->cols()) {
     backward_view_list.push_back(view_model->view_at(i));
   }
@@ -1251,20 +1251,17 @@
   forward_view_list.push_back(
       app_list_folder_view()->folder_header_view()->GetFolderNameViewForTest());
   forward_view_list.push_back(search_box_view()->search_box());
-  forward_view_list.push_back(
-      view_model->view_at(GetAppListConfig().max_folder_items_per_page()));
+  forward_view_list.push_back(view_model->view_at(0));
 
   // Test traversal triggered by down.
   TestFocusTraversal(forward_view_list, ui::VKEY_DOWN, false);
 
   std::vector<views::View*> backward_view_list;
-  backward_view_list.push_back(
-      view_model->view_at(GetAppListConfig().max_folder_items_per_page()));
+  backward_view_list.push_back(view_model->view_at(0));
   backward_view_list.push_back(search_box_view()->search_box());
   backward_view_list.push_back(
       app_list_folder_view()->folder_header_view()->GetFolderNameViewForTest());
-  for (size_t i = view_model->view_size() - 1;
-       i >= GetAppListConfig().max_folder_items_per_page();
+  for (int i = view_model->view_size() - 1; i >= 0;
        i -= app_list_folder_view()->items_grid_view()->cols()) {
     backward_view_list.push_back(view_model->view_at(i));
   }
diff --git a/ash/app_list/views/apps_container_view.cc b/ash/app_list/views/apps_container_view.cc
index 75ba44c..dda842d5 100644
--- a/ash/app_list/views/apps_container_view.cc
+++ b/ash/app_list/views/apps_container_view.cc
@@ -733,23 +733,6 @@
   return bounds;
 }
 
-views::View* AppsContainerView::GetFirstFocusableView() {
-  if (IsInFolderView()) {
-    // The pagination inside a folder is set horizontally, so focus should be
-    // set on the first item view in the selected page when it is moved down
-    // from the search box.
-    return app_list_folder_view_->items_grid_view()
-        ->GetCurrentPageFirstItemViewInFolder();
-  }
-  return GetFocusManager()->GetNextFocusableView(
-      this, GetWidget(), false /* reverse */, false /* dont_loop */);
-}
-
-views::View* AppsContainerView::GetLastFocusableView() {
-  return GetFocusManager()->GetNextFocusableView(
-      this, GetWidget(), true /* reverse */, false /* dont_loop */);
-}
-
 const gfx::Insets& AppsContainerView::CalculateMarginsForAvailableBounds(
     const gfx::Rect& available_bounds,
     const gfx::Size& search_box_size) {
diff --git a/ash/app_list/views/apps_container_view.h b/ash/app_list/views/apps_container_view.h
index f7dd0f3..79e265e 100644
--- a/ash/app_list/views/apps_container_view.h
+++ b/ash/app_list/views/apps_container_view.h
@@ -104,8 +104,6 @@
       AppListState state,
       const gfx::Rect& contents_bounds,
       const gfx::Rect& search_box_bounds) const override;
-  views::View* GetFirstFocusableView() override;
-  views::View* GetLastFocusableView() override;
   void AnimateOpacity(float current_progress,
                       AppListViewState target_view_state,
                       const OpacityAnimator& animator) override;
diff --git a/ash/app_list/views/apps_grid_view.cc b/ash/app_list/views/apps_grid_view.cc
index 79f6d4c..f45ceac 100644
--- a/ash/app_list/views/apps_grid_view.cc
+++ b/ash/app_list/views/apps_grid_view.cc
@@ -1488,31 +1488,16 @@
   int target_col = source_index.slot % cols_;
 
   if (target_row < 0) {
-    // In folders, vertical keys should not flip between pages (because the
-    // folder grid is paged horizontally) - set the target page to -1, so the
-    // focus gets moved to the reversed next focusable view.
-    if (folder_delegate_) {
-      target_page = -1;
-    } else {
-      // Move focus to the last row of previous page if target row is negative.
-      --target_page;
+    // Move focus to the last row of previous page if target row is negative.
+    --target_page;
 
-      // |target_page| may be invalid which makes |target_row| invalid, but
-      // |target_row| will not be used if |target_page| is invalid.
-      target_row = (GetNumberOfItemsOnPage(target_page) - 1) / cols_;
-    }
+    // |target_page| may be invalid which makes |target_row| invalid, but
+    // |target_row| will not be used if |target_page| is invalid.
+    target_row = (GetNumberOfItemsOnPage(target_page) - 1) / cols_;
   } else if (target_row > (GetNumberOfItemsOnPage(target_page) - 1) / cols_) {
-    if (folder_delegate_) {
-      // In folders, vertical keys should not flip between pages (because the
-      // folder grid is paged horizontally) - set the target page beyond the
-      // number of pages in the grid so the focus gets moved to the next
-      // focusable view.
-      target_page = GetTotalPages();
-    } else {
-      // Move focus to the first row of next page if target row is beyond range.
-      ++target_page;
-      target_row = 0;
-    }
+    // Move focus to the first row of next page if target row is beyond range.
+    ++target_page;
+    target_row = 0;
   }
 
   if (target_page < 0) {
@@ -1680,22 +1665,6 @@
   RecordAppMovingTypeMetrics(kMoveByKeyboardOutOfFolder);
 }
 
-AppListItemView* AppsGridView::GetCurrentPageFirstItemViewInFolder() {
-  DCHECK(folder_delegate_);
-  int first_index =
-      GetSelectedPage() * GetAppListConfig().max_folder_items_per_page();
-  return view_model_.view_at(first_index);
-}
-
-AppListItemView* AppsGridView::GetCurrentPageLastItemViewInFolder() {
-  DCHECK(folder_delegate_);
-  int last_index = std::min(
-      (GetSelectedPage() + 1) * GetAppListConfig().max_folder_items_per_page() -
-          1,
-      item_list_->item_count() - 1);
-  return view_model_.view_at(last_index);
-}
-
 void AppsGridView::UpdatePagedViewStructure() {
   view_structure_.SaveToMetadata();
 }
diff --git a/ash/app_list/views/apps_grid_view.h b/ash/app_list/views/apps_grid_view.h
index de84d19..11480e9 100644
--- a/ash/app_list/views/apps_grid_view.h
+++ b/ash/app_list/views/apps_grid_view.h
@@ -252,12 +252,6 @@
                               AppListItemView* original_parent_item_view,
                               ui::KeyboardCode key_code);
 
-  // Returns the first app list item view in the selected page in the folder.
-  AppListItemView* GetCurrentPageFirstItemViewInFolder();
-
-  // Returns the last app list item view in the selected page in the folder.
-  AppListItemView* GetCurrentPageLastItemViewInFolder();
-
   // Updates paged view structure and save it to meta data.
   void UpdatePagedViewStructure();
 
diff --git a/ash/app_list/views/assistant/assistant_page_view.cc b/ash/app_list/views/assistant/assistant_page_view.cc
index ed839e00..4f33daa8 100644
--- a/ash/app_list/views/assistant/assistant_page_view.cc
+++ b/ash/app_list/views/assistant/assistant_page_view.cc
@@ -39,7 +39,6 @@
 #include "ui/compositor/scoped_layer_animation_settings.h"
 #include "ui/compositor_extra/shadow.h"
 #include "ui/views/background.h"
-#include "ui/views/focus/focus_manager.h"
 #include "ui/views/layout/layout_manager_base.h"
 
 namespace ash {
@@ -335,16 +334,6 @@
   return absl::nullopt;
 }
 
-views::View* AssistantPageView::GetFirstFocusableView() {
-  return GetFocusManager()->GetNextFocusableView(
-      this, GetWidget(), /*reverse=*/false, /*dont_loop=*/false);
-}
-
-views::View* AssistantPageView::GetLastFocusableView() {
-  return GetFocusManager()->GetNextFocusableView(
-      this, GetWidget(), /*reverse=*/true, /*dont_loop=*/false);
-}
-
 void AssistantPageView::AnimateYPosition(AppListViewState target_view_state,
                                          const TransformAnimator& animator,
                                          float default_offset) {
diff --git a/ash/app_list/views/assistant/assistant_page_view.h b/ash/app_list/views/assistant/assistant_page_view.h
index 35972750..efa31b4f 100644
--- a/ash/app_list/views/assistant/assistant_page_view.h
+++ b/ash/app_list/views/assistant/assistant_page_view.h
@@ -56,8 +56,6 @@
       AppListState state,
       const gfx::Rect& contents_bounds,
       const gfx::Rect& search_box_bounds) const override;
-  views::View* GetFirstFocusableView() override;
-  views::View* GetLastFocusableView() override;
   void AnimateYPosition(AppListViewState target_view_state,
                         const TransformAnimator& animator,
                         float default_offset) override;
diff --git a/ash/app_list/views/assistant/assistant_page_view_unittest.cc b/ash/app_list/views/assistant/assistant_page_view_unittest.cc
index 43127ff..bfd11f3b 100644
--- a/ash/app_list/views/assistant/assistant_page_view_unittest.cc
+++ b/ash/app_list/views/assistant/assistant_page_view_unittest.cc
@@ -163,8 +163,8 @@
                      base::TimeTicks(),
                      details) {}
 
- private:
-  DISALLOW_COPY_AND_ASSIGN(GestureEventForTest);
+  GestureEventForTest(const GestureEventForTest&) = delete;
+  GestureEventForTest& operator=(const GestureEventForTest&) = delete;
 };
 
 // Base class for tests of the embedded assistant page in:
@@ -175,6 +175,9 @@
  public:
   AssistantPageViewTest() = default;
 
+  AssistantPageViewTest(const AssistantPageViewTest&) = delete;
+  AssistantPageViewTest& operator=(const AssistantPageViewTest&) = delete;
+
   void ShowAssistantUiInTextMode() {
     ShowAssistantUi(AssistantEntryPoint::kUnspecified);
     EXPECT_TRUE(IsVisible());
@@ -207,9 +210,6 @@
     SetNumberOfSessionsWhereOnboardingShown(
         assistant::ui::kOnboardingMaxSessionsShown);
   }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(AssistantPageViewTest);
 };
 
 // Tests for the legacy non-bubble app list ("peeking launcher").
@@ -993,6 +993,11 @@
  public:
   AssistantPageViewTabletModeTest() = default;
 
+  AssistantPageViewTabletModeTest(const AssistantPageViewTabletModeTest&) =
+      delete;
+  AssistantPageViewTabletModeTest& operator=(
+      const AssistantPageViewTabletModeTest&) = delete;
+
   void SetUp() override {
     AssistantPageViewTest::SetUp();
     SetTabletMode(true);
@@ -1030,9 +1035,6 @@
   gfx::Point GetPointInside(const views::View* view) {
     return view->GetBoundsInScreen().CenterPoint();
   }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(AssistantPageViewTabletModeTest);
 };
 
 TEST_F(AssistantPageViewTabletModeTest,
diff --git a/ash/app_list/views/contents_view.h b/ash/app_list/views/contents_view.h
index 6f8f7f4..4f6ad48 100644
--- a/ash/app_list/views/contents_view.h
+++ b/ash/app_list/views/contents_view.h
@@ -73,6 +73,10 @@
   };
 
   explicit ContentsView(AppListView* app_list_view);
+
+  ContentsView(const ContentsView&) = delete;
+  ContentsView& operator=(const ContentsView&) = delete;
+
   ~ContentsView() override;
 
   // Initialize the pages of the launcher. Should be called after
@@ -304,8 +308,6 @@
   // to a new app list view state.
   absl::optional<AppListState> target_page_for_last_view_state_update_;
   absl::optional<AppListViewState> last_target_view_state_;
-
-  DISALLOW_COPY_AND_ASSIGN(ContentsView);
 };
 
 }  // namespace ash
diff --git a/ash/app_list/views/continue_task_view.cc b/ash/app_list/views/continue_task_view.cc
index 8c9ce95..3d8cce8 100644
--- a/ash/app_list/views/continue_task_view.cc
+++ b/ash/app_list/views/continue_task_view.cc
@@ -13,6 +13,7 @@
 #include "ash/app_list/app_list_view_delegate.h"
 #include "ash/app_list/model/search/search_result.h"
 #include "ash/bubble/bubble_utils.h"
+#include "ash/constants/ash_features.h"
 #include "ash/public/cpp/style/color_provider.h"
 #include "base/strings/string_util.h"
 #include "extensions/common/constants.h"
@@ -31,13 +32,26 @@
 namespace ash {
 namespace {
 
-constexpr int kIconSize = 36;
+constexpr int kIconSize = 20;
+constexpr int kCircleRadius = 18;
 
 constexpr int kBetweenChildPadding = 16;
 constexpr gfx::Insets kInteriorMargin(7, 8, 7, 16);
 
 constexpr int kViewCornerRadius = 8;
 
+gfx::ImageSkia CreateIconWithCircleBackground(const gfx::ImageSkia& icon) {
+  // The icon with circular background should only be styled when dark light
+  // mode is enabled. Otherwise, use the default chip icon.
+  if (!features::IsDarkLightModeEnabled())
+    return icon;
+  return gfx::ImageSkiaOperations::CreateImageWithCircleBackground(
+      kCircleRadius,
+      ColorProvider::Get()->GetControlsLayerColor(
+          ColorProvider::ControlsLayerType::kControlBackgroundColorInactive),
+      icon);
+}
+
 }  // namespace
 
 ContinueTaskView::ContinueTaskView(AppListViewDelegate* view_delegate)
@@ -78,8 +92,6 @@
   icon_ = AddChildView(std::make_unique<views::ImageView>());
   icon_->SetVerticalAlignment(views::ImageView::Alignment::kCenter);
   icon_->SetHorizontalAlignment(views::ImageView::Alignment::kCenter);
-  icon_->SetImageSize(GetIconSize());
-  icon_->SetPreferredSize(GetIconSize());
 
   auto* label_container = AddChildView(std::make_unique<views::View>());
   label_container->SetLayoutManager(std::make_unique<views::BoxLayout>(
@@ -112,10 +124,11 @@
 }
 
 void ContinueTaskView::SetIcon(const gfx::ImageSkia& icon) {
-  gfx::ImageSkia resized(gfx::ImageSkiaOperations::CreateResizedImage(
-      icon, skia::ImageOperations::RESIZE_BEST, GetIconSize()));
-  icon_->SetImage(resized);
-  icon_->SetImageSize(GetIconSize());
+  icon_->SetImage(CreateIconWithCircleBackground(
+      icon.size() == GetIconSize()
+          ? icon
+          : gfx::ImageSkiaOperations::CreateResizedImage(
+                icon, skia::ImageOperations::RESIZE_BEST, GetIconSize())));
 }
 
 gfx::Size ContinueTaskView::GetIconSize() const {
diff --git a/ash/app_list/views/result_selection_controller_unittest.cc b/ash/app_list/views/result_selection_controller_unittest.cc
index 73e17a8..51b4988 100644
--- a/ash/app_list/views/result_selection_controller_unittest.cc
+++ b/ash/app_list/views/result_selection_controller_unittest.cc
@@ -52,6 +52,10 @@
     set_actions_view(actions_view_owned_.get());
   }
 
+  TestResultViewWithActions(const TestResultViewWithActions&) = delete;
+  TestResultViewWithActions& operator=(const TestResultViewWithActions&) =
+      delete;
+
   // TestResultView:
   TestResultViewWithActions* AsResultViewWithActions() override { return this; }
 
@@ -65,8 +69,6 @@
 
  private:
   std::unique_ptr<SearchResultActionsView> actions_view_owned_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestResultViewWithActions);
 };
 
 // Allows immediate invocation of |VerticalTestContainer| and its derivatives,
diff --git a/ash/app_list/views/search_result_base_view.h b/ash/app_list/views/search_result_base_view.h
index c459841..8075c4e 100644
--- a/ash/app_list/views/search_result_base_view.h
+++ b/ash/app_list/views/search_result_base_view.h
@@ -21,6 +21,9 @@
  public:
   SearchResultBaseView();
 
+  SearchResultBaseView(const SearchResultBaseView&) = delete;
+  SearchResultBaseView& operator=(const SearchResultBaseView&) = delete;
+
   // Set whether the result is selected. It updates the background highlight,
   // and selects the result action associated with the result if
   // SearchBoxSelection feature is enabled.
@@ -128,8 +131,6 @@
   // activated by user by pressing ENTER key.
   bool is_default_result_ = false;
   SearchResult* result_ = nullptr;  // Owned by SearchModel::SearchResults.
-
-  DISALLOW_COPY_AND_ASSIGN(SearchResultBaseView);
 };
 
 }  // namespace ash
diff --git a/ash/app_list/views/search_result_page_view.cc b/ash/app_list/views/search_result_page_view.cc
index 1390742..fee106a7 100644
--- a/ash/app_list/views/search_result_page_view.cc
+++ b/ash/app_list/views/search_result_page_view.cc
@@ -43,7 +43,6 @@
 #include "ui/views/controls/scroll_view.h"
 #include "ui/views/controls/scrollbar/overlay_scroll_bar.h"
 #include "ui/views/controls/textfield/textfield.h"
-#include "ui/views/focus/focus_manager.h"
 #include "ui/views/layout/box_layout.h"
 #include "ui/views/layout/fill_layout.h"
 #include "ui/views/window/dialog_delegate.h"
@@ -681,16 +680,6 @@
   return absl::nullopt;
 }
 
-views::View* SearchResultPageView::GetFirstFocusableView() {
-  return GetFocusManager()->GetNextFocusableView(
-      this, GetWidget(), false /* reverse */, false /* dont_loop */);
-}
-
-views::View* SearchResultPageView::GetLastFocusableView() {
-  return GetFocusManager()->GetNextFocusableView(
-      this, GetWidget(), true /* reverse */, false /* dont_loop */);
-}
-
 void SearchResultPageView::OnAnchoredDialogClosed() {
   anchored_dialog_.reset();
 }
diff --git a/ash/app_list/views/search_result_page_view.h b/ash/app_list/views/search_result_page_view.h
index 5f1d1eee..96536145 100644
--- a/ash/app_list/views/search_result_page_view.h
+++ b/ash/app_list/views/search_result_page_view.h
@@ -91,8 +91,6 @@
   gfx::Size GetPreferredSearchBoxSize() const override;
   absl::optional<int> GetSearchBoxTop(
       AppListViewState view_state) const override;
-  views::View* GetFirstFocusableView() override;
-  views::View* GetLastFocusableView() override;
 
   // Overridden from SearchResultContainerView::Delegate:
   void OnSearchResultContainerResultsChanging() override;
diff --git a/ash/app_menu/notification_menu_controller_unittest.cc b/ash/app_menu/notification_menu_controller_unittest.cc
index d9c0673..13a9af6 100644
--- a/ash/app_menu/notification_menu_controller_unittest.cc
+++ b/ash/app_menu/notification_menu_controller_unittest.cc
@@ -42,11 +42,12 @@
                             base::OnceClosure(),
                             false /* is_tablet_mode */) {}
 
+  TestAppMenuModelAdapter(const TestAppMenuModelAdapter&) = delete;
+  TestAppMenuModelAdapter& operator=(const TestAppMenuModelAdapter&) = delete;
+
  private:
   // AppMenuModelAdapter overrides:
   void RecordHistogramOnMenuClosed() override {}
-
-  DISALLOW_COPY_AND_ASSIGN(TestAppMenuModelAdapter);
 };
 
 }  // namespace
diff --git a/ash/ash_prefs.cc b/ash/ash_prefs.cc
index d0ff0f0a..776d685 100644
--- a/ash/ash_prefs.cc
+++ b/ash/ash_prefs.cc
@@ -10,6 +10,7 @@
 #include "ash/ambient/ambient_controller.h"
 #include "ash/app_list/app_list_controller_impl.h"
 #include "ash/assistant/assistant_controller_impl.h"
+#include "ash/capture_mode/capture_mode_controller.h"
 #include "ash/clipboard/clipboard_nudge_controller.h"
 #include "ash/components/quick_answers/public/cpp/quick_answers_prefs.h"
 #include "ash/constants/ash_pref_names.h"
@@ -64,6 +65,7 @@
   AmbientController::RegisterProfilePrefs(registry);
   BluetoothPowerController::RegisterProfilePrefs(registry);
   CapsLockNotificationController::RegisterProfilePrefs(registry, for_test);
+  CaptureModeController::RegisterProfilePrefs(registry);
   CellularSetupNotifier::RegisterProfilePrefs(registry);
   contextual_tooltip::RegisterProfilePrefs(registry);
   ClipboardNudgeController::RegisterProfilePrefs(registry);
diff --git a/ash/assistant/assistant_alarm_timer_controller_unittest.cc b/ash/assistant/assistant_alarm_timer_controller_unittest.cc
index 073a8a6..79e05591 100644
--- a/ash/assistant/assistant_alarm_timer_controller_unittest.cc
+++ b/ash/assistant/assistant_alarm_timer_controller_unittest.cc
@@ -334,6 +334,11 @@
       : AssistantAshTestBase(
             base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
 
+  AssistantAlarmTimerControllerTest(const AssistantAlarmTimerControllerTest&) =
+      delete;
+  AssistantAlarmTimerControllerTest& operator=(
+      const AssistantAlarmTimerControllerTest&) = delete;
+
   ~AssistantAlarmTimerControllerTest() override = default;
 
   // AshTestBase:
@@ -370,9 +375,6 @@
   AssistantAlarmTimerController* controller() {
     return AssistantAlarmTimerController::Get();
   }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(AssistantAlarmTimerControllerTest);
 };
 
 // Tests -----------------------------------------------------------------------
diff --git a/ash/assistant/assistant_notification_controller_impl_unittest.cc b/ash/assistant/assistant_notification_controller_impl_unittest.cc
index 0f59d07..21b262cd 100644
--- a/ash/assistant/assistant_notification_controller_impl_unittest.cc
+++ b/ash/assistant/assistant_notification_controller_impl_unittest.cc
@@ -200,6 +200,12 @@
 // AssistantNotificationControllerTest -----------------------------------------
 
 class AssistantNotificationControllerTest : public AshTestBase {
+ public:
+  AssistantNotificationControllerTest(
+      const AssistantNotificationControllerTest&) = delete;
+  AssistantNotificationControllerTest& operator=(
+      const AssistantNotificationControllerTest&) = delete;
+
  protected:
   AssistantNotificationControllerTest()
       : AshTestBase(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
@@ -238,8 +244,6 @@
  private:
   AssistantNotificationControllerImpl* controller_;
   std::unique_ptr<AssistantNotificationModelObserverMock> observer_;
-
-  DISALLOW_COPY_AND_ASSIGN(AssistantNotificationControllerTest);
 };
 
 }  // namespace
diff --git a/ash/assistant/assistant_screen_context_controller_impl_unittest.cc b/ash/assistant/assistant_screen_context_controller_impl_unittest.cc
index e4e701a..ca88030b 100644
--- a/ash/assistant/assistant_screen_context_controller_impl_unittest.cc
+++ b/ash/assistant/assistant_screen_context_controller_impl_unittest.cc
@@ -41,6 +41,12 @@
 }  // namespace
 
 class AssistantScreenContextControllerTest : public AssistantAshTestBase {
+ public:
+  AssistantScreenContextControllerTest(
+      const AssistantScreenContextControllerTest&) = delete;
+  AssistantScreenContextControllerTest& operator=(
+      const AssistantScreenContextControllerTest&) = delete;
+
  protected:
   AssistantScreenContextControllerTest()
       : AssistantAshTestBase(
@@ -95,8 +101,6 @@
 
  private:
   AssistantScreenContextControllerImpl* controller_ = nullptr;
-
-  DISALLOW_COPY_AND_ASSIGN(AssistantScreenContextControllerTest);
 };
 
 // Verify that incognito windows are blocked in screenshot.
diff --git a/ash/assistant/assistant_state_controller_unittest.cc b/ash/assistant/assistant_state_controller_unittest.cc
index 2e2a6ea..f535d7f9 100644
--- a/ash/assistant/assistant_state_controller_unittest.cc
+++ b/ash/assistant/assistant_state_controller_unittest.cc
@@ -90,6 +90,11 @@
 };
 
 class AssistantStateControllerTest : public AshTestBase {
+ public:
+  AssistantStateControllerTest(const AssistantStateControllerTest&) = delete;
+  AssistantStateControllerTest& operator=(const AssistantStateControllerTest&) =
+      delete;
+
  protected:
   AssistantStateControllerTest() = default;
   ~AssistantStateControllerTest() override = default;
@@ -111,8 +116,6 @@
  private:
   PrefService* prefs_ = nullptr;
   std::unique_ptr<TestAssistantStateObserver> observer_;
-
-  DISALLOW_COPY_AND_ASSIGN(AssistantStateControllerTest);
 };
 
 }  // namespace
diff --git a/ash/assistant/model/assistant_interaction_model_observer.h b/ash/assistant/model/assistant_interaction_model_observer.h
index b82c41dc..884d5fc 100644
--- a/ash/assistant/model/assistant_interaction_model_observer.h
+++ b/ash/assistant/model/assistant_interaction_model_observer.h
@@ -23,6 +23,11 @@
 class COMPONENT_EXPORT(ASSISTANT_MODEL) AssistantInteractionModelObserver
     : public base::CheckedObserver {
  public:
+  AssistantInteractionModelObserver(const AssistantInteractionModelObserver&) =
+      delete;
+  AssistantInteractionModelObserver& operator=(
+      const AssistantInteractionModelObserver&) = delete;
+
   // Invoked when the interaction state is changed.
   virtual void OnInteractionStateChanged(InteractionState interaction_state) {}
 
@@ -60,8 +65,6 @@
  protected:
   AssistantInteractionModelObserver() = default;
   ~AssistantInteractionModelObserver() override = default;
-
-  DISALLOW_COPY_AND_ASSIGN(AssistantInteractionModelObserver);
 };
 
 }  // namespace ash
diff --git a/ash/assistant/model/assistant_query_history.h b/ash/assistant/model/assistant_query_history.h
index a1eaafb9..f69a312 100644
--- a/ash/assistant/model/assistant_query_history.h
+++ b/ash/assistant/model/assistant_query_history.h
@@ -45,6 +45,10 @@
   };
 
   AssistantQueryHistory(int capacity = 100);
+
+  AssistantQueryHistory(const AssistantQueryHistory&) = delete;
+  AssistantQueryHistory& operator=(const AssistantQueryHistory&) = delete;
+
   ~AssistantQueryHistory();
 
   // Gets the iterator of query history.
@@ -56,8 +60,6 @@
  private:
   const int capacity_;
   base::circular_deque<std::string> queries_;
-
-  DISALLOW_COPY_AND_ASSIGN(AssistantQueryHistory);
 };
 
 }  // namespace ash
diff --git a/ash/assistant/model/assistant_response.h b/ash/assistant/model/assistant_response.h
index 1aa25c2d..b8181db 100644
--- a/ash/assistant/model/assistant_response.h
+++ b/ash/assistant/model/assistant_response.h
@@ -43,6 +43,9 @@
 
   AssistantResponse();
 
+  AssistantResponse(const AssistantResponse&) = delete;
+  AssistantResponse& operator=(const AssistantResponse&) = delete;
+
   // Adds/removes the specified |observer|.
   // NOTE: only the AssistantInteractionController is able to obtain non-const
   // access to an AssistantResponse through its owned model, but there are const
@@ -120,8 +123,6 @@
   mutable base::ObserverList<AssistantResponseObserver> observers_;
 
   base::WeakPtrFactory<AssistantResponse> weak_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(AssistantResponse);
 };
 
 }  // namespace ash
diff --git a/ash/assistant/model/assistant_screen_context_model_observer.h b/ash/assistant/model/assistant_screen_context_model_observer.h
index de8dfc5..7e82057 100644
--- a/ash/assistant/model/assistant_screen_context_model_observer.h
+++ b/ash/assistant/model/assistant_screen_context_model_observer.h
@@ -18,6 +18,11 @@
 class COMPONENT_EXPORT(ASSISTANT_MODEL) AssistantScreenContextModelObserver
     : public base::CheckedObserver {
  public:
+  AssistantScreenContextModelObserver(
+      const AssistantScreenContextModelObserver&) = delete;
+  AssistantScreenContextModelObserver& operator=(
+      const AssistantScreenContextModelObserver&) = delete;
+
   // Invoked when the screen context request state is changed.
   virtual void OnScreenContextRequestStateChanged(
       ScreenContextRequestState request_state) {}
@@ -25,8 +30,6 @@
  protected:
   AssistantScreenContextModelObserver() = default;
   ~AssistantScreenContextModelObserver() override = default;
-
-  DISALLOW_COPY_AND_ASSIGN(AssistantScreenContextModelObserver);
 };
 
 }  // namespace ash
diff --git a/ash/assistant/model/assistant_ui_model_observer.h b/ash/assistant/model/assistant_ui_model_observer.h
index 35ce9f1..6243ffa 100644
--- a/ash/assistant/model/assistant_ui_model_observer.h
+++ b/ash/assistant/model/assistant_ui_model_observer.h
@@ -31,6 +31,9 @@
   using AssistantEntryPoint = chromeos::assistant::AssistantEntryPoint;
   using AssistantExitPoint = chromeos::assistant::AssistantExitPoint;
 
+  AssistantUiModelObserver(const AssistantUiModelObserver&) = delete;
+  AssistantUiModelObserver& operator=(const AssistantUiModelObserver&) = delete;
+
   // Invoked when the UI mode is changed. If |due_to_interaction| is true, the
   // UI mode was changed as a result of an Assistant interaction.
   virtual void OnUiModeChanged(AssistantUiMode ui_mode,
@@ -53,8 +56,6 @@
  protected:
   AssistantUiModelObserver() = default;
   ~AssistantUiModelObserver() override = default;
-
-  DISALLOW_COPY_AND_ASSIGN(AssistantUiModelObserver);
 };
 
 }  // namespace ash
diff --git a/ash/capture_mode/capture_mode_controller.cc b/ash/capture_mode/capture_mode_controller.cc
index fec4231d8..4a51ab4 100644
--- a/ash/capture_mode/capture_mode_controller.cc
+++ b/ash/capture_mode/capture_mode_controller.cc
@@ -42,6 +42,8 @@
 #include "base/task/thread_pool.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/pref_service.h"
 #include "components/vector_icons/vector_icons.h"
 #include "components/viz/host/host_frame_sink_manager.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
@@ -88,6 +90,11 @@
 constexpr base::TimeDelta kResetCaptureRegionDuration =
     base::TimeDelta::FromMinutes(8);
 
+// The name of a file path pref for the user-selected custom path to which
+// captured images and videos should be saved.
+constexpr char kCustomCapturePathPrefName[] =
+    "ash.capture_mode.custom_save_path";
+
 // The screenshot notification button index.
 enum ScreenshotNotificationButtonIndex {
   BUTTON_EDIT = 0,
@@ -380,6 +387,12 @@
   return g_instance;
 }
 
+// static
+void CaptureModeController::RegisterProfilePrefs(PrefRegistrySimple* registry) {
+  registry->RegisterFilePathPref(kCustomCapturePathPrefName,
+                                 /*default_value=*/base::FilePath());
+}
+
 bool CaptureModeController::IsActive() const {
   return capture_mode_session_ && !capture_mode_session_->is_shutting_down();
 }
@@ -481,6 +494,45 @@
     last_capture_region_update_time_ = base::TimeTicks::Now();
 }
 
+void CaptureModeController::SetCustomCaptureFolder(const base::FilePath& path) {
+  DCHECK(Shell::Get()->session_controller()->IsActiveUserSessionStarted());
+
+  auto* pref_service =
+      Shell::Get()->session_controller()->GetActivePrefService();
+  DCHECK(pref_service);
+  pref_service->SetFilePath(kCustomCapturePathPrefName, path);
+
+  // TODO(https://crbug.com/1250885): Propagate the changes to the capture
+  // session (if any).
+}
+
+CaptureModeController::CaptureFolder
+CaptureModeController::GetCurrentCaptureFolder() const {
+  if (!Shell::Get()->session_controller()->IsActiveUserSessionStarted()) {
+    base::FilePath temp_dir;
+    if (!base::GetTempDir(&temp_dir))
+      LOG(ERROR) << "Failed to find the temporary directory.";
+    return {temp_dir, /*is_default_downloads_folder=*/false};
+  }
+
+  auto* pref_service =
+      Shell::Get()->session_controller()->GetActivePrefService();
+  const auto default_downloads_folder =
+      delegate_->GetUserDefaultDownloadsFolder();
+  if (pref_service) {
+    const auto custom_path =
+        pref_service->GetFilePath(kCustomCapturePathPrefName);
+    if (!custom_path.empty()) {
+      return {custom_path,
+              /*is_default_downloads_folder=*/custom_path ==
+                  default_downloads_folder};
+    }
+  }
+
+  return {default_downloads_folder,
+          /*is_default_downloads_folder=*/true};
+}
+
 void CaptureModeController::CaptureScreenshotsOfAllDisplays() {
   if (!delegate_->IsCaptureAllowedByPolicy()) {
     ShowDisabledNotification(CaptureAllowance::kDisallowedByPolicy);
@@ -1122,11 +1174,13 @@
 base::FilePath CaptureModeController::BuildPathNoExtension(
     const char* const format_string,
     base::Time timestamp) const {
-  const base::FilePath path = delegate_->GetScreenCaptureDir();
   base::Time::Exploded exploded_time;
   timestamp.LocalExplode(&exploded_time);
 
-  return path.AppendASCII(base::StringPrintf(
+  // TODO(https://crbug.com/1252156): The current path can become unavailable at
+  // any time before we get here. We need to handle the cases mentioned on the
+  // bug.
+  return GetCurrentCaptureFolder().path.AppendASCII(base::StringPrintf(
       format_string, GetDateStr(exploded_time).c_str(),
       GetTimeStr(exploded_time, delegate_->Uses24HourFormat()).c_str()));
 }
diff --git a/ash/capture_mode/capture_mode_controller.h b/ash/capture_mode/capture_mode_controller.h
index b153097d..3a40f57 100644
--- a/ash/capture_mode/capture_mode_controller.h
+++ b/ash/capture_mode/capture_mode_controller.h
@@ -15,6 +15,7 @@
 #include "ash/public/cpp/session/session_observer.h"
 #include "ash/services/recording/public/mojom/recording_service.mojom.h"
 #include "base/callback_forward.h"
+#include "base/files/file_path.h"
 #include "base/memory/ref_counted_memory.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/memory/weak_ptr.h"
@@ -27,6 +28,8 @@
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/image/image.h"
 
+class PrefRegistrySimple;
+
 namespace base {
 class FilePath;
 class Time;
@@ -44,6 +47,16 @@
       public SessionObserver,
       public chromeos::PowerManagerClient::Observer {
  public:
+  // Contains info about the folder used for saving the captured images and
+  // videos.
+  struct CaptureFolder {
+    // The absolute path of the folder used for saving the captures.
+    base::FilePath path;
+
+    // True if the above |path| is the default "Downloads" folder on the device.
+    bool is_default_downloads_folder = false;
+  };
+
   explicit CaptureModeController(std::unique_ptr<CaptureModeDelegate> delegate);
   CaptureModeController(const CaptureModeController&) = delete;
   CaptureModeController& operator=(const CaptureModeController&) = delete;
@@ -53,6 +66,8 @@
   // owned by Shell.
   static CaptureModeController* Get();
 
+  static void RegisterProfilePrefs(PrefRegistrySimple* registry);
+
   CaptureModeType type() const { return type_; }
   CaptureModeSource source() const { return source_; }
   CaptureModeSession* capture_mode_session() const {
@@ -88,6 +103,17 @@
   // update |last_capture_region_update_time_|.
   void SetUserCaptureRegion(const gfx::Rect& region, bool by_user);
 
+  // Sets the given |path| as the custom save location of captured images and
+  // videos for the currently logged in user (i.e. can only be called when user
+  // is logged in). Setting an empty |path| clears any custom selected folder
+  // resulting in using the default downloads folder.
+  void SetCustomCaptureFolder(const base::FilePath& path);
+
+  // Returns the folder in which all taken screenshots and videos will be saved.
+  // It can be the temp directory if the user is not logged in, the default
+  // "Downloads" folder, or a user-selected custom location.
+  CaptureFolder GetCurrentCaptureFolder() const;
+
   // Full screen capture for each available display if no restricted
   // content exists on that display, each capture is saved as an individual
   // file. Note: this won't start a capture mode session.
diff --git a/ash/capture_mode/capture_mode_unittests.cc b/ash/capture_mode/capture_mode_unittests.cc
index 338bf23c..93b888d 100644
--- a/ash/capture_mode/capture_mode_unittests.cc
+++ b/ash/capture_mode/capture_mode_unittests.cc
@@ -4001,6 +4001,64 @@
   EXPECT_TRUE(controller->enable_audio_recording());
 }
 
+TEST_F(CaptureModeTest, CaptureFolderSetting) {
+  auto* controller = CaptureModeController::Get();
+  auto* test_delegate = controller->delegate_for_testing();
+  const auto default_downloads_folder =
+      test_delegate->GetUserDefaultDownloadsFolder();
+
+  auto capture_folder = controller->GetCurrentCaptureFolder();
+  EXPECT_EQ(capture_folder.path, default_downloads_folder);
+  EXPECT_TRUE(capture_folder.is_default_downloads_folder);
+
+  const base::FilePath custom_folder(FILE_PATH_LITERAL("/home/tests"));
+  controller->SetCustomCaptureFolder(custom_folder);
+
+  capture_folder = controller->GetCurrentCaptureFolder();
+  EXPECT_EQ(capture_folder.path, custom_folder);
+  EXPECT_FALSE(capture_folder.is_default_downloads_folder);
+}
+
+TEST_F(CaptureModeTest, CaptureFolderSetToDefaultDownloads) {
+  auto* controller = CaptureModeController::Get();
+  auto* test_delegate = controller->delegate_for_testing();
+
+  const base::FilePath custom_folder(FILE_PATH_LITERAL("/home/tests"));
+  controller->SetCustomCaptureFolder(custom_folder);
+  auto capture_folder = controller->GetCurrentCaptureFolder();
+  EXPECT_FALSE(capture_folder.is_default_downloads_folder);
+
+  // If the user selects the default downloads folder manually, we should be
+  // able to detect that.
+  const auto default_downloads_folder =
+      test_delegate->GetUserDefaultDownloadsFolder();
+  controller->SetCustomCaptureFolder(default_downloads_folder);
+
+  capture_folder = controller->GetCurrentCaptureFolder();
+  EXPECT_EQ(capture_folder.path, default_downloads_folder);
+  EXPECT_TRUE(capture_folder.is_default_downloads_folder);
+}
+
+TEST_F(CaptureModeTest, CaptureFolderSetToEmptyPath) {
+  auto* controller = CaptureModeController::Get();
+  auto* test_delegate = controller->delegate_for_testing();
+
+  const base::FilePath custom_folder(FILE_PATH_LITERAL("/home/tests"));
+  controller->SetCustomCaptureFolder(custom_folder);
+  auto capture_folder = controller->GetCurrentCaptureFolder();
+  EXPECT_FALSE(capture_folder.is_default_downloads_folder);
+
+  // If we set the custom path to an empty folder to clear, we should revert
+  // back to the default downloads folder.
+  controller->SetCustomCaptureFolder(base::FilePath());
+
+  const auto default_downloads_folder =
+      test_delegate->GetUserDefaultDownloadsFolder();
+  capture_folder = controller->GetCurrentCaptureFolder();
+  EXPECT_EQ(capture_folder.path, default_downloads_folder);
+  EXPECT_TRUE(capture_folder.is_default_downloads_folder);
+}
+
 namespace {
 
 // -----------------------------------------------------------------------------
diff --git a/ash/capture_mode/test_capture_mode_delegate.cc b/ash/capture_mode/test_capture_mode_delegate.cc
index b442dce..e88b795 100644
--- a/ash/capture_mode/test_capture_mode_delegate.cc
+++ b/ash/capture_mode/test_capture_mode_delegate.cc
@@ -8,6 +8,8 @@
 #include "ash/public/cpp/capture_mode/recording_overlay_view.h"
 #include "ash/services/recording/public/mojom/recording_service.mojom.h"
 #include "ash/services/recording/recording_service_test_api.h"
+#include "ash/session/session_controller_impl.h"
+#include "ash/shell.h"
 #include "base/files/file_util.h"
 #include "base/threading/thread_restrictions.h"
 
@@ -61,7 +63,9 @@
   recording_service_->RequestAndWaitForVideoFrame();
 }
 
-base::FilePath TestCaptureModeDelegate::GetScreenCaptureDir() const {
+base::FilePath TestCaptureModeDelegate::GetUserDefaultDownloadsFolder() const {
+  DCHECK(Shell::Get()->session_controller()->IsActiveUserSessionStarted());
+
   return fake_downloads_dir_;
 }
 
diff --git a/ash/capture_mode/test_capture_mode_delegate.h b/ash/capture_mode/test_capture_mode_delegate.h
index 70255e3..519781a4 100644
--- a/ash/capture_mode/test_capture_mode_delegate.h
+++ b/ash/capture_mode/test_capture_mode_delegate.h
@@ -49,7 +49,7 @@
   void RequestAndWaitForVideoFrame();
 
   // CaptureModeDelegate:
-  base::FilePath GetScreenCaptureDir() const override;
+  base::FilePath GetUserDefaultDownloadsFolder() const override;
   void ShowScreenCaptureItemInFolder(const base::FilePath& file_path) override;
   void OpenScreenshotInImageEditor(const base::FilePath& file_path) override;
   bool Uses24HourFormat() const override;
diff --git a/ash/child_accounts/parent_access_controller_impl_unittest.cc b/ash/child_accounts/parent_access_controller_impl_unittest.cc
index 3ff0879..be716cd 100644
--- a/ash/child_accounts/parent_access_controller_impl_unittest.cc
+++ b/ash/child_accounts/parent_access_controller_impl_unittest.cc
@@ -33,6 +33,12 @@
 }
 
 class ParentAccessControllerImplTest : public LoginTestBase {
+ public:
+  ParentAccessControllerImplTest(const ParentAccessControllerImplTest&) =
+      delete;
+  ParentAccessControllerImplTest& operator=(
+      const ParentAccessControllerImplTest&) = delete;
+
  protected:
   ParentAccessControllerImplTest() : account_id_(GetChildAccountId()) {}
   ~ParentAccessControllerImplTest() override = default;
@@ -157,9 +163,6 @@
   base::HistogramTester histogram_tester_;
 
   PinRequestView* view_ = nullptr;  // Owned by test widget view hierarchy.
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ParentAccessControllerImplTest);
 };
 
 // Tests parent access dialog showing/hiding and focus behavior for parent
diff --git a/ash/components/audio/audio_devices_pref_handler_impl.h b/ash/components/audio/audio_devices_pref_handler_impl.h
index 1f51de3..da65359 100644
--- a/ash/components/audio/audio_devices_pref_handler_impl.h
+++ b/ash/components/audio/audio_devices_pref_handler_impl.h
@@ -28,6 +28,10 @@
   // |local_state| is the device-wide preference service.
   explicit AudioDevicesPrefHandlerImpl(PrefService* local_state);
 
+  AudioDevicesPrefHandlerImpl(const AudioDevicesPrefHandlerImpl&) = delete;
+  AudioDevicesPrefHandlerImpl& operator=(const AudioDevicesPrefHandlerImpl&) =
+      delete;
+
   // Overridden from AudioDevicesPrefHandler.
   double GetOutputVolumeValue(const AudioDevice* device) override;
   double GetInputGainValue(const AudioDevice* device) override;
@@ -120,8 +124,6 @@
 
   PrefChangeRegistrar pref_change_registrar_;
   base::ObserverList<AudioPrefObserver>::Unchecked observers_;
-
-  DISALLOW_COPY_AND_ASSIGN(AudioDevicesPrefHandlerImpl);
 };
 
 }  // namespace ash
diff --git a/ash/components/audio/audio_devices_pref_handler_stub.h b/ash/components/audio/audio_devices_pref_handler_stub.h
index 9b754c0d..ceea09a 100644
--- a/ash/components/audio/audio_devices_pref_handler_stub.h
+++ b/ash/components/audio/audio_devices_pref_handler_stub.h
@@ -30,6 +30,10 @@
 
   AudioDevicesPrefHandlerStub();
 
+  AudioDevicesPrefHandlerStub(const AudioDevicesPrefHandlerStub&) = delete;
+  AudioDevicesPrefHandlerStub& operator=(const AudioDevicesPrefHandlerStub&) =
+      delete;
+
   // AudioDevicesPrefHandler:
   double GetOutputVolumeValue(const AudioDevice* device) override;
   double GetInputGainValue(const AudioDevice* device) override;
@@ -58,8 +62,6 @@
   AudioDeviceStateMap audio_device_state_map_;
 
   bool noise_cancellation_state_ = true;
-
-  DISALLOW_COPY_AND_ASSIGN(AudioDevicesPrefHandlerStub);
 };
 
 }  // namespace ash
diff --git a/ash/components/audio/cras_audio_handler.h b/ash/components/audio/cras_audio_handler.h
index a617310..2a74f2f2 100644
--- a/ash/components/audio/cras_audio_handler.h
+++ b/ash/components/audio/cras_audio_handler.h
@@ -67,6 +67,9 @@
 
   class AudioObserver {
    public:
+    AudioObserver(const AudioObserver&) = delete;
+    AudioObserver& operator=(const AudioObserver&) = delete;
+
     // Called when an active output volume changed.
     virtual void OnOutputNodeVolumeChanged(uint64_t node_id, int volume);
 
@@ -119,7 +122,6 @@
    protected:
     AudioObserver();
     virtual ~AudioObserver();
-    DISALLOW_COPY_AND_ASSIGN(AudioObserver);
   };
 
   enum DeviceActivateType {
@@ -155,6 +157,9 @@
   // Gets the global instance. Initialize must be called first.
   static CrasAudioHandler* Get();
 
+  CrasAudioHandler(const CrasAudioHandler&) = delete;
+  CrasAudioHandler& operator=(const CrasAudioHandler&) = delete;
+
   // Overrides media::VideoCaptureObserver.
   void OnVideoCaptureStarted(media::VideoFacingMode facing) override;
   void OnVideoCaptureStopped(media::VideoFacingMode facing) override;
@@ -753,8 +758,6 @@
   cras::DisplayRotation display_rotation_ = cras::DisplayRotation::ROTATE_0;
 
   base::WeakPtrFactory<CrasAudioHandler> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(CrasAudioHandler);
 };
 
 // Helper class that will initialize the |CrasAudioHandler| for testing in its
diff --git a/ash/components/audio/cras_audio_handler_unittest.cc b/ash/components/audio/cras_audio_handler_unittest.cc
index 11b636d8..f33936e 100644
--- a/ash/components/audio/cras_audio_handler_unittest.cc
+++ b/ash/components/audio/cras_audio_handler_unittest.cc
@@ -42,6 +42,10 @@
  public:
   FakeMediaControllerManager() = default;
 
+  FakeMediaControllerManager(const FakeMediaControllerManager&) = delete;
+  FakeMediaControllerManager& operator=(const FakeMediaControllerManager&) =
+      delete;
+
   mojo::PendingRemote<media_session::mojom::MediaControllerManager>
   MakeRemote() {
     mojo::PendingRemote<media_session::mojom::MediaControllerManager> remote;
@@ -63,8 +67,6 @@
   }
 
   mojo::ReceiverSet<media_session::mojom::MediaControllerManager> receivers_;
-
-  DISALLOW_COPY_AND_ASSIGN(FakeMediaControllerManager);
 };
 
 const uint64_t kInternalSpeakerId = 10001;
@@ -509,6 +511,9 @@
       : cras_audio_handler_test_(cras_audio_handler_test),
         grace_period_duration_in_ms_(grace_period_duration_in_ms) {}
 
+  HDMIRediscoverWaiter(const HDMIRediscoverWaiter&) = delete;
+  HDMIRediscoverWaiter& operator=(const HDMIRediscoverWaiter&) = delete;
+
   void WaitUntilTimeOut(int wait_duration_in_ms) {
     base::RunLoop run_loop;
     base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
@@ -538,8 +543,6 @@
  private:
   CrasAudioHandlerTest* cras_audio_handler_test_;  // not owned
   int grace_period_duration_in_ms_;
-
-  DISALLOW_COPY_AND_ASSIGN(HDMIRediscoverWaiter);
 };
 
 INSTANTIATE_TEST_SUITE_P(StableIdV1, CrasAudioHandlerTest, testing::Values(1));
diff --git a/ash/components/drivefs/drivefs_auth_unittest.cc b/ash/components/drivefs/drivefs_auth_unittest.cc
index 0df996e..f43336ef 100644
--- a/ash/components/drivefs/drivefs_auth_unittest.cc
+++ b/ash/components/drivefs/drivefs_auth_unittest.cc
@@ -65,6 +65,9 @@
  public:
   DriveFsAuthTest() = default;
 
+  DriveFsAuthTest(const DriveFsAuthTest&) = delete;
+  DriveFsAuthTest& operator=(const DriveFsAuthTest&) = delete;
+
  protected:
   void SetUp() override {
     clock_.SetNow(base::Time::Now());
@@ -104,9 +107,6 @@
   std::unique_ptr<AuthDelegateImpl> delegate_;
   std::unique_ptr<DriveFsAuth> auth_;
   base::MockOneShotTimer* timer_ = nullptr;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(DriveFsAuthTest);
 };
 
 TEST_F(DriveFsAuthTest, GetAccessToken_Success) {
diff --git a/ash/components/drivefs/drivefs_bootstrap_unittest.cc b/ash/components/drivefs/drivefs_bootstrap_unittest.cc
index 94b8c2c..7451256 100644
--- a/ash/components/drivefs/drivefs_bootstrap_unittest.cc
+++ b/ash/components/drivefs/drivefs_bootstrap_unittest.cc
@@ -47,6 +47,11 @@
       mojo::PendingRemote<mojom::DriveFsBootstrap> available_bootstrap)
       : available_bootstrap_(std::move(available_bootstrap)) {}
 
+  DriveFsBootstrapListenerForTest(const DriveFsBootstrapListenerForTest&) =
+      delete;
+  DriveFsBootstrapListenerForTest& operator=(
+      const DriveFsBootstrapListenerForTest&) = delete;
+
   mojo::PendingRemote<mojom::DriveFsBootstrap> bootstrap() override {
     return std::move(available_bootstrap_);
   }
@@ -55,8 +60,6 @@
 
  private:
   mojo::PendingRemote<mojom::DriveFsBootstrap> available_bootstrap_;
-
-  DISALLOW_COPY_AND_ASSIGN(DriveFsBootstrapListenerForTest);
 };
 
 class DriveFsBootstrapTest : public testing::Test,
@@ -64,6 +67,9 @@
  public:
   DriveFsBootstrapTest() = default;
 
+  DriveFsBootstrapTest(const DriveFsBootstrapTest&) = delete;
+  DriveFsBootstrapTest& operator=(const DriveFsBootstrapTest&) = delete;
+
  protected:
   MOCK_CONST_METHOD0(OnDisconnect, void());
   MOCK_CONST_METHOD0(OnInit, void());
@@ -108,8 +114,6 @@
   mojo::Remote<mojom::DriveFsDelegate> delegate_;
   mojo::PendingReceiver<mojom::DriveFsDelegate> pending_delegate_receiver_;
   std::string email_;
-
-  DISALLOW_COPY_AND_ASSIGN(DriveFsBootstrapTest);
 };
 
 }  // namespace
diff --git a/ash/components/drivefs/drivefs_host_unittest.cc b/ash/components/drivefs/drivefs_host_unittest.cc
index 05b5602..1f306bdd 100644
--- a/ash/components/drivefs/drivefs_host_unittest.cc
+++ b/ash/components/drivefs/drivefs_host_unittest.cc
@@ -202,6 +202,9 @@
     clock_.SetNow(base::Time::Now());
   }
 
+  DriveFsHostTest(const DriveFsHostTest&) = delete;
+  DriveFsHostTest& operator=(const DriveFsHostTest&) = delete;
+
  protected:
   void SetUp() override {
     testing::Test::SetUp();
@@ -344,9 +347,6 @@
   mojo::PendingReceiver<mojom::DriveFsDelegate> pending_delegate_receiver_;
   std::string token_;
   absl::optional<std::string> init_access_token_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(DriveFsHostTest);
 };
 
 TEST_F(DriveFsHostTest, Basic) {
diff --git a/ash/components/drivefs/drivefs_search_unittest.cc b/ash/components/drivefs/drivefs_search_unittest.cc
index b2ca00f1f..844906f 100644
--- a/ash/components/drivefs/drivefs_search_unittest.cc
+++ b/ash/components/drivefs/drivefs_search_unittest.cc
@@ -28,6 +28,9 @@
  public:
   MockDriveFs() = default;
 
+  MockDriveFs(const MockDriveFs&) = delete;
+  MockDriveFs& operator=(const MockDriveFs&) = delete;
+
   DriveFs* GetForwardingInterface() override {
     NOTREACHED();
     return nullptr;
@@ -53,7 +56,6 @@
 
  private:
   mojo::Receiver<mojom::SearchQuery> search_receiver_{this};
-  DISALLOW_COPY_AND_ASSIGN(MockDriveFs);
 };
 
 class DriveFsSearchTest : public testing::Test {
diff --git a/ash/components/drivefs/drivefs_session_unittest.cc b/ash/components/drivefs/drivefs_session_unittest.cc
index 8e183a62..c88dbc8c 100644
--- a/ash/components/drivefs/drivefs_session_unittest.cc
+++ b/ash/components/drivefs/drivefs_session_unittest.cc
@@ -286,6 +286,9 @@
  public:
   DriveFsSessionTest() {}
 
+  DriveFsSessionTest(const DriveFsSessionTest&) = delete;
+  DriveFsSessionTest& operator=(const DriveFsSessionTest&) = delete;
+
  protected:
   MOCK_METHOD1(OnMounted, void(const base::FilePath& path));
   MOCK_METHOD1(OnUnmounted, void(absl::optional<base::TimeDelta> delay));
@@ -344,9 +347,6 @@
   base::MockOneShotTimer timer_;
   std::unique_ptr<PointerHolder> holder_;
   std::unique_ptr<DriveFsSession> session_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(DriveFsSessionTest);
 };
 
 }  // namespace
diff --git a/ash/components/drivefs/fake_drivefs.cc b/ash/components/drivefs/fake_drivefs.cc
index 9610f7a1..77dec10 100644
--- a/ash/components/drivefs/fake_drivefs.cc
+++ b/ash/components/drivefs/fake_drivefs.cc
@@ -107,6 +107,9 @@
               drivefs::mojom::QueryParametersPtr params)
       : drive_fs_(std::move(drive_fs)), params_(std::move(params)) {}
 
+  SearchQuery(const SearchQuery&) = delete;
+  SearchQuery& operator=(const SearchQuery&) = delete;
+
  private:
   void GetNextPage(GetNextPageCallback callback) override {
     if (!drive_fs_) {
@@ -234,8 +237,6 @@
   size_t pending_callbacks_ = 0;
 
   base::WeakPtrFactory<SearchQuery> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(SearchQuery);
 };
 
 FakeDriveFs::FakeDriveFs(const base::FilePath& mount_path)
diff --git a/ash/components/drivefs/fake_drivefs_launcher_client.h b/ash/components/drivefs/fake_drivefs_launcher_client.h
index fb48e19..29054ed 100644
--- a/ash/components/drivefs/fake_drivefs_launcher_client.h
+++ b/ash/components/drivefs/fake_drivefs_launcher_client.h
@@ -20,6 +20,10 @@
   static void Init(const base::FilePath& socket_path,
                    const base::FilePath& chroot_path);
 
+  FakeDriveFsLauncherClient(const FakeDriveFsLauncherClient&) = delete;
+  FakeDriveFsLauncherClient& operator=(const FakeDriveFsLauncherClient&) =
+      delete;
+
  private:
   friend class base::NoDestructor<FakeDriveFsLauncherClient>;
 
@@ -35,8 +39,6 @@
   const base::FilePath socket_path_;
 
   mojo::Remote<mojom::FakeDriveFsLauncher> launcher_;
-
-  DISALLOW_COPY_AND_ASSIGN(FakeDriveFsLauncherClient);
 };
 
 }  // namespace drivefs
diff --git a/ash/display/cros_display_config_unittest.cc b/ash/display/cros_display_config_unittest.cc
index a77a99b3..80a4451 100644
--- a/ash/display/cros_display_config_unittest.cc
+++ b/ash/display/cros_display_config_unittest.cc
@@ -63,6 +63,9 @@
  public:
   TestObserver() = default;
 
+  TestObserver(const TestObserver&) = delete;
+  TestObserver& operator=(const TestObserver&) = delete;
+
   // mojom::CrosDisplayConfigObserver:
   void OnDisplayConfigChanged() override { display_changes_++; }
 
@@ -71,8 +74,6 @@
 
  private:
   int display_changes_ = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(TestObserver);
 };
 
 }  // namespace
diff --git a/ash/display/cursor_window_controller.h b/ash/display/cursor_window_controller.h
index f936676..63c7ba79 100644
--- a/ash/display/cursor_window_controller.h
+++ b/ash/display/cursor_window_controller.h
@@ -44,6 +44,10 @@
   };
 
   CursorWindowController();
+
+  CursorWindowController(const CursorWindowController&) = delete;
+  CursorWindowController& operator=(const CursorWindowController&) = delete;
+
   ~CursorWindowController();
 
   bool is_cursor_compositing_enabled() const {
@@ -137,8 +141,6 @@
   views::UniqueWidgetPtr cursor_view_widget_;
 
   const bool is_cursor_motion_blur_enabled_;
-
-  DISALLOW_COPY_AND_ASSIGN(CursorWindowController);
 };
 
 }  // namespace ash
diff --git a/ash/display/display_animator.cc b/ash/display/display_animator.cc
index 5c0a17ae..e6545f13 100644
--- a/ash/display/display_animator.cc
+++ b/ash/display/display_animator.cc
@@ -35,6 +35,9 @@
         animation_aborted_(false),
         callback_(std::move(callback)) {}
 
+  CallbackRunningObserver(const CallbackRunningObserver&) = delete;
+  CallbackRunningObserver& operator=(const CallbackRunningObserver&) = delete;
+
   void AddNewAnimator(ui::LayerAnimator* animator) {
     auto observer = std::make_unique<Observer>(animator, this);
     animator->AddObserver(observer.get());
@@ -63,6 +66,9 @@
     Observer(ui::LayerAnimator* animator, CallbackRunningObserver* observer)
         : animator_(animator), observer_(observer) {}
 
+    Observer(const Observer&) = delete;
+    Observer& operator=(const Observer&) = delete;
+
    protected:
     // ui::LayerAnimationObserver overrides:
     void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) override {
@@ -83,16 +89,12 @@
    private:
     ui::LayerAnimator* animator_;
     CallbackRunningObserver* observer_;
-
-    DISALLOW_COPY_AND_ASSIGN(Observer);
   };
 
   size_t completed_counter_;
   bool animation_aborted_;
   std::vector<std::unique_ptr<Observer>> observer_list_;
   base::OnceClosure callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(CallbackRunningObserver);
 };
 
 }  // namespace
diff --git a/ash/display/display_color_manager_unittest.cc b/ash/display/display_color_manager_unittest.cc
index 6c9b9a5..2a88874 100644
--- a/ash/display/display_color_manager_unittest.cc
+++ b/ash/display/display_color_manager_unittest.cc
@@ -39,6 +39,10 @@
       display::DisplayConfigurator* configurator)
       : DisplayColorManager(configurator) {}
 
+  DisplayColorManagerForTest(const DisplayColorManagerForTest&) = delete;
+  DisplayColorManagerForTest& operator=(const DisplayColorManagerForTest&) =
+      delete;
+
   void SetOnFinishedForTest(base::OnceClosure on_finished_for_test) {
     on_finished_for_test_ = std::move(on_finished_for_test);
   }
@@ -73,8 +77,6 @@
   }
 
   base::OnceClosure on_finished_for_test_;
-
-  DISALLOW_COPY_AND_ASSIGN(DisplayColorManagerForTest);
 };
 
 // Implementation of QuirksManager::Delegate to fake chrome-restricted parts.
@@ -83,6 +85,10 @@
   QuirksManagerDelegateTestImpl(base::FilePath color_path)
       : color_path_(color_path) {}
 
+  QuirksManagerDelegateTestImpl(const QuirksManagerDelegateTestImpl&) = delete;
+  QuirksManagerDelegateTestImpl& operator=(
+      const QuirksManagerDelegateTestImpl&) = delete;
+
   // Unused by these tests.
   std::string GetApiKey() const override { return std::string(); }
 
@@ -96,8 +102,6 @@
   ~QuirksManagerDelegateTestImpl() override = default;
 
   base::FilePath color_path_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuirksManagerDelegateTestImpl);
 };
 
 }  // namespace
diff --git a/ash/display/display_configuration_controller.cc b/ash/display/display_configuration_controller.cc
index 7d41f6dd..3b3b0711 100644
--- a/ash/display/display_configuration_controller.cc
+++ b/ash/display/display_configuration_controller.cc
@@ -64,6 +64,9 @@
  public:
   DisplayChangeLimiter() : throttle_timeout_(base::Time::Now()) {}
 
+  DisplayChangeLimiter(const DisplayChangeLimiter&) = delete;
+  DisplayChangeLimiter& operator=(const DisplayChangeLimiter&) = delete;
+
   void SetThrottleTimeout(int64_t throttle_ms) {
     throttle_timeout_ =
         base::Time::Now() + base::TimeDelta::FromMilliseconds(throttle_ms);
@@ -73,8 +76,6 @@
 
  private:
   base::Time throttle_timeout_;
-
-  DISALLOW_COPY_AND_ASSIGN(DisplayChangeLimiter);
 };
 
 // static
diff --git a/ash/display/display_configuration_controller_test_api.h b/ash/display/display_configuration_controller_test_api.h
index 0a4e6f48..9f888fc 100644
--- a/ash/display/display_configuration_controller_test_api.h
+++ b/ash/display/display_configuration_controller_test_api.h
@@ -21,6 +21,11 @@
   explicit DisplayConfigurationControllerTestApi(
       DisplayConfigurationController* controller);
 
+  DisplayConfigurationControllerTestApi(
+      const DisplayConfigurationControllerTestApi&) = delete;
+  DisplayConfigurationControllerTestApi& operator=(
+      const DisplayConfigurationControllerTestApi&) = delete;
+
   // Wrapper functions for DisplayConfigurationController.
   void SetDisplayAnimator(bool enable);
   ScreenRotationAnimator* GetScreenRotationAnimatorForDisplay(
@@ -32,8 +37,6 @@
 
  private:
   DisplayConfigurationController* controller_;
-
-  DISALLOW_COPY_AND_ASSIGN(DisplayConfigurationControllerTestApi);
 };
 
 }  // namespace ash
diff --git a/ash/display/display_error_observer_unittest.cc b/ash/display/display_error_observer_unittest.cc
index e693b12..cf5aaf5 100644
--- a/ash/display/display_error_observer_unittest.cc
+++ b/ash/display/display_error_observer_unittest.cc
@@ -19,6 +19,10 @@
 namespace ash {
 
 class DisplayErrorObserverTest : public AshTestBase {
+ public:
+  DisplayErrorObserverTest(const DisplayErrorObserverTest&) = delete;
+  DisplayErrorObserverTest& operator=(const DisplayErrorObserverTest&) = delete;
+
  protected:
   DisplayErrorObserverTest() = default;
 
@@ -38,8 +42,6 @@
 
  private:
   std::unique_ptr<DisplayErrorObserver> observer_;
-
-  DISALLOW_COPY_AND_ASSIGN(DisplayErrorObserverTest);
 };
 
 TEST_F(DisplayErrorObserverTest, Normal) {
diff --git a/ash/display/display_prefs_unittest.cc b/ash/display/display_prefs_unittest.cc
index 2ec2eb0..82df615 100644
--- a/ash/display/display_prefs_unittest.cc
+++ b/ash/display/display_prefs_unittest.cc
@@ -111,6 +111,10 @@
 }  // namespace
 
 class DisplayPrefsTest : public AshTestBase {
+ public:
+  DisplayPrefsTest(const DisplayPrefsTest&) = delete;
+  DisplayPrefsTest& operator=(const DisplayPrefsTest&) = delete;
+
  protected:
   DisplayPrefsTest() = default;
   ~DisplayPrefsTest() override = default;
@@ -240,16 +244,14 @@
  private:
   std::unique_ptr<WindowTreeHostManager::Observer> observer_;
   base::test::ScopedFeatureList scoped_feature_list_;
-
-  DISALLOW_COPY_AND_ASSIGN(DisplayPrefsTest);
 };
 
 class DisplayPrefsTestGuest : public DisplayPrefsTest {
  public:
   DisplayPrefsTestGuest() { set_start_session(false); }
 
- private:
-  DISALLOW_COPY_AND_ASSIGN(DisplayPrefsTestGuest);
+  DisplayPrefsTestGuest(const DisplayPrefsTestGuest&) = delete;
+  DisplayPrefsTestGuest& operator=(const DisplayPrefsTestGuest&) = delete;
 };
 
 TEST_F(DisplayPrefsTest, ListedLayoutOverrides) {
diff --git a/ash/display/mirror_window_controller.cc b/ash/display/mirror_window_controller.cc
index 4bbba73..94a10a8 100644
--- a/ash/display/mirror_window_controller.cc
+++ b/ash/display/mirror_window_controller.cc
@@ -45,6 +45,10 @@
   explicit MirroringScreenPositionClient(MirrorWindowController* controller)
       : controller_(controller) {}
 
+  MirroringScreenPositionClient(const MirroringScreenPositionClient&) = delete;
+  MirroringScreenPositionClient& operator=(
+      const MirroringScreenPositionClient&) = delete;
+
   // aura::client::ScreenPositionClient:
   void ConvertPointToScreen(const aura::Window* window,
                             gfx::PointF* point) override {
@@ -93,8 +97,6 @@
 
  private:
   MirrorWindowController* controller_;  // not owned.
-
-  DISALLOW_COPY_AND_ASSIGN(MirroringScreenPositionClient);
 };
 
 // A trivial CaptureClient that does nothing. That is, calls to set/release
diff --git a/ash/display/null_mouse_warp_controller.h b/ash/display/null_mouse_warp_controller.h
index 85ff488e..1e81194 100644
--- a/ash/display/null_mouse_warp_controller.h
+++ b/ash/display/null_mouse_warp_controller.h
@@ -17,12 +17,12 @@
  public:
   NullMouseWarpController() {}
 
+  NullMouseWarpController(const NullMouseWarpController&) = delete;
+  NullMouseWarpController& operator=(const NullMouseWarpController&) = delete;
+
   // MouseWarpController:
   bool WarpMouseCursor(ui::MouseEvent* event) override;
   void SetEnabled(bool enable) override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(NullMouseWarpController);
 };
 
 }  // namespace ash
diff --git a/ash/display/resolution_notification_controller.cc b/ash/display/resolution_notification_controller.cc
index af5be2317..177e389 100644
--- a/ash/display/resolution_notification_controller.cc
+++ b/ash/display/resolution_notification_controller.cc
@@ -29,6 +29,10 @@
                        const display::ManagedDisplayMode& old_resolution,
                        const display::ManagedDisplayMode& new_resolution,
                        base::OnceClosure accept_callback);
+
+  ResolutionChangeInfo(const ResolutionChangeInfo&) = delete;
+  ResolutionChangeInfo& operator=(const ResolutionChangeInfo&) = delete;
+
   ~ResolutionChangeInfo();
 
   // The id of the display where the resolution change happens.
@@ -46,9 +50,6 @@
 
   // The callback when accept is chosen.
   base::OnceClosure accept_callback;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ResolutionChangeInfo);
 };
 
 ResolutionNotificationController::ResolutionChangeInfo::ResolutionChangeInfo(
diff --git a/ash/display/root_window_transformers.cc b/ash/display/root_window_transformers.cc
index 3e5fe4fc..5842a978 100644
--- a/ash/display/root_window_transformers.cc
+++ b/ash/display/root_window_transformers.cc
@@ -123,6 +123,9 @@
     initial_host_size_ = info.bounds_in_native().size();
   }
 
+  AshRootWindowTransformer(const AshRootWindowTransformer&) = delete;
+  AshRootWindowTransformer& operator=(const AshRootWindowTransformer&) = delete;
+
   // aura::RootWindowTransformer overrides:
   gfx::Transform GetTransform() const override { return transform_; }
   gfx::Transform GetInverseTransform() const override {
@@ -186,8 +189,6 @@
   gfx::Transform insets_and_scale_transform_;
   gfx::Rect initial_root_bounds_;
   gfx::Size initial_host_size_;
-
-  DISALLOW_COPY_AND_ASSIGN(AshRootWindowTransformer);
 };
 
 // RootWindowTransformer for mirror root window. We simply copy the
@@ -265,6 +266,10 @@
     }
   }
 
+  MirrorRootWindowTransformer(const MirrorRootWindowTransformer&) = delete;
+  MirrorRootWindowTransformer& operator=(const MirrorRootWindowTransformer&) =
+      delete;
+
   // aura::RootWindowTransformer overrides:
   gfx::Transform GetTransform() const override { return transform_; }
   gfx::Transform GetInverseTransform() const override {
@@ -286,8 +291,6 @@
   gfx::Transform transform_;
   gfx::Rect root_bounds_;
   gfx::Insets insets_;
-
-  DISALLOW_COPY_AND_ASSIGN(MirrorRootWindowTransformer);
 };
 
 class PartialBoundsRootWindowTransformer : public RootWindowTransformer {
@@ -326,6 +329,11 @@
                          -SkIntToScalar(display.bounds().y()));
   }
 
+  PartialBoundsRootWindowTransformer(
+      const PartialBoundsRootWindowTransformer&) = delete;
+  PartialBoundsRootWindowTransformer& operator=(
+      const PartialBoundsRootWindowTransformer&) = delete;
+
   // RootWindowTransformer:
   gfx::Transform GetTransform() const override { return transform_; }
   gfx::Transform GetInverseTransform() const override {
@@ -344,8 +352,6 @@
  private:
   gfx::Transform transform_;
   gfx::Rect root_bounds_;
-
-  DISALLOW_COPY_AND_ASSIGN(PartialBoundsRootWindowTransformer);
 };
 
 }  // namespace
diff --git a/ash/display/screen_ash.cc b/ash/display/screen_ash.cc
index 0cb59f8..6400703a 100644
--- a/ash/display/screen_ash.cc
+++ b/ash/display/screen_ash.cc
@@ -44,6 +44,9 @@
     SetDisplayForNewWindows(primary_display_.id());
   }
 
+  ScreenForShutdown(const ScreenForShutdown&) = delete;
+  ScreenForShutdown& operator=(const ScreenForShutdown&) = delete;
+
   // display::Screen overrides:
   gfx::Point GetCursorScreenPoint() override { return gfx::Point(); }
   bool IsWindowUnderCursor(gfx::NativeWindow window) override { return false; }
@@ -85,8 +88,6 @@
  private:
   const std::vector<display::Display> display_list_;
   const display::Display primary_display_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScreenForShutdown);
 };
 
 }  // namespace
diff --git a/ash/display/screen_orientation_controller.h b/ash/display/screen_orientation_controller.h
index 9eab587..0d3883a 100644
--- a/ash/display/screen_orientation_controller.h
+++ b/ash/display/screen_orientation_controller.h
@@ -70,6 +70,11 @@
   };
 
   ScreenOrientationController();
+
+  ScreenOrientationController(const ScreenOrientationController&) = delete;
+  ScreenOrientationController& operator=(const ScreenOrientationController&) =
+      delete;
+
   ~ScreenOrientationController() override;
 
   OrientationLockType natural_orientation() const {
@@ -283,8 +288,6 @@
 
   // Register for DisplayObserver callbacks.
   display::ScopedDisplayObserver display_observer_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(ScreenOrientationController);
 };
 
 }  // namespace ash
diff --git a/ash/display/screen_orientation_controller_test_api.h b/ash/display/screen_orientation_controller_test_api.h
index 9856ca5..f2ffda8 100644
--- a/ash/display/screen_orientation_controller_test_api.h
+++ b/ash/display/screen_orientation_controller_test_api.h
@@ -19,6 +19,11 @@
   explicit ScreenOrientationControllerTestApi(
       ScreenOrientationController* controller);
 
+  ScreenOrientationControllerTestApi(
+      const ScreenOrientationControllerTestApi&) = delete;
+  ScreenOrientationControllerTestApi& operator=(
+      const ScreenOrientationControllerTestApi&) = delete;
+
   void SetDisplayRotation(
       display::Display::Rotation rotation,
       display::Display::RotationSource source,
@@ -37,8 +42,6 @@
 
  private:
   ScreenOrientationController* controller_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScreenOrientationControllerTestApi);
 };
 
 }  // namespace ash
diff --git a/ash/display/touch_calibrator_controller_unittest.cc b/ash/display/touch_calibrator_controller_unittest.cc
index d407569c..3fc6b30b 100644
--- a/ash/display/touch_calibrator_controller_unittest.cc
+++ b/ash/display/touch_calibrator_controller_unittest.cc
@@ -48,6 +48,10 @@
  public:
   TouchCalibratorControllerTest() = default;
 
+  TouchCalibratorControllerTest(const TouchCalibratorControllerTest&) = delete;
+  TouchCalibratorControllerTest& operator=(
+      const TouchCalibratorControllerTest&) = delete;
+
   void TearDown() override {
     // Reset all touch device and touch association.
     display::test::TouchDeviceManagerTestApi(touch_device_manager())
@@ -183,9 +187,6 @@
         ->ConfigureTouchDevices(transforms);
     return touchdevice;
   }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(TouchCalibratorControllerTest);
 };
 
 TEST_F(TouchCalibratorControllerTest, StartCalibration) {
diff --git a/ash/display/window_tree_host_manager.cc b/ash/display/window_tree_host_manager.cc
index 63f0305..f6690bc 100644
--- a/ash/display/window_tree_host_manager.cc
+++ b/ash/display/window_tree_host_manager.cc
@@ -161,6 +161,9 @@
         focused_(nullptr),
         active_(nullptr) {}
 
+  FocusActivationStore(const FocusActivationStore&) = delete;
+  FocusActivationStore& operator=(const FocusActivationStore&) = delete;
+
   void Store(bool clear_focus) {
     if (!activation_client_) {
       aura::Window* root = Shell::GetPrimaryRootWindow();
@@ -214,8 +217,6 @@
   aura::WindowTracker tracker_;
   aura::Window* focused_;
   aura::Window* active_;
-
-  DISALLOW_COPY_AND_ASSIGN(FocusActivationStore);
 };
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/ash/display/window_tree_host_manager_unittest.cc b/ash/display/window_tree_host_manager_unittest.cc
index 037d0cc..21efd6dc 100644
--- a/ash/display/window_tree_host_manager_unittest.cc
+++ b/ash/display/window_tree_host_manager_unittest.cc
@@ -347,11 +347,12 @@
  public:
   TestMouseWatcherListener() = default;
 
+  TestMouseWatcherListener(const TestMouseWatcherListener&) = delete;
+  TestMouseWatcherListener& operator=(const TestMouseWatcherListener&) = delete;
+
  private:
   // views::MouseWatcherListener:
   void MouseMovedOutOfHost() override {}
-
-  DISALLOW_COPY_AND_ASSIGN(TestMouseWatcherListener);
 };
 
 }  // namespace
diff --git a/ash/drag_drop/drag_drop_controller_unittest.cc b/ash/drag_drop/drag_drop_controller_unittest.cc
index 13a19965..5e13f6e 100644
--- a/ash/drag_drop/drag_drop_controller_unittest.cc
+++ b/ash/drag_drop/drag_drop_controller_unittest.cc
@@ -66,6 +66,9 @@
  public:
   DragTestView() : views::View() { Reset(); }
 
+  DragTestView(const DragTestView&) = delete;
+  DragTestView& operator=(const DragTestView&) = delete;
+
   void Reset() {
     num_drag_enters_ = 0;
     num_drag_exits_ = 0;
@@ -149,8 +152,6 @@
     num_drops_++;
     output_drag_op = DragOperation::kCopy;
   }
-
-  DISALLOW_COPY_AND_ASSIGN(DragTestView);
 };
 
 class CompletableLinearAnimation : public gfx::LinearAnimation {
@@ -160,16 +161,20 @@
                              gfx::AnimationDelegate* delegate)
       : gfx::LinearAnimation(duration, frame_rate, delegate) {}
 
-  void Complete() { Step(start_time() + duration()); }
+  CompletableLinearAnimation(const CompletableLinearAnimation&) = delete;
+  CompletableLinearAnimation& operator=(const CompletableLinearAnimation&) =
+      delete;
 
- private:
-  DISALLOW_COPY_AND_ASSIGN(CompletableLinearAnimation);
+  void Complete() { Step(start_time() + duration()); }
 };
 
 class TestDragDropController : public DragDropController {
  public:
   TestDragDropController() : DragDropController() { Reset(); }
 
+  TestDragDropController(const TestDragDropController&) = delete;
+  TestDragDropController& operator=(const TestDragDropController&) = delete;
+
   void Reset() {
     drag_start_received_ = false;
     num_drag_updates_ = 0;
@@ -224,9 +229,6 @@
   bool drop_received_;
   bool drag_canceled_;
   std::u16string drag_string_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(TestDragDropController);
 };
 
 class MockObserver : public aura::client::DragDropClientObserver {
@@ -244,6 +246,9 @@
 
   TestObserver() : state_(State::kNotInvoked) {}
 
+  TestObserver(const TestObserver&) = delete;
+  TestObserver& operator=(const TestObserver&) = delete;
+
   State state() const { return state_; }
 
   // aura::client::DragDropClientObserver
@@ -260,8 +265,6 @@
 
  private:
   State state_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestObserver);
 };
 
 class EventTargetTestDelegate : public aura::client::DragDropDelegate {
@@ -275,6 +278,10 @@
   };
 
   explicit EventTargetTestDelegate(aura::Window* window) : window_(window) {}
+
+  EventTargetTestDelegate(const EventTargetTestDelegate&) = delete;
+  EventTargetTestDelegate& operator=(const EventTargetTestDelegate&) = delete;
+
   State state() const { return state_; }
 
   // aura::client::DragDropDelegate:
@@ -325,8 +332,6 @@
 
   aura::Window* const window_;
   State state_{State::kNotInvoked};
-
-  DISALLOW_COPY_AND_ASSIGN(EventTargetTestDelegate);
 };
 
 void AddViewToWidgetAndResize(views::Widget* widget, views::View* view) {
diff --git a/ash/fast_ink/laser/laser_pointer_view.cc b/ash/fast_ink/laser/laser_pointer_view.cc
index 8e5a6185..2c8b57a 100644
--- a/ash/fast_ink/laser/laser_pointer_view.cc
+++ b/ash/fast_ink/laser/laser_pointer_view.cc
@@ -146,14 +146,15 @@
     path_points_.push_back(ordered_points[3]);
   }
 
+  LaserSegment(const LaserSegment&) = delete;
+  LaserSegment& operator=(const LaserSegment&) = delete;
+
   SkPath path() const { return path_; }
   std::vector<gfx::PointF> path_points() const { return path_points_; }
 
  private:
   SkPath path_;
   std::vector<gfx::PointF> path_points_;
-
-  DISALLOW_COPY_AND_ASSIGN(LaserSegment);
 };
 
 // LaserPointerView
diff --git a/ash/focus_cycler_unittest.cc b/ash/focus_cycler_unittest.cc
index 241c0cc..eff9fec 100644
--- a/ash/focus_cycler_unittest.cc
+++ b/ash/focus_cycler_unittest.cc
@@ -60,6 +60,9 @@
  public:
   FocusCyclerTest() = default;
 
+  FocusCyclerTest(const FocusCyclerTest&) = delete;
+  FocusCyclerTest& operator=(const FocusCyclerTest&) = delete;
+
   void SetUp() override {
     AshTestBase::SetUp();
 
@@ -100,8 +103,6 @@
 
  private:
   std::unique_ptr<FocusCycler> focus_cycler_;
-
-  DISALLOW_COPY_AND_ASSIGN(FocusCyclerTest);
 };
 
 TEST_F(FocusCyclerTest, CycleFocusBrowserOnly) {
diff --git a/ash/highlighter/highlighter_controller.h b/ash/highlighter/highlighter_controller.h
index 23bdff7..4a685aa 100644
--- a/ash/highlighter/highlighter_controller.h
+++ b/ash/highlighter/highlighter_controller.h
@@ -61,6 +61,10 @@
   };
 
   HighlighterController();
+
+  HighlighterController(const HighlighterController&) = delete;
+  HighlighterController& operator=(const HighlighterController&) = delete;
+
   ~HighlighterController() override;
 
   HighlighterEnabledState enabled_state() { return enabled_state_; }
@@ -150,8 +154,6 @@
   base::ObserverList<Observer>::Unchecked observers_;
 
   base::WeakPtrFactory<HighlighterController> weak_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(HighlighterController);
 };
 
 }  // namespace ash
diff --git a/ash/highlighter/highlighter_result_view.cc b/ash/highlighter/highlighter_result_view.cc
index e6edc4e..0dae85577 100644
--- a/ash/highlighter/highlighter_result_view.cc
+++ b/ash/highlighter/highlighter_result_view.cc
@@ -59,6 +59,9 @@
  public:
   ResultLayer(const gfx::Rect& bounds);
 
+  ResultLayer(const ResultLayer&) = delete;
+  ResultLayer& operator=(const ResultLayer&) = delete;
+
  private:
   // ui::LayerDelegate:
   void OnDeviceScaleFactorChanged(float old_device_scale_factor,
@@ -75,8 +78,6 @@
                          float y,
                          float width,
                          cc::PaintFlags& flags);
-
-  DISALLOW_COPY_AND_ASSIGN(ResultLayer);
 };
 
 ResultLayer::ResultLayer(const gfx::Rect& box) {
diff --git a/ash/host/ash_window_tree_host_unified.cc b/ash/host/ash_window_tree_host_unified.cc
index 40369d2..e0c23b1 100644
--- a/ash/host/ash_window_tree_host_unified.cc
+++ b/ash/host/ash_window_tree_host_unified.cc
@@ -30,6 +30,9 @@
     DCHECK(delegate);
   }
 
+  UnifiedEventTargeter(const UnifiedEventTargeter&) = delete;
+  UnifiedEventTargeter& operator=(const UnifiedEventTargeter&) = delete;
+
   ui::EventTarget* FindTargetForEvent(ui::EventTarget* root,
                                       ui::Event* event) override {
     if (root == src_root_ && !event->target()) {
@@ -57,8 +60,6 @@
   aura::Window* src_root_;
   aura::Window* dst_root_;
   AshWindowTreeHostMirroringDelegate* delegate_;  // Not owned.
-
-  DISALLOW_COPY_AND_ASSIGN(UnifiedEventTargeter);
 };
 
 AshWindowTreeHostUnified::AshWindowTreeHostUnified(
diff --git a/ash/host/transformer_helper.cc b/ash/host/transformer_helper.cc
index 12080e5..adc6dcc8 100644
--- a/ash/host/transformer_helper.cc
+++ b/ash/host/transformer_helper.cc
@@ -33,6 +33,10 @@
                               const gfx::Transform& transform)
       : root_window_(root_window), transform_(transform) {}
 
+  SimpleRootWindowTransformer(const SimpleRootWindowTransformer&) = delete;
+  SimpleRootWindowTransformer& operator=(const SimpleRootWindowTransformer&) =
+      delete;
+
   // RootWindowTransformer overrides:
   gfx::Transform GetTransform() const override { return transform_; }
 
@@ -62,8 +66,6 @@
 
   const aura::Window* root_window_;
   const gfx::Transform transform_;
-
-  DISALLOW_COPY_AND_ASSIGN(SimpleRootWindowTransformer);
 };
 
 }  // namespace
diff --git a/ash/ime/ime_controller_impl_unittest.cc b/ash/ime/ime_controller_impl_unittest.cc
index 43270e5..b7249be 100644
--- a/ash/ime/ime_controller_impl_unittest.cc
+++ b/ash/ime/ime_controller_impl_unittest.cc
@@ -74,6 +74,10 @@
  public:
   TestImeControllerObserver() = default;
 
+  TestImeControllerObserver(const TestImeControllerObserver&) = delete;
+  TestImeControllerObserver& operator=(const TestImeControllerObserver&) =
+      delete;
+
   // IMEController::Observer:
   void OnCapsLockChanged(bool enabled) override { ++caps_lock_count_; }
   void OnKeyboardLayoutNameChanged(const std::string& layout_name) override {
@@ -87,8 +91,6 @@
  private:
   int caps_lock_count_ = 0;
   std::string last_keyboard_layout_name_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestImeControllerObserver);
 };
 
 using ImeControllerImplTest = AshTestBase;
diff --git a/ash/keyboard/arc/arc_virtual_keyboard_container_layout_manager.h b/ash/keyboard/arc/arc_virtual_keyboard_container_layout_manager.h
index 5240f1a21..b3f6177 100644
--- a/ash/keyboard/arc/arc_virtual_keyboard_container_layout_manager.h
+++ b/ash/keyboard/arc/arc_virtual_keyboard_container_layout_manager.h
@@ -17,6 +17,11 @@
   explicit ArcVirtualKeyboardContainerLayoutManager(
       aura::Window* arc_ime_window_parent_container);
 
+  ArcVirtualKeyboardContainerLayoutManager(
+      const ArcVirtualKeyboardContainerLayoutManager&) = delete;
+  ArcVirtualKeyboardContainerLayoutManager& operator=(
+      const ArcVirtualKeyboardContainerLayoutManager&) = delete;
+
   // aura::LayoutManager:
   void OnWindowResized() override;
   void OnWindowAddedToLayout(aura::Window* child) override;
@@ -29,8 +34,6 @@
 
  private:
   aura::Window* arc_ime_window_parent_container_;
-
-  DISALLOW_COPY_AND_ASSIGN(ArcVirtualKeyboardContainerLayoutManager);
 };
 
 }  // namespace ash
diff --git a/ash/keyboard/ui/keyboard_ui_controller.cc b/ash/keyboard/ui/keyboard_ui_controller.cc
index 1bee89c..1038389 100644
--- a/ash/keyboard/ui/keyboard_ui_controller.cc
+++ b/ash/keyboard/ui/keyboard_ui_controller.cc
@@ -146,6 +146,10 @@
   explicit CallbackAnimationObserver(base::OnceClosure callback)
       : callback_(std::move(callback)) {}
 
+  CallbackAnimationObserver(const CallbackAnimationObserver&) = delete;
+  CallbackAnimationObserver& operator=(const CallbackAnimationObserver&) =
+      delete;
+
  private:
   // ui::ImplicitAnimationObserver:
   void OnImplicitAnimationsCompleted() override {
@@ -161,8 +165,6 @@
   }
 
   base::OnceClosure callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(CallbackAnimationObserver);
 };
 
 KeyboardUIController::KeyboardUIController()
diff --git a/ash/keyboard/ui/keyboard_ui_model.h b/ash/keyboard/ui/keyboard_ui_model.h
index e9ce0f9..0a2222dc 100644
--- a/ash/keyboard/ui/keyboard_ui_model.h
+++ b/ash/keyboard/ui/keyboard_ui_model.h
@@ -51,6 +51,9 @@
  public:
   KeyboardUIModel();
 
+  KeyboardUIModel(const KeyboardUIModel&) = delete;
+  KeyboardUIModel& operator=(const KeyboardUIModel&) = delete;
+
   // Get the current state of the keyboard UI.
   KeyboardUIState state() const { return state_; }
 
@@ -60,8 +63,6 @@
  private:
   // Current state of the keyboard UI.
   KeyboardUIState state_ = KeyboardUIState::kInitial;
-
-  DISALLOW_COPY_AND_ASSIGN(KeyboardUIModel);
 };
 
 }  // namespace keyboard
diff --git a/ash/keyboard/ui/test/run_all_unittests.cc b/ash/keyboard/ui/test/run_all_unittests.cc
index 2b3a1706..62795b9 100644
--- a/ash/keyboard/ui/test/run_all_unittests.cc
+++ b/ash/keyboard/ui/test/run_all_unittests.cc
@@ -21,6 +21,9 @@
  public:
   KeyboardTestSuite(int argc, char** argv) : base::TestSuite(argc, argv) {}
 
+  KeyboardTestSuite(const KeyboardTestSuite&) = delete;
+  KeyboardTestSuite& operator=(const KeyboardTestSuite&) = delete;
+
  protected:
   void Initialize() override {
     base::TestSuite::Initialize();
@@ -41,8 +44,6 @@
 
  private:
   std::unique_ptr<aura::Env> env_;
-
-  DISALLOW_COPY_AND_ASSIGN(KeyboardTestSuite);
 };
 
 }  // namespace
diff --git a/ash/keyboard/ui/test/test_keyboard_controller_observer.h b/ash/keyboard/ui/test/test_keyboard_controller_observer.h
index ace27cf..04ca6ce 100644
--- a/ash/keyboard/ui/test/test_keyboard_controller_observer.h
+++ b/ash/keyboard/ui/test/test_keyboard_controller_observer.h
@@ -13,6 +13,12 @@
 // A KeyboardControllerObserver that counts occurrences of events for testing.
 struct TestKeyboardControllerObserver : public ash::KeyboardControllerObserver {
   TestKeyboardControllerObserver();
+
+  TestKeyboardControllerObserver(const TestKeyboardControllerObserver&) =
+      delete;
+  TestKeyboardControllerObserver& operator=(
+      const TestKeyboardControllerObserver&) = delete;
+
   ~TestKeyboardControllerObserver() override;
 
   // KeyboardControllerObserver:
@@ -20,7 +26,6 @@
 
   int enabled_count = 0;
   int disabled_count = 0;
-  DISALLOW_COPY_AND_ASSIGN(TestKeyboardControllerObserver);
 };
 
 }  // namespace keyboard
diff --git a/ash/keyboard/ui/test/test_keyboard_ui_factory.h b/ash/keyboard/ui/test/test_keyboard_ui_factory.h
index 5cc1ffc..1976a0c 100644
--- a/ash/keyboard/ui/test/test_keyboard_ui_factory.h
+++ b/ash/keyboard/ui/test/test_keyboard_ui_factory.h
@@ -42,6 +42,10 @@
   };
 
   explicit TestKeyboardUIFactory(ui::InputMethod* input_method);
+
+  TestKeyboardUIFactory(const TestKeyboardUIFactory&) = delete;
+  TestKeyboardUIFactory& operator=(const TestKeyboardUIFactory&) = delete;
+
   ~TestKeyboardUIFactory() override;
 
   // Overridden from KeyboardUIFactory:
@@ -49,8 +53,6 @@
 
  private:
   ui::InputMethod* input_method_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestKeyboardUIFactory);
 };
 
 }  // namespace keyboard
diff --git a/ash/keyboard/virtual_keyboard_container_layout_manager.h b/ash/keyboard/virtual_keyboard_container_layout_manager.h
index 1b43017..16ecb721 100644
--- a/ash/keyboard/virtual_keyboard_container_layout_manager.h
+++ b/ash/keyboard/virtual_keyboard_container_layout_manager.h
@@ -17,6 +17,11 @@
   explicit VirtualKeyboardContainerLayoutManager(
       aura::Window* ime_window_parent_container);
 
+  VirtualKeyboardContainerLayoutManager(
+      const VirtualKeyboardContainerLayoutManager&) = delete;
+  VirtualKeyboardContainerLayoutManager& operator=(
+      const VirtualKeyboardContainerLayoutManager&) = delete;
+
   // Overridden from aura::LayoutManager
   void OnWindowResized() override;
   void OnWindowAddedToLayout(aura::Window* child) override;
@@ -29,8 +34,6 @@
 
  private:
   aura::Window* ime_window_parent_container_;
-
-  DISALLOW_COPY_AND_ASSIGN(VirtualKeyboardContainerLayoutManager);
 };
 
 }  // namespace ash
diff --git a/ash/login/ui/lock_contents_view.h b/ash/login/ui/lock_contents_view.h
index 568f360..9d99a85 100644
--- a/ash/login/ui/lock_contents_view.h
+++ b/ash/login/ui/lock_contents_view.h
@@ -136,6 +136,10 @@
       LockScreen::ScreenType screen_type,
       LoginDataDispatcher* data_dispatcher,
       std::unique_ptr<LoginDetachableBaseModel> detachable_base_model);
+
+  LockContentsView(const LockContentsView&) = delete;
+  LockContentsView& operator=(const LockContentsView&) = delete;
+
   ~LockContentsView() override;
 
   void FocusNextUser();
@@ -537,8 +541,6 @@
       BottomIndicatorState::kNone;
 
   base::WeakPtrFactory<LockContentsView> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(LockContentsView);
 };
 
 }  // namespace ash
diff --git a/ash/login/ui/lock_screen.h b/ash/login/ui/lock_screen.h
index 754bce3..73cdf33 100644
--- a/ash/login/ui/lock_screen.h
+++ b/ash/login/ui/lock_screen.h
@@ -46,6 +46,9 @@
   // The UI that this instance is displaying.
   enum class ScreenType { kLogin, kLock };
 
+  LockScreen(const LockScreen&) = delete;
+  LockScreen& operator=(const LockScreen&) = delete;
+
   // Fetch the global lock screen instance. |Show()| must have been called
   // before this.
   static LockScreen* Get();
@@ -114,8 +117,6 @@
   ScopedSessionObserver session_observer_{this};
 
   std::vector<base::OnceClosure> on_shown_callbacks_;
-
-  DISALLOW_COPY_AND_ASSIGN(LockScreen);
 };
 
 }  // namespace ash
diff --git a/ash/login/ui/login_auth_user_view.cc b/ash/login/ui/login_auth_user_view.cc
index cd4b8fb..3d82291 100644
--- a/ash/login/ui/login_auth_user_view.cc
+++ b/ash/login/ui/login_auth_user_view.cc
@@ -230,6 +230,9 @@
                         false /*can_use_pin*/);
   }
 
+  FingerprintLabel(const FingerprintLabel&) = delete;
+  FingerprintLabel& operator=(const FingerprintLabel&) = delete;
+
   void SetTextBasedOnAuthAttempt(bool success) {
     SetText(l10n_util::GetStringUTF16(
         success ? IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_AUTH_SUCCESS
@@ -288,8 +291,6 @@
   }
 
   std::u16string accessible_name_;
-
-  DISALLOW_COPY_AND_ASSIGN(FingerprintLabel);
 };
 
 // The content needed to render the disabled auth message view.
@@ -744,6 +745,9 @@
     message_contents_->SetMultiLine(true);
   }
 
+  DisabledAuthMessageView(const DisabledAuthMessageView&) = delete;
+  DisabledAuthMessageView& operator=(const DisabledAuthMessageView&) = delete;
+
   ~DisabledAuthMessageView() override = default;
 
   // Set the parameters needed to render the message.
@@ -812,8 +816,6 @@
   views::Label* message_contents_;
   views::ImageView* message_icon_;
   const gfx::VectorIcon* message_vector_icon_ = nullptr;
-
-  DISALLOW_COPY_AND_ASSIGN(DisabledAuthMessageView);
 };
 
 // The message shown to user when TPM is locked.
diff --git a/ash/login/ui/login_auth_user_view.h b/ash/login/ui/login_auth_user_view.h
index 935b2372..7aff83f 100644
--- a/ash/login/ui/login_auth_user_view.h
+++ b/ash/login/ui/login_auth_user_view.h
@@ -132,6 +132,10 @@
   };
 
   LoginAuthUserView(const LoginUserInfo& user, const Callbacks& callbacks);
+
+  LoginAuthUserView(const LoginAuthUserView&) = delete;
+  LoginAuthUserView& operator=(const LoginAuthUserView&) = delete;
+
   ~LoginAuthUserView() override;
 
   // Set the displayed set of auth methods. |auth_methods| contains or-ed
@@ -297,8 +301,6 @@
   std::unique_ptr<UiState> previous_state_;
 
   base::WeakPtrFactory<LoginAuthUserView> weak_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(LoginAuthUserView);
 };
 
 }  // namespace ash
diff --git a/ash/login/ui/login_auth_user_view_unittest.cc b/ash/login/ui/login_auth_user_view_unittest.cc
index 44d02051b..a591d96 100644
--- a/ash/login/ui/login_auth_user_view_unittest.cc
+++ b/ash/login/ui/login_auth_user_view_unittest.cc
@@ -61,6 +61,10 @@
                                   /*autosubmit_feature*/
                                   public ::testing::WithParamInterface<bool> {
  public:
+  LoginAuthUserViewUnittest(const LoginAuthUserViewUnittest&) = delete;
+  LoginAuthUserViewUnittest& operator=(const LoginAuthUserViewUnittest&) =
+      delete;
+
   static std::string ParamInfoToString(
       testing::TestParamInfo<LoginAuthUserViewUnittest::ParamType> info) {
     return base::StrCat(
@@ -145,9 +149,6 @@
   LoginUserInfo user_;
   views::View* container_ = nullptr;   // Owned by test widget view hierarchy.
   LoginAuthUserView* view_ = nullptr;  // Owned by test widget view hierarchy.
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(LoginAuthUserViewUnittest);
 };
 
 // Verifies showing the PIN keyboard makes the user view grow.
diff --git a/ash/login/ui/login_base_bubble_view_unittest.cc b/ash/login/ui/login_base_bubble_view_unittest.cc
index 111c314..b743bde 100644
--- a/ash/login/ui/login_base_bubble_view_unittest.cc
+++ b/ash/login/ui/login_base_bubble_view_unittest.cc
@@ -19,6 +19,10 @@
 }  // namespace
 
 class LoginBaseBubbleViewTest : public LoginTestBase {
+ public:
+  LoginBaseBubbleViewTest(const LoginBaseBubbleViewTest&) = delete;
+  LoginBaseBubbleViewTest& operator=(const LoginBaseBubbleViewTest&) = delete;
+
  protected:
   LoginBaseBubbleViewTest() = default;
   ~LoginBaseBubbleViewTest() override = default;
@@ -49,9 +53,6 @@
   LoginBaseBubbleView* bubble_;
   views::View* container_;
   views::View* anchor_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(LoginBaseBubbleViewTest);
 };
 
 TEST_F(LoginBaseBubbleViewTest, BasicProperties) {
diff --git a/ash/login/ui/login_big_user_view.h b/ash/login/ui/login_big_user_view.h
index 4d0bd33c..660d15e 100644
--- a/ash/login/ui/login_big_user_view.h
+++ b/ash/login/ui/login_big_user_view.h
@@ -39,6 +39,10 @@
       const LoginUserInfo& user,
       const LoginAuthUserView::Callbacks& auth_user_callbacks,
       const LoginPublicAccountUserView::Callbacks& public_account_callbacks);
+
+  LoginBigUserView(const LoginBigUserView&) = delete;
+  LoginBigUserView& operator=(const LoginBigUserView&) = delete;
+
   ~LoginBigUserView() override;
 
   // Base on the user type, call CreateAuthUser or CreatePublicAccount.
@@ -84,8 +88,6 @@
 
   base::ScopedObservation<WallpaperController, WallpaperControllerObserver>
       observation_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(LoginBigUserView);
 };
 
 }  // namespace ash
diff --git a/ash/login/ui/login_expanded_public_account_view.h b/ash/login/ui/login_expanded_public_account_view.h
index c315278..f905b98 100644
--- a/ash/login/ui/login_expanded_public_account_view.h
+++ b/ash/login/ui/login_expanded_public_account_view.h
@@ -63,6 +63,12 @@
   using OnPublicSessionViewDismissed = base::RepeatingClosure;
   explicit LoginExpandedPublicAccountView(
       const OnPublicSessionViewDismissed& on_dismissed);
+
+  LoginExpandedPublicAccountView(const LoginExpandedPublicAccountView&) =
+      delete;
+  LoginExpandedPublicAccountView& operator=(
+      const LoginExpandedPublicAccountView&) = delete;
+
   ~LoginExpandedPublicAccountView() override;
 
   static void RegisterLocalStatePrefs(PrefRegistrySimple* registry);
@@ -89,8 +95,6 @@
   std::unique_ptr<ui::EventHandler> event_handler_;
 
   base::WeakPtrFactory<LoginExpandedPublicAccountView> weak_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(LoginExpandedPublicAccountView);
 };
 
 }  // namespace ash
diff --git a/ash/login/ui/login_expanded_public_account_view_unittest.cc b/ash/login/ui/login_expanded_public_account_view_unittest.cc
index 087bf04..5c52c56a 100644
--- a/ash/login/ui/login_expanded_public_account_view_unittest.cc
+++ b/ash/login/ui/login_expanded_public_account_view_unittest.cc
@@ -45,6 +45,12 @@
 class LoginExpandedPublicAccountViewTest
     : public LoginTestBase,
       public ::testing::WithParamInterface<const char*> {
+ public:
+  LoginExpandedPublicAccountViewTest(
+      const LoginExpandedPublicAccountViewTest&) = delete;
+  LoginExpandedPublicAccountViewTest& operator=(
+      const LoginExpandedPublicAccountViewTest&) = delete;
+
  protected:
   LoginExpandedPublicAccountViewTest() = default;
   ~LoginExpandedPublicAccountViewTest() override = default;
@@ -121,9 +127,6 @@
   views::View* container_ = nullptr;
   LoginExpandedPublicAccountView* public_account_ = nullptr;
   views::View* other_view_ = nullptr;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(LoginExpandedPublicAccountViewTest);
 };
 
 }  // namespace
diff --git a/ash/login/ui/login_password_view.h b/ash/login/ui/login_password_view.h
index 32731b9..38ccf0b 100644
--- a/ash/login/ui/login_password_view.h
+++ b/ash/login/ui/login_password_view.h
@@ -86,6 +86,10 @@
 
   // Must call |Init| after construction.
   explicit LoginPasswordView(const LoginPalette& palette);
+
+  LoginPasswordView(const LoginPasswordView&) = delete;
+  LoginPasswordView& operator=(const LoginPasswordView&) = delete;
+
   ~LoginPasswordView() override;
 
   // |on_submit| is called when the user hits enter or has pressed the submit
@@ -214,8 +218,6 @@
   bool should_show_easy_unlock_ = false;
 
   bool is_capslock_higlight_ = false;
-
-  DISALLOW_COPY_AND_ASSIGN(LoginPasswordView);
 };
 
 }  // namespace ash
diff --git a/ash/login/ui/login_password_view_test.cc b/ash/login/ui/login_password_view_test.cc
index 69820f9..0d2b1cf 100644
--- a/ash/login/ui/login_password_view_test.cc
+++ b/ash/login/ui/login_password_view_test.cc
@@ -34,6 +34,10 @@
     base::TimeDelta::FromSeconds(4);
 
 class LoginPasswordViewTest : public LoginTestBase {
+ public:
+  LoginPasswordViewTest(const LoginPasswordViewTest&) = delete;
+  LoginPasswordViewTest& operator=(const LoginPasswordViewTest&) = delete;
+
  protected:
   LoginPasswordViewTest() = default;
   ~LoginPasswordViewTest() override = default;
@@ -70,9 +74,6 @@
   bool is_password_field_empty_ = true;
   bool easy_unlock_icon_hovered_called_ = false;
   bool easy_unlock_icon_tapped_called_ = false;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(LoginPasswordViewTest);
 };
 
 // For tests with the Smart Lock UI revamp feature enabled. Enables the flag
diff --git a/ash/login/ui/login_pin_view.h b/ash/login/ui/login_pin_view.h
index 5503a92..082a5bf 100644
--- a/ash/login/ui/login_pin_view.h
+++ b/ash/login/ui/login_pin_view.h
@@ -103,6 +103,9 @@
                const OnPinBackspace& on_backspace,
                const OnPinSubmit& on_submit = base::NullCallback());
 
+  LoginPinView(const LoginPinView&) = delete;
+  LoginPinView& operator=(const LoginPinView&) = delete;
+
   ~LoginPinView() override;
 
   // Notify accessibility that location of rows and LoginPinView changed.
@@ -129,8 +132,6 @@
 
   std::vector<NonAccessibleView*> rows_;
   std::vector<DigitPinButton*> digit_buttons_;
-
-  DISALLOW_COPY_AND_ASSIGN(LoginPinView);
 };
 
 }  // namespace ash
diff --git a/ash/login/ui/login_pin_view_unittest.cc b/ash/login/ui/login_pin_view_unittest.cc
index 53e02aa..855c605 100644
--- a/ash/login/ui/login_pin_view_unittest.cc
+++ b/ash/login/ui/login_pin_view_unittest.cc
@@ -21,6 +21,10 @@
 namespace {
 
 class LoginPinViewTest : public LoginTestBase {
+ public:
+  LoginPinViewTest(const LoginPinViewTest&) = delete;
+  LoginPinViewTest& operator=(const LoginPinViewTest&) = delete;
+
  protected:
   LoginPinViewTest() = default;
   ~LoginPinViewTest() override = default;
@@ -51,9 +55,6 @@
   int backspace_ = 0;
   // Number of times the submit event has been fired.
   int submit_ = 0;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(LoginPinViewTest);
 };
 
 }  // namespace
diff --git a/ash/login/ui/login_public_account_user_view.h b/ash/login/ui/login_public_account_user_view.h
index 1b6ea1f..d2b662a 100644
--- a/ash/login/ui/login_public_account_user_view.h
+++ b/ash/login/ui/login_public_account_user_view.h
@@ -46,6 +46,11 @@
 
   LoginPublicAccountUserView(const LoginUserInfo& user,
                              const Callbacks& callbacks);
+
+  LoginPublicAccountUserView(const LoginPublicAccountUserView&) = delete;
+  LoginPublicAccountUserView& operator=(const LoginPublicAccountUserView&) =
+      delete;
+
   ~LoginPublicAccountUserView() override;
 
   void SetAuthEnabled(bool enabled, bool animate);
@@ -80,8 +85,6 @@
   bool ignore_hover_ = false;
   bool auth_enabled_ = false;
   LoginUserView* user_view_ = nullptr;
-
-  DISALLOW_COPY_AND_ASSIGN(LoginPublicAccountUserView);
 };
 
 }  // namespace ash
diff --git a/ash/login/ui/login_public_account_user_view_unittest.cc b/ash/login/ui/login_public_account_user_view_unittest.cc
index 0e12dab5..b3501e7a 100644
--- a/ash/login/ui/login_public_account_user_view_unittest.cc
+++ b/ash/login/ui/login_public_account_user_view_unittest.cc
@@ -20,6 +20,12 @@
 constexpr int kNonEmptySize = 20;
 
 class LoginPublicAccountUserViewTest : public LoginTestBase {
+ public:
+  LoginPublicAccountUserViewTest(const LoginPublicAccountUserViewTest&) =
+      delete;
+  LoginPublicAccountUserViewTest& operator=(
+      const LoginPublicAccountUserViewTest&) = delete;
+
  protected:
   LoginPublicAccountUserViewTest() = default;
   ~LoginPublicAccountUserViewTest() override = default;
@@ -73,8 +79,6 @@
   }
 
   void OnPublicAccountTapped() { ++public_account_tap_count_; }
-
-  DISALLOW_COPY_AND_ASSIGN(LoginPublicAccountUserViewTest);
 };
 
 }  // namespace
diff --git a/ash/login/ui/login_user_view.cc b/ash/login/ui/login_user_view.cc
index 75c94e11..ea965a4 100644
--- a/ash/login/ui/login_user_view.cc
+++ b/ash/login/ui/login_user_view.cc
@@ -185,6 +185,9 @@
     AddChildView(enterprise_icon_);
   }
 
+  UserImage(const UserImage&) = delete;
+  UserImage& operator=(const UserImage&) = delete;
+
   ~UserImage() override = default;
 
   void UpdateForUser(const LoginUserInfo& user) {
@@ -258,8 +261,6 @@
   bool animation_enabled_ = false;
 
   base::WeakPtrFactory<UserImage> weak_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(UserImage);
 };
 
 // Shows the user's name.
diff --git a/ash/login/ui/login_user_view.h b/ash/login/ui/login_user_view.h
index 12e51877..7ba2618 100644
--- a/ash/login/ui/login_user_view.h
+++ b/ash/login/ui/login_user_view.h
@@ -63,6 +63,10 @@
                 const OnTap& on_tap,
                 const OnRemoveWarningShown& on_remove_warning_shown,
                 const OnRemove& on_remove);
+
+  LoginUserView(const LoginUserView&) = delete;
+  LoginUserView& operator=(const LoginUserView&) = delete;
+
   ~LoginUserView() override;
 
   // Update the user view to display the given user information.
@@ -141,8 +145,6 @@
   base::ScopedObservation<display::DisplayConfigurator,
                           display::DisplayConfigurator::Observer>
       display_observation_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(LoginUserView);
 };
 
 }  // namespace ash
diff --git a/ash/login/ui/login_user_view_unittest.cc b/ash/login/ui/login_user_view_unittest.cc
index 2721e3fde..69d2376 100644
--- a/ash/login/ui/login_user_view_unittest.cc
+++ b/ash/login/ui/login_user_view_unittest.cc
@@ -18,6 +18,10 @@
 namespace {
 
 class LoginUserViewUnittest : public LoginTestBase {
+ public:
+  LoginUserViewUnittest(const LoginUserViewUnittest&) = delete;
+  LoginUserViewUnittest& operator=(const LoginUserViewUnittest&) = delete;
+
  protected:
   LoginUserViewUnittest() = default;
   ~LoginUserViewUnittest() override = default;
@@ -75,8 +79,6 @@
   void OnTapped() { ++tap_count_; }
   void OnRemoveWarningShown() { ++remove_show_warning_count_; }
   void OnRemove() { ++remove_count_; }
-
-  DISALLOW_COPY_AND_ASSIGN(LoginUserViewUnittest);
 };
 
 }  // namespace
diff --git a/ash/login/ui/note_action_launch_button.h b/ash/login/ui/note_action_launch_button.h
index 6558701a..3fc3563 100644
--- a/ash/login/ui/note_action_launch_button.h
+++ b/ash/login/ui/note_action_launch_button.h
@@ -50,6 +50,10 @@
 
   explicit NoteActionLaunchButton(
       mojom::TrayActionState initial_note_action_state);
+
+  NoteActionLaunchButton(const NoteActionLaunchButton&) = delete;
+  NoteActionLaunchButton& operator=(const NoteActionLaunchButton&) = delete;
+
   ~NoteActionLaunchButton() override;
 
   // Updates the bubble visibility depending on the note taking action state.
@@ -64,8 +68,6 @@
 
   // The actionable image button view.
   ActionButton* action_button_ = nullptr;
-
-  DISALLOW_COPY_AND_ASSIGN(NoteActionLaunchButton);
 };
 
 }  // namespace ash
diff --git a/ash/login/ui/pin_request_view.h b/ash/login/ui/pin_request_view.h
index 5336615..6bfa9a1 100644
--- a/ash/login/ui/pin_request_view.h
+++ b/ash/login/ui/pin_request_view.h
@@ -121,6 +121,10 @@
   // Creates pin request view that will enable the user to enter a pin.
   // |request| is used to configure callbacks and UI details.
   PinRequestView(PinRequest request, Delegate* delegate);
+
+  PinRequestView(const PinRequestView&) = delete;
+  PinRequestView& operator=(const PinRequestView&) = delete;
+
   ~PinRequestView() override;
 
   // views::View:
@@ -207,8 +211,6 @@
       tablet_mode_observation_{this};
 
   base::WeakPtrFactory<PinRequestView> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(PinRequestView);
 };
 
 }  // namespace ash
diff --git a/ash/login/ui/pin_request_view_unittest.cc b/ash/login/ui/pin_request_view_unittest.cc
index 8b37cb4..d65bc54 100644
--- a/ash/login/ui/pin_request_view_unittest.cc
+++ b/ash/login/ui/pin_request_view_unittest.cc
@@ -49,6 +49,10 @@
 
 class PinRequestViewTest : public LoginTestBase,
                            public PinRequestView::Delegate {
+ public:
+  PinRequestViewTest(const PinRequestViewTest&) = delete;
+  PinRequestViewTest& operator=(const PinRequestViewTest&) = delete;
+
  protected:
   PinRequestViewTest() {}
   ~PinRequestViewTest() override = default;
@@ -174,9 +178,6 @@
   bool will_authenticate_ = true;
 
   PinRequestView* view_ = nullptr;  // Owned by test widget view hierarchy.
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(PinRequestViewTest);
 };
 
 // Tests that back button works.
diff --git a/ash/login/ui/pin_request_widget.h b/ash/login/ui/pin_request_widget.h
index b721ac8..5205cbf 100644
--- a/ash/login/ui/pin_request_widget.h
+++ b/ash/login/ui/pin_request_widget.h
@@ -45,6 +45,9 @@
     PinRequestWidget* const pin_request_widget_;
   };
 
+  PinRequestWidget(const PinRequestWidget&) = delete;
+  PinRequestWidget& operator=(const PinRequestWidget&) = delete;
+
   // Creates and shows the instance of PinRequestWidget.
   // This widget is modal and only one instance can be created at a time. It
   // will be destroyed when dismissed.
@@ -89,8 +92,6 @@
   std::unique_ptr<WindowDimmer> dimmer_;
 
   base::WeakPtrFactory<PinRequestWidget> weak_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(PinRequestWidget);
 };
 
 }  // namespace ash
diff --git a/ash/login/ui/scrollable_users_list_view.h b/ash/login/ui/scrollable_users_list_view.h
index 556c050c..a917d3b 100644
--- a/ash/login/ui/scrollable_users_list_view.h
+++ b/ash/login/ui/scrollable_users_list_view.h
@@ -50,6 +50,10 @@
   ScrollableUsersListView(const std::vector<LoginUserInfo>& users,
                           const ActionWithUser& on_tap_user,
                           LoginDisplayStyle display_style);
+
+  ScrollableUsersListView(const ScrollableUsersListView&) = delete;
+  ScrollableUsersListView& operator=(const ScrollableUsersListView&) = delete;
+
   ~ScrollableUsersListView() override;
 
   // Returns user view at |index| if it exists or nullptr otherwise.
@@ -103,8 +107,6 @@
 
   base::ScopedObservation<WallpaperController, WallpaperControllerObserver>
       observation_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(ScrollableUsersListView);
 };
 
 }  // namespace ash
diff --git a/ash/login/ui/views_utils_unittest.cc b/ash/login/ui/views_utils_unittest.cc
index b6fbe76..d691ad54 100644
--- a/ash/login/ui/views_utils_unittest.cc
+++ b/ash/login/ui/views_utils_unittest.cc
@@ -13,12 +13,13 @@
 namespace {
 
 class ViewsUtilsUnittest : public testing::Test {
+ public:
+  ViewsUtilsUnittest(const ViewsUtilsUnittest&) = delete;
+  ViewsUtilsUnittest& operator=(const ViewsUtilsUnittest&) = delete;
+
  protected:
   ViewsUtilsUnittest() = default;
   ~ViewsUtilsUnittest() override = default;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ViewsUtilsUnittest);
 };
 
 }  // namespace
diff --git a/ash/metrics/demo_session_metrics_recorder.cc b/ash/metrics/demo_session_metrics_recorder.cc
index 03d4f35..1111ac3 100644
--- a/ash/metrics/demo_session_metrics_recorder.cc
+++ b/ash/metrics/demo_session_metrics_recorder.cc
@@ -230,6 +230,11 @@
       DemoSessionMetricsRecorder* metrics_recorder)
       : metrics_recorder_(metrics_recorder) {}
 
+  ActiveAppArcPackageNameObserver(const ActiveAppArcPackageNameObserver&) =
+      delete;
+  ActiveAppArcPackageNameObserver& operator=(
+      const ActiveAppArcPackageNameObserver&) = delete;
+
   // aura::WindowObserver
   void OnWindowPropertyChanged(aura::Window* window,
                                const void* key,
@@ -262,8 +267,6 @@
   DemoSessionMetricsRecorder* metrics_recorder_;
   base::ScopedMultiSourceObservation<aura::Window, aura::WindowObserver>
       scoped_observations_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(ActiveAppArcPackageNameObserver);
 };
 
 // Observes changes in a window's ArcPackageName property for the purpose of
@@ -275,6 +278,11 @@
       DemoSessionMetricsRecorder* metrics_recorder)
       : metrics_recorder_(metrics_recorder) {}
 
+  UniqueAppsLaunchedArcPackageNameObserver(
+      const UniqueAppsLaunchedArcPackageNameObserver&) = delete;
+  UniqueAppsLaunchedArcPackageNameObserver& operator=(
+      const UniqueAppsLaunchedArcPackageNameObserver&) = delete;
+
   // aura::WindowObserver
   void OnWindowPropertyChanged(aura::Window* window,
                                const void* key,
@@ -307,8 +315,6 @@
   DemoSessionMetricsRecorder* metrics_recorder_;
   base::ScopedObservation<aura::Window, aura::WindowObserver>
       scoped_observation_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(UniqueAppsLaunchedArcPackageNameObserver);
 };
 
 DemoSessionMetricsRecorder::DemoSessionMetricsRecorder(
diff --git a/ash/metrics/desktop_task_switch_metric_recorder_unittest.cc b/ash/metrics/desktop_task_switch_metric_recorder_unittest.cc
index 154bb51..a2fec26 100644
--- a/ash/metrics/desktop_task_switch_metric_recorder_unittest.cc
+++ b/ash/metrics/desktop_task_switch_metric_recorder_unittest.cc
@@ -254,6 +254,12 @@
     : public AshTestBase {
  public:
   DesktopTaskSwitchMetricRecorderWithShellIntegrationTest();
+
+  DesktopTaskSwitchMetricRecorderWithShellIntegrationTest(
+      const DesktopTaskSwitchMetricRecorderWithShellIntegrationTest&) = delete;
+  DesktopTaskSwitchMetricRecorderWithShellIntegrationTest& operator=(
+      const DesktopTaskSwitchMetricRecorderWithShellIntegrationTest&) = delete;
+
   ~DesktopTaskSwitchMetricRecorderWithShellIntegrationTest() override;
 
   // AshTestBase:
@@ -276,10 +282,6 @@
   // Delegate used when creating new windows using the
   // CreatePositionableWindowInShellWithBounds(...) method.
   aura::test::TestWindowDelegate test_window_delegate_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(
-      DesktopTaskSwitchMetricRecorderWithShellIntegrationTest);
 };
 
 DesktopTaskSwitchMetricRecorderWithShellIntegrationTest::
diff --git a/ash/multi_device_setup/multi_device_notification_presenter_unittest.cc b/ash/multi_device_setup/multi_device_notification_presenter_unittest.cc
index 0aba2ab..5f32f79 100644
--- a/ash/multi_device_setup/multi_device_notification_presenter_unittest.cc
+++ b/ash/multi_device_setup/multi_device_notification_presenter_unittest.cc
@@ -104,6 +104,11 @@
  public:
   MultiDeviceNotificationPresenterTest() = default;
 
+  MultiDeviceNotificationPresenterTest(
+      const MultiDeviceNotificationPresenterTest&) = delete;
+  MultiDeviceNotificationPresenterTest& operator=(
+      const MultiDeviceNotificationPresenterTest&) = delete;
+
   void SetUp() override {
     fake_multidevice_setup_ =
         std::make_unique<chromeos::multidevice_setup::FakeMultiDeviceSetup>();
@@ -334,8 +339,6 @@
     EXPECT_EQ(title, kVisibleNotification->title());
     EXPECT_EQ(message, kVisibleNotification->message());
   }
-
-  DISALLOW_COPY_AND_ASSIGN(MultiDeviceNotificationPresenterTest);
 };
 
 TEST_F(MultiDeviceNotificationPresenterTest, NotSignedIntoAccount) {
diff --git a/ash/multi_profile_uma.h b/ash/multi_profile_uma.h
index ad4be7b..2caa7ba57 100644
--- a/ash/multi_profile_uma.h
+++ b/ash/multi_profile_uma.h
@@ -22,11 +22,12 @@
     NUM_SWITCH_ACTIVE_USER_ACTIONS
   };
 
+  MultiProfileUMA() = delete;
+  MultiProfileUMA(const MultiProfileUMA&) = delete;
+  MultiProfileUMA& operator=(const MultiProfileUMA&) = delete;
+
   // Record switching the active user and what UI path was taken.
   static void RecordSwitchActiveUser(SwitchActiveUserAction action);
-
- private:
-  DISALLOW_IMPLICIT_CONSTRUCTORS(MultiProfileUMA);
 };
 
 }  // namespace ash
diff --git a/ash/multi_user/user_switch_animator.cc b/ash/multi_user/user_switch_animator.cc
index e6108d6..2d629d3 100644
--- a/ash/multi_user/user_switch_animator.cc
+++ b/ash/multi_user/user_switch_animator.cc
@@ -59,13 +59,16 @@
       std::unique_ptr<ui::LayerTreeOwner> old_layer)
       : old_layer_(std::move(old_layer)) {}
 
+  MaximizedWindowAnimationWatcher(const MaximizedWindowAnimationWatcher&) =
+      delete;
+  MaximizedWindowAnimationWatcher& operator=(
+      const MaximizedWindowAnimationWatcher&) = delete;
+
   // ui::ImplicitAnimationObserver:
   void OnImplicitAnimationsCompleted() override { delete this; }
 
  private:
   std::unique_ptr<ui::LayerTreeOwner> old_layer_;
-
-  DISALLOW_COPY_AND_ASSIGN(MaximizedWindowAnimationWatcher);
 };
 
 // Modifies the given |window_list| such that the most-recently used window (if
diff --git a/ash/policy/policy_recommendation_restorer_unittest.cc b/ash/policy/policy_recommendation_restorer_unittest.cc
index d57c0bc3..06b7bb9b 100644
--- a/ash/policy/policy_recommendation_restorer_unittest.cc
+++ b/ash/policy/policy_recommendation_restorer_unittest.cc
@@ -20,6 +20,12 @@
 namespace ash {
 
 class PolicyRecommendationRestorerTest : public NoSessionAshTestBase {
+ public:
+  PolicyRecommendationRestorerTest(const PolicyRecommendationRestorerTest&) =
+      delete;
+  PolicyRecommendationRestorerTest& operator=(
+      const PolicyRecommendationRestorerTest&) = delete;
+
  protected:
   PolicyRecommendationRestorerTest()
       : recommended_prefs_(new TestingPrefStore),
@@ -146,9 +152,6 @@
   // Ownerships are passed to SessionController.
   TestingPrefStore* recommended_prefs_;
   sync_preferences::TestingPrefServiceSyncable* prefs_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(PolicyRecommendationRestorerTest);
 };
 
 // Verifies that when no recommended values have been set, |restorer_| does not
diff --git a/ash/public/cpp/accessibility_controller.h b/ash/public/cpp/accessibility_controller.h
index 7b147dd..c27ba75 100644
--- a/ash/public/cpp/accessibility_controller.h
+++ b/ash/public/cpp/accessibility_controller.h
@@ -32,6 +32,9 @@
  public:
   static AccessibilityController* Get();
 
+  AccessibilityController(const AccessibilityController&) = delete;
+  AccessibilityController& operator=(const AccessibilityController&) = delete;
+
   // Sets the client interface.
   virtual void SetClient(AccessibilityControllerClient* client) = 0;
 
@@ -182,9 +185,6 @@
  protected:
   AccessibilityController();
   virtual ~AccessibilityController();
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(AccessibilityController);
 };
 
 }  // namespace ash
diff --git a/ash/public/cpp/accessibility_focus_ring_controller.h b/ash/public/cpp/accessibility_focus_ring_controller.h
index e609173..ec69e3f0 100644
--- a/ash/public/cpp/accessibility_focus_ring_controller.h
+++ b/ash/public/cpp/accessibility_focus_ring_controller.h
@@ -25,6 +25,11 @@
  public:
   static AccessibilityFocusRingController* Get();
 
+  AccessibilityFocusRingController(const AccessibilityFocusRingController&) =
+      delete;
+  AccessibilityFocusRingController& operator=(
+      const AccessibilityFocusRingController&) = delete;
+
   // Sets the focus ring with the given ID to the specifications of focus_ring.
   virtual void SetFocusRing(
       const std::string& focus_ring_id,
@@ -49,9 +54,6 @@
  protected:
   AccessibilityFocusRingController();
   virtual ~AccessibilityFocusRingController();
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(AccessibilityFocusRingController);
 };
 
 }  // namespace ash
diff --git a/ash/public/cpp/accessibility_focus_ring_info.h b/ash/public/cpp/accessibility_focus_ring_info.h
index b7015c3..4f925a4 100644
--- a/ash/public/cpp/accessibility_focus_ring_info.h
+++ b/ash/public/cpp/accessibility_focus_ring_info.h
@@ -41,6 +41,11 @@
 // TODO: This struct could possibly be merged with ash::AccessibilityFocusRing.
 struct ASH_PUBLIC_EXPORT AccessibilityFocusRingInfo {
   AccessibilityFocusRingInfo();
+
+  AccessibilityFocusRingInfo(const AccessibilityFocusRingInfo&) = delete;
+  AccessibilityFocusRingInfo& operator=(const AccessibilityFocusRingInfo&) =
+      delete;
+
   ~AccessibilityFocusRingInfo();
 
   bool operator==(const AccessibilityFocusRingInfo& other) const;
@@ -53,9 +58,6 @@
   SkColor color = SK_ColorTRANSPARENT;
   SkColor secondary_color = SK_ColorTRANSPARENT;
   SkColor background_color = SK_ColorTRANSPARENT;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(AccessibilityFocusRingInfo);
 };
 
 }  // namespace ash
diff --git a/ash/public/cpp/android_intent_helper.h b/ash/public/cpp/android_intent_helper.h
index 98418483..2fe973d5 100644
--- a/ash/public/cpp/android_intent_helper.h
+++ b/ash/public/cpp/android_intent_helper.h
@@ -19,6 +19,9 @@
  public:
   static AndroidIntentHelper* GetInstance();
 
+  AndroidIntentHelper(const AndroidIntentHelper&) = delete;
+  AndroidIntentHelper& operator=(const AndroidIntentHelper&) = delete;
+
   // Launch the given Android |intent|.
   virtual void LaunchAndroidIntent(const std::string& intent) = 0;
 
@@ -30,9 +33,6 @@
  protected:
   AndroidIntentHelper();
   virtual ~AndroidIntentHelper();
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(AndroidIntentHelper);
 };
 
 ASH_PUBLIC_EXPORT bool IsAndroidIntent(const GURL& url);
diff --git a/ash/public/cpp/app_list/app_list_config_provider.h b/ash/public/cpp/app_list/app_list_config_provider.h
index c8ca592d..278872a 100644
--- a/ash/public/cpp/app_list/app_list_config_provider.h
+++ b/ash/public/cpp/app_list/app_list_config_provider.h
@@ -41,6 +41,10 @@
   static AppListConfigProvider& Get();
 
   AppListConfigProvider();
+
+  AppListConfigProvider(const AppListConfigProvider&) = delete;
+  AppListConfigProvider& operator=(const AppListConfigProvider&) = delete;
+
   ~AppListConfigProvider();
 
   void AddObserver(Observer* observer);
@@ -80,8 +84,6 @@
   std::map<AppListConfigType, std::unique_ptr<AppListConfig>> configs_;
 
   base::ObserverList<Observer> observers_;
-
-  DISALLOW_COPY_AND_ASSIGN(AppListConfigProvider);
 };
 
 }  // namespace ash
diff --git a/ash/public/cpp/app_list/app_list_controller.h b/ash/public/cpp/app_list/app_list_controller.h
index e6a5bb5..351a8cb 100644
--- a/ash/public/cpp/app_list/app_list_controller.h
+++ b/ash/public/cpp/app_list/app_list_controller.h
@@ -56,10 +56,6 @@
   // single child left.
   virtual void RemoveUninstalledItem(const std::string& id) = 0;
 
-  // Moves the item with |id| to the folder with |folder_id|.
-  virtual void MoveItemToFolder(const std::string& id,
-                                const std::string& folder_id) = 0;
-
   // Tells Ash what the current status of AppListModel should be,
   // e.g. the model is under synchronization or in normal status.
   virtual void SetStatus(AppListModelStatus status) = 0;
diff --git a/ash/public/cpp/assistant/assistant_setup.h b/ash/public/cpp/assistant/assistant_setup.h
index f7b556f3..e60ced0 100644
--- a/ash/public/cpp/assistant/assistant_setup.h
+++ b/ash/public/cpp/assistant/assistant_setup.h
@@ -25,6 +25,9 @@
  public:
   static AssistantSetup* GetInstance();
 
+  AssistantSetup(const AssistantSetup&) = delete;
+  AssistantSetup& operator=(const AssistantSetup&) = delete;
+
   using StartAssistantOptInFlowCallback = base::OnceCallback<void(bool)>;
 
   // Start the assistant setup flow.
@@ -40,9 +43,6 @@
  protected:
   AssistantSetup();
   virtual ~AssistantSetup();
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(AssistantSetup);
 };
 
 }  // namespace ash
diff --git a/ash/public/cpp/assistant/controller/assistant_controller_observer.h b/ash/public/cpp/assistant/controller/assistant_controller_observer.h
index c4f9e08b..423d6d9 100644
--- a/ash/public/cpp/assistant/controller/assistant_controller_observer.h
+++ b/ash/public/cpp/assistant/controller/assistant_controller_observer.h
@@ -27,6 +27,10 @@
 class ASH_PUBLIC_EXPORT AssistantControllerObserver
     : public base::CheckedObserver {
  public:
+  AssistantControllerObserver(const AssistantControllerObserver&) = delete;
+  AssistantControllerObserver& operator=(const AssistantControllerObserver&) =
+      delete;
+
   // Invoked when the AssistantController has been fully constructed.
   virtual void OnAssistantControllerConstructed() {}
 
@@ -56,8 +60,6 @@
  protected:
   AssistantControllerObserver() = default;
   ~AssistantControllerObserver() override = default;
-
-  DISALLOW_COPY_AND_ASSIGN(AssistantControllerObserver);
 };
 
 }  // namespace ash
diff --git a/ash/public/cpp/capture_mode/capture_mode_delegate.h b/ash/public/cpp/capture_mode/capture_mode_delegate.h
index 5eaea33..93a9d679 100644
--- a/ash/public/cpp/capture_mode/capture_mode_delegate.h
+++ b/ash/public/cpp/capture_mode/capture_mode_delegate.h
@@ -46,9 +46,9 @@
  public:
   virtual ~CaptureModeDelegate() = default;
 
-  // Returns the path to save screen capture files based on user login status.
-  // If no user is logged in, returns the temporary directory.
-  virtual base::FilePath GetScreenCaptureDir() const = 0;
+  // Returns the path to the default downloads directory of the currently active
+  // user. This function can only be called if the user is logged in.
+  virtual base::FilePath GetUserDefaultDownloadsFolder() const = 0;
 
   // Shows the screenshot or screen recording item in the screen capture folder.
   virtual void ShowScreenCaptureItemInFolder(
diff --git a/ash/public/cpp/external_arc/message_center/arc_notification_delegate.h b/ash/public/cpp/external_arc/message_center/arc_notification_delegate.h
index 42d0c37..60ea62cb 100644
--- a/ash/public/cpp/external_arc/message_center/arc_notification_delegate.h
+++ b/ash/public/cpp/external_arc/message_center/arc_notification_delegate.h
@@ -25,6 +25,9 @@
  public:
   explicit ArcNotificationDelegate(base::WeakPtr<ArcNotificationItem> item);
 
+  ArcNotificationDelegate(const ArcNotificationDelegate&) = delete;
+  ArcNotificationDelegate& operator=(const ArcNotificationDelegate&) = delete;
+
   // Creates a view for the given notification (which must have been the one
   // generated by |item_|).
   std::unique_ptr<message_center::MessageView> CreateCustomMessageView(
@@ -44,8 +47,6 @@
   // around ARC notification is somewhat complex so we want to use it until
   // it gets stable.
   base::WeakPtr<ArcNotificationItem> item_;
-
-  DISALLOW_COPY_AND_ASSIGN(ArcNotificationDelegate);
 };
 
 }  // namespace ash
diff --git a/ash/public/cpp/external_arc/message_center/arc_notification_manager.cc b/ash/public/cpp/external_arc/message_center/arc_notification_manager.cc
index 8187541..28245971 100644
--- a/ash/public/cpp/external_arc/message_center/arc_notification_manager.cc
+++ b/ash/public/cpp/external_arc/message_center/arc_notification_manager.cc
@@ -61,20 +61,26 @@
  public:
   explicit DoNotDisturbManager(ArcNotificationManager* manager)
       : manager_(manager) {}
+
+  DoNotDisturbManager(const DoNotDisturbManager&) = delete;
+  DoNotDisturbManager& operator=(const DoNotDisturbManager&) = delete;
+
   void OnQuietModeChanged(bool in_quiet_mode) override {
     manager_->SetDoNotDisturbStatusOnAndroid(in_quiet_mode);
   }
 
  private:
   ArcNotificationManager* const manager_;
-
-  DISALLOW_COPY_AND_ASSIGN(DoNotDisturbManager);
 };
 
 class VisibilityManager : public message_center::MessageCenterObserver {
  public:
   explicit VisibilityManager(ArcNotificationManager* manager)
       : manager_(manager) {}
+
+  VisibilityManager(const VisibilityManager&) = delete;
+  VisibilityManager& operator=(const VisibilityManager&) = delete;
+
   void OnCenterVisibilityChanged(
       message_center::Visibility visibility) override {
     manager_->OnMessageCenterVisibilityChanged(toMojom(visibility));
@@ -92,8 +98,6 @@
   }
 
   ArcNotificationManager* const manager_;
-
-  DISALLOW_COPY_AND_ASSIGN(VisibilityManager);
 };
 
 }  // namespace
diff --git a/ash/public/cpp/external_arc/message_center/arc_notification_surface_manager.h b/ash/public/cpp/external_arc/message_center/arc_notification_surface_manager.h
index 11054f1..d182d66 100644
--- a/ash/public/cpp/external_arc/message_center/arc_notification_surface_manager.h
+++ b/ash/public/cpp/external_arc/message_center/arc_notification_surface_manager.h
@@ -31,6 +31,10 @@
   };
   static ArcNotificationSurfaceManager* Get();
 
+  ArcNotificationSurfaceManager(const ArcNotificationSurfaceManager&) = delete;
+  ArcNotificationSurfaceManager& operator=(
+      const ArcNotificationSurfaceManager&) = delete;
+
   virtual ~ArcNotificationSurfaceManager();
 
   virtual ArcNotificationSurface* GetArcSurface(
@@ -43,8 +47,6 @@
 
  private:
   static ArcNotificationSurfaceManager* instance_;
-
-  DISALLOW_COPY_AND_ASSIGN(ArcNotificationSurfaceManager);
 };
 
 }  // namespace ash
diff --git a/ash/public/cpp/external_arc/message_center/arc_notification_view_unittest.cc b/ash/public/cpp/external_arc/message_center/arc_notification_view_unittest.cc
index 1e134d8..d1893ed 100644
--- a/ash/public/cpp/external_arc/message_center/arc_notification_view_unittest.cc
+++ b/ash/public/cpp/external_arc/message_center/arc_notification_view_unittest.cc
@@ -46,14 +46,15 @@
  public:
   TestTextInputClient() : ui::DummyTextInputClient(ui::TEXT_INPUT_TYPE_TEXT) {}
 
+  TestTextInputClient(const TestTextInputClient&) = delete;
+  TestTextInputClient& operator=(const TestTextInputClient&) = delete;
+
   ui::TextInputType GetTextInputType() const override { return type_; }
 
   void set_text_input_type(ui::TextInputType type) { type_ = type; }
 
  private:
   ui::TextInputType type_ = ui::TEXT_INPUT_TYPE_NONE;
-
-  DISALLOW_COPY_AND_ASSIGN(TestTextInputClient);
 };
 
 }  // namespace
diff --git a/ash/public/cpp/login_screen_test_api.h b/ash/public/cpp/login_screen_test_api.h
index 0d09c1c1..2c61d19 100644
--- a/ash/public/cpp/login_screen_test_api.h
+++ b/ash/public/cpp/login_screen_test_api.h
@@ -20,6 +20,10 @@
 
 class ASH_PUBLIC_EXPORT LoginScreenTestApi {
  public:
+  LoginScreenTestApi() = delete;
+  LoginScreenTestApi(const LoginScreenTestApi&) = delete;
+  LoginScreenTestApi& operator=(const LoginScreenTestApi&) = delete;
+
   static bool IsLockShown();
   // Schedules the callback to be run when the LockScreen is shown. Note that
   // the LockScreen class is used for both the Lock and the Login screens.
@@ -95,9 +99,6 @@
   static std::u16string GetPinRequestWidgetTitle();
   static void SubmitPinRequestWidget(const std::string& pin);
   static void CancelPinRequestWidget();
-
- private:
-  DISALLOW_IMPLICIT_CONSTRUCTORS(LoginScreenTestApi);
 };
 
 }  // namespace ash
diff --git a/ash/public/cpp/night_light_controller.h b/ash/public/cpp/night_light_controller.h
index a5b49a3a..b559bd2 100644
--- a/ash/public/cpp/night_light_controller.h
+++ b/ash/public/cpp/night_light_controller.h
@@ -61,6 +61,9 @@
 
   static NightLightController* GetInstance();
 
+  NightLightController(const NightLightController&) = delete;
+  NightLightController& operator=(const NightLightController&) = delete;
+
   // Provides the NightLightController with the user's geoposition so that it
   // can calculate the sunset and sunrise times. This should only be called when
   // the schedule type is set to "Sunset to Sunrise".
@@ -77,9 +80,6 @@
   virtual ~NightLightController();
 
   base::ObserverList<Observer>::Unchecked observers_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(NightLightController);
 };
 
 }  // namespace ash
diff --git a/ash/public/cpp/note_taking_client.h b/ash/public/cpp/note_taking_client.h
index ce22ba3..04f48961 100644
--- a/ash/public/cpp/note_taking_client.h
+++ b/ash/public/cpp/note_taking_client.h
@@ -16,6 +16,9 @@
  public:
   static NoteTakingClient* GetInstance();
 
+  NoteTakingClient(const NoteTakingClient&) = delete;
+  NoteTakingClient& operator=(const NoteTakingClient&) = delete;
+
   // Returns true when it can create notes.
   virtual bool CanCreateNote() = 0;
 
@@ -25,9 +28,6 @@
  protected:
   NoteTakingClient();
   virtual ~NoteTakingClient();
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(NoteTakingClient);
 };
 
 }  // namespace ash
diff --git a/ash/public/cpp/notifier_settings_controller.h b/ash/public/cpp/notifier_settings_controller.h
index 541929c..e560f1a 100644
--- a/ash/public/cpp/notifier_settings_controller.h
+++ b/ash/public/cpp/notifier_settings_controller.h
@@ -23,6 +23,10 @@
   // Returns the singleton instance.
   static NotifierSettingsController* Get();
 
+  NotifierSettingsController(const NotifierSettingsController&) = delete;
+  NotifierSettingsController& operator=(const NotifierSettingsController&) =
+      delete;
+
   // Assembles the list of active notifiers and updates all
   // NotifierSettingsObservers via OnNotifiersUpdated.
   virtual void GetNotifiers() = 0;
@@ -40,8 +44,6 @@
  protected:
   NotifierSettingsController();
   virtual ~NotifierSettingsController();
-
-  DISALLOW_COPY_AND_ASSIGN(NotifierSettingsController);
 };
 
 }  // namespace ash
diff --git a/ash/public/cpp/presentation_time_recorder.h b/ash/public/cpp/presentation_time_recorder.h
index 6d23fb5..773049451 100644
--- a/ash/public/cpp/presentation_time_recorder.h
+++ b/ash/public/cpp/presentation_time_recorder.h
@@ -31,6 +31,9 @@
    public:
     explicit TestApi(PresentationTimeRecorder* recorder);
 
+    TestApi(const TestApi&) = delete;
+    TestApi& operator=(const TestApi&) = delete;
+
     void OnCompositingDidCommit(ui::Compositor* compositor);
     void OnPresented(int count,
                      base::TimeTicks requested_time,
@@ -42,11 +45,14 @@
 
    private:
     PresentationTimeRecorder* recorder_;
-    DISALLOW_COPY_AND_ASSIGN(TestApi);
   };
 
   explicit PresentationTimeRecorder(
       std::unique_ptr<PresentationTimeRecorderInternal> internal);
+
+  PresentationTimeRecorder(const PresentationTimeRecorder&) = delete;
+  PresentationTimeRecorder& operator=(const PresentationTimeRecorder&) = delete;
+
   ~PresentationTimeRecorder();
 
   // Start recording next frame. It skips requesting next frame and returns
@@ -59,8 +65,6 @@
 
  private:
   std::unique_ptr<PresentationTimeRecorderInternal> recorder_internal_;
-
-  DISALLOW_COPY_AND_ASSIGN(PresentationTimeRecorder);
 };
 
 // Creates a PresentationTimeRecorder that records timing histograms of
diff --git a/ash/public/cpp/shelf_model_unittest.cc b/ash/public/cpp/shelf_model_unittest.cc
index 17de111b..e5442c0e 100644
--- a/ash/public/cpp/shelf_model_unittest.cc
+++ b/ash/public/cpp/shelf_model_unittest.cc
@@ -22,6 +22,9 @@
  public:
   TestShelfModelObserver() = default;
 
+  TestShelfModelObserver(const TestShelfModelObserver&) = delete;
+  TestShelfModelObserver& operator=(const TestShelfModelObserver&) = delete;
+
   // Returns a string description of the changes that have occurred since this
   // was last invoked. Resets state to initial state.
   std::string StateStringAndClear() {
@@ -61,8 +64,6 @@
   int changed_count_ = 0;
   int moved_count_ = 0;
   int delegate_changed_count_ = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(TestShelfModelObserver);
 };
 
 }  // namespace
diff --git a/ash/public/cpp/wallpaper/wallpaper_controller_observer.h b/ash/public/cpp/wallpaper/wallpaper_controller_observer.h
index 1ef400a..fdc5aca 100644
--- a/ash/public/cpp/wallpaper/wallpaper_controller_observer.h
+++ b/ash/public/cpp/wallpaper/wallpaper_controller_observer.h
@@ -15,6 +15,10 @@
  public:
   WallpaperControllerObserver();
 
+  WallpaperControllerObserver(const WallpaperControllerObserver&) = delete;
+  WallpaperControllerObserver& operator=(const WallpaperControllerObserver&) =
+      delete;
+
   // Invoked when the wallpaper is about to change.
   virtual void OnWallpaperChanging() {}
 
@@ -41,9 +45,6 @@
 
  protected:
   virtual ~WallpaperControllerObserver();
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(WallpaperControllerObserver);
 };
 
 }  // namespace ash
diff --git a/ash/root_window_controller_unittest.cc b/ash/root_window_controller_unittest.cc
index f2a5cbf..47f1604 100644
--- a/ash/root_window_controller_unittest.cc
+++ b/ash/root_window_controller_unittest.cc
@@ -735,6 +735,9 @@
  public:
   MockTextInputClient() : ui::DummyTextInputClient(ui::TEXT_INPUT_TYPE_TEXT) {}
 
+  MockTextInputClient(const MockTextInputClient&) = delete;
+  MockTextInputClient& operator=(const MockTextInputClient&) = delete;
+
   void EnsureCaretNotInRect(const gfx::Rect& rect) override {
     caret_exclude_rect_ = rect;
   }
@@ -743,23 +746,22 @@
 
  private:
   gfx::Rect caret_exclude_rect_;
-
-  DISALLOW_COPY_AND_ASSIGN(MockTextInputClient);
 };
 
 class TargetHitTestEventHandler : public ui::test::TestEventHandler {
  public:
   TargetHitTestEventHandler() = default;
 
+  TargetHitTestEventHandler(const TargetHitTestEventHandler&) = delete;
+  TargetHitTestEventHandler& operator=(const TargetHitTestEventHandler&) =
+      delete;
+
   // ui::test::TestEventHandler overrides.
   void OnMouseEvent(ui::MouseEvent* event) override {
     if (event->type() == ui::ET_MOUSE_PRESSED)
       ui::test::TestEventHandler::OnMouseEvent(event);
     event->StopPropagation();
   }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(TargetHitTestEventHandler);
 };
 
 // Test for http://crbug.com/263599. Virtual keyboard should be able to receive
diff --git a/ash/rotator/screen_rotation_animator_unittest.cc b/ash/rotator/screen_rotation_animator_unittest.cc
index 28443fa..14d4d9a 100644
--- a/ash/rotator/screen_rotation_animator_unittest.cc
+++ b/ash/rotator/screen_rotation_animator_unittest.cc
@@ -60,6 +60,9 @@
  public:
   AnimationObserver() = default;
 
+  AnimationObserver(const AnimationObserver&) = delete;
+  AnimationObserver& operator=(const AnimationObserver&) = delete;
+
   bool copy_notified() const { return copy_notified_; }
   bool finish_notified() const { return finish_notified_; }
 
@@ -72,8 +75,6 @@
  private:
   bool copy_notified_ = false;
   bool finish_notified_ = false;
-
-  DISALLOW_COPY_AND_ASSIGN(AnimationObserver);
 };
 
 class TestScreenRotationAnimator : public ScreenRotationAnimator {
diff --git a/ash/session/multiprofiles_intro_dialog.h b/ash/session/multiprofiles_intro_dialog.h
index bb5af9fc..427e23e 100644
--- a/ash/session/multiprofiles_intro_dialog.h
+++ b/ash/session/multiprofiles_intro_dialog.h
@@ -23,6 +23,9 @@
 
   static void Show(OnAcceptCallback on_accept);
 
+  MultiprofilesIntroDialog(const MultiprofilesIntroDialog&) = delete;
+  MultiprofilesIntroDialog& operator=(const MultiprofilesIntroDialog&) = delete;
+
   // views::View overrides.
   gfx::Size CalculatePreferredSize() const override;
 
@@ -34,8 +37,6 @@
 
   views::Checkbox* never_show_again_checkbox_;
   OnAcceptCallback on_accept_;
-
-  DISALLOW_COPY_AND_ASSIGN(MultiprofilesIntroDialog);
 };
 
 }  // namespace ash
diff --git a/ash/session/session_aborted_dialog.h b/ash/session/session_aborted_dialog.h
index db74931..eddf0c52 100644
--- a/ash/session/session_aborted_dialog.h
+++ b/ash/session/session_aborted_dialog.h
@@ -18,6 +18,9 @@
  public:
   static void Show(const std::string& user_email);
 
+  SessionAbortedDialog(const SessionAbortedDialog&) = delete;
+  SessionAbortedDialog& operator=(const SessionAbortedDialog&) = delete;
+
   // views::View overrides.
   gfx::Size CalculatePreferredSize() const override;
 
@@ -26,8 +29,6 @@
   ~SessionAbortedDialog() override;
 
   void InitDialog(const std::string& user_email);
-
-  DISALLOW_COPY_AND_ASSIGN(SessionAbortedDialog);
 };
 
 }  // namespace ash
diff --git a/ash/shelf/home_button.h b/ash/shelf/home_button.h
index 9ad36eb..11a9963 100644
--- a/ash/shelf/home_button.h
+++ b/ash/shelf/home_button.h
@@ -47,6 +47,10 @@
   static const char kViewClassName[];
 
   explicit HomeButton(Shelf* shelf);
+
+  HomeButton(const HomeButton&) = delete;
+  HomeButton& operator=(const HomeButton&) = delete;
+
   ~HomeButton() override;
 
   // views::Button:
@@ -91,8 +95,6 @@
 
   // The controller used to determine the button's behavior.
   HomeButtonController controller_;
-
-  DISALLOW_COPY_AND_ASSIGN(HomeButton);
 };
 
 }  // namespace ash
diff --git a/ash/shelf/hotseat_widget.h b/ash/shelf/hotseat_widget.h
index 861f694..830202d 100644
--- a/ash/shelf/hotseat_widget.h
+++ b/ash/shelf/hotseat_widget.h
@@ -66,6 +66,10 @@
   };
 
   HotseatWidget();
+
+  HotseatWidget(const HotseatWidget&) = delete;
+  HotseatWidget& operator=(const HotseatWidget&) = delete;
+
   ~HotseatWidget() override;
 
   // Returns whether the hotseat background should be shown.
@@ -257,8 +261,6 @@
   // on the non visible portion of the hotseat, or events that reach the hotseat
   // during an animation.
   std::unique_ptr<aura::ScopedWindowTargeter> hotseat_window_targeter_;
-
-  DISALLOW_COPY_AND_ASSIGN(HotseatWidget);
 };
 
 }  // namespace ash
diff --git a/ash/shelf/login_shelf_view.cc b/ash/shelf/login_shelf_view.cc
index 9995ab2..ab40718 100644
--- a/ash/shelf/login_shelf_view.cc
+++ b/ash/shelf/login_shelf_view.cc
@@ -352,6 +352,9 @@
         1, gfx::Font::FontStyle::NORMAL, gfx::Font::Weight::NORMAL));
   }
 
+  KioskAppsButton(const KioskAppsButton&) = delete;
+  KioskAppsButton& operator=(const KioskAppsButton&) = delete;
+
   bool LaunchAppForTesting(const std::string& app_id) {
     for (size_t i = 0; i < kiosk_apps_.size(); ++i) {
       if (kiosk_apps_[i].app_id == app_id) {
@@ -449,8 +452,6 @@
   std::vector<KioskAppMenuEntry> kiosk_apps_;
 
   bool is_launch_enabled_ = true;
-
-  DISALLOW_COPY_AND_ASSIGN(KioskAppsButton);
 };
 
 // Class that temporarily disables Guest login buttin on shelf.
diff --git a/ash/shelf/shelf.h b/ash/shelf/shelf.h
index 92725f2..b119b5c 100644
--- a/ash/shelf/shelf.h
+++ b/ash/shelf/shelf.h
@@ -70,6 +70,10 @@
   };
 
   Shelf();
+
+  Shelf(const Shelf&) = delete;
+  Shelf& operator=(const Shelf&) = delete;
+
   ~Shelf() override;
 
   // Returns the shelf for the display that |window| is on. Note that the shelf
@@ -322,8 +326,6 @@
   int auto_hide_lock_ = 0;
 
   std::unique_ptr<ShelfTooltipManager> tooltip_;
-
-  DISALLOW_COPY_AND_ASSIGN(Shelf);
 };
 
 }  // namespace ash
diff --git a/ash/shelf/shelf_app_button.cc b/ash/shelf/shelf_app_button.cc
index a7457091..0affda1 100644
--- a/ash/shelf/shelf_app_button.cc
+++ b/ash/shelf/shelf_app_button.cc
@@ -84,6 +84,9 @@
     virtual ~Observer() = default;
   };
 
+  ShelfAppButtonAnimation(const ShelfAppButtonAnimation&) = delete;
+  ShelfAppButtonAnimation& operator=(const ShelfAppButtonAnimation&) = delete;
+
   static ShelfAppButtonAnimation* GetInstance() {
     static ShelfAppButtonAnimation* s_instance = new ShelfAppButtonAnimation();
     return s_instance;
@@ -136,8 +139,6 @@
 
   gfx::ThrobAnimation animation_;
   base::ObserverList<Observer>::Unchecked observers_;
-
-  DISALLOW_COPY_AND_ASSIGN(ShelfAppButtonAnimation);
 };
 
 }  // namespace
diff --git a/ash/shelf/shelf_button_pressed_metric_tracker_unittest.cc b/ash/shelf/shelf_button_pressed_metric_tracker_unittest.cc
index 42777971..e6ae884 100644
--- a/ash/shelf/shelf_button_pressed_metric_tracker_unittest.cc
+++ b/ash/shelf/shelf_button_pressed_metric_tracker_unittest.cc
@@ -26,8 +26,8 @@
  public:
   DummyButton();
 
- private:
-  DISALLOW_COPY_AND_ASSIGN(DummyButton);
+  DummyButton(const DummyButton&) = delete;
+  DummyButton& operator=(const DummyButton&) = delete;
 };
 
 DummyButton::DummyButton() : views::Button(views::Button::PressedCallback()) {}
diff --git a/ash/shelf/shelf_layout_manager.h b/ash/shelf/shelf_layout_manager.h
index f2bcd531..469d058 100644
--- a/ash/shelf/shelf_layout_manager.h
+++ b/ash/shelf/shelf_layout_manager.h
@@ -114,6 +114,10 @@
   };
 
   ShelfLayoutManager(ShelfWidget* shelf_widget, Shelf* shelf);
+
+  ShelfLayoutManager(const ShelfLayoutManager&) = delete;
+  ShelfLayoutManager& operator=(const ShelfLayoutManager&) = delete;
+
   ~ShelfLayoutManager() override;
 
   // Initializes observers.
@@ -730,8 +734,6 @@
   std::unique_ptr<PresentationTimeRecorder> hotseat_presentation_time_recorder_;
 
   base::WeakPtrFactory<ShelfLayoutManager> weak_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(ShelfLayoutManager);
 };
 
 }  // namespace ash
diff --git a/ash/shelf/shelf_locking_manager_unittest.cc b/ash/shelf/shelf_locking_manager_unittest.cc
index cae59b6..63a07f7 100644
--- a/ash/shelf/shelf_locking_manager_unittest.cc
+++ b/ash/shelf/shelf_locking_manager_unittest.cc
@@ -15,6 +15,9 @@
  public:
   ShelfLockingManagerTest() = default;
 
+  ShelfLockingManagerTest(const ShelfLockingManagerTest&) = delete;
+  ShelfLockingManagerTest& operator=(const ShelfLockingManagerTest&) = delete;
+
   ShelfLockingManager* GetShelfLockingManager() {
     return GetPrimaryShelf()->GetShelfLockingManagerForTesting();
   }
@@ -26,9 +29,6 @@
   void SetSessionState(session_manager::SessionState state) {
     GetShelfLockingManager()->OnSessionStateChanged(state);
   }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ShelfLockingManagerTest);
 };
 
 // Makes sure shelf alignment is correct for lock screen.
diff --git a/ash/shelf/shelf_navigation_widget.h b/ash/shelf/shelf_navigation_widget.h
index 9b2ce490..1d610a6 100644
--- a/ash/shelf/shelf_navigation_widget.h
+++ b/ash/shelf/shelf_navigation_widget.h
@@ -52,6 +52,10 @@
   };
 
   ShelfNavigationWidget(Shelf* shelf, ShelfView* shelf_view);
+
+  ShelfNavigationWidget(const ShelfNavigationWidget&) = delete;
+  ShelfNavigationWidget& operator=(const ShelfNavigationWidget&) = delete;
+
   ~ShelfNavigationWidget() override;
 
   // Initializes the widget, sets its contents view and basic properties.
@@ -139,8 +143,6 @@
   // Widget to ensure it outlives the HomeButton view.
   std::unique_ptr<NavigationButtonAnimationMetricsReporter>
       home_button_metrics_reporter_;
-
-  DISALLOW_COPY_AND_ASSIGN(ShelfNavigationWidget);
 };
 
 }  // namespace ash
diff --git a/ash/shelf/shelf_test_util.h b/ash/shelf/shelf_test_util.h
index b9f9dca..a1e2898 100644
--- a/ash/shelf/shelf_test_util.h
+++ b/ash/shelf/shelf_test_util.h
@@ -18,6 +18,9 @@
 
 class ShelfTestUtil {
  public:
+  ShelfTestUtil(const ShelfTestUtil&) = delete;
+  ShelfTestUtil& operator=(const ShelfTestUtil&) = delete;
+
   // Adds an application shortcut to the shelf model, with the given identifier
   // and the given shelf item type.
   static ShelfItem AddAppShortcut(const std::string& id, ShelfItemType type);
@@ -27,7 +30,6 @@
   static ShelfItem AddAppShortcutWithIcon(const std::string& id,
                                           ShelfItemType type,
                                           gfx::ImageSkia icon);
-  DISALLOW_COPY_AND_ASSIGN(ShelfTestUtil);
 };
 
 // Waits for an overview enter animation if |enter|; waits for an overview exit
diff --git a/ash/shelf/shelf_tooltip_bubble.h b/ash/shelf/shelf_tooltip_bubble.h
index f03d7ba..0d33a7d9 100644
--- a/ash/shelf/shelf_tooltip_bubble.h
+++ b/ash/shelf/shelf_tooltip_bubble.h
@@ -23,6 +23,9 @@
                      SkColor background_color,
                      const std::u16string& text);
 
+  ShelfTooltipBubble(const ShelfTooltipBubble&) = delete;
+  ShelfTooltipBubble& operator=(const ShelfTooltipBubble&) = delete;
+
  protected:
   // ShelfBubble:
   bool ShouldCloseOnPressDown() override;
@@ -31,8 +34,6 @@
  private:
   // BubbleDialogDelegateView overrides:
   gfx::Size CalculatePreferredSize() const override;
-
-  DISALLOW_COPY_AND_ASSIGN(ShelfTooltipBubble);
 };
 
 }  // namespace ash
diff --git a/ash/shelf/shelf_view_unittest.cc b/ash/shelf/shelf_view_unittest.cc
index 50471d1..77d4d298 100644
--- a/ash/shelf/shelf_view_unittest.cc
+++ b/ash/shelf/shelf_view_unittest.cc
@@ -2356,6 +2356,10 @@
  public:
   ShelfViewVisibleBoundsTest() : scoped_locale_(GetParam() ? "he" : "") {}
 
+  ShelfViewVisibleBoundsTest(const ShelfViewVisibleBoundsTest&) = delete;
+  ShelfViewVisibleBoundsTest& operator=(const ShelfViewVisibleBoundsTest&) =
+      delete;
+
   void CheckAllItemsAreInBounds() {
     gfx::Rect visible_bounds = shelf_view_->GetVisibleItemsBoundsInScreen();
     gfx::Rect shelf_bounds = shelf_view_->GetBoundsInScreen();
@@ -2370,8 +2374,6 @@
  private:
   // Restores locale to the default when destructor is called.
   base::test::ScopedRestoreICUDefaultLocale scoped_locale_;
-
-  DISALLOW_COPY_AND_ASSIGN(ShelfViewVisibleBoundsTest);
 };
 
 TEST_P(ShelfViewVisibleBoundsTest, ItemsAreInBounds) {
diff --git a/ash/shelf/window_preview.h b/ash/shelf/window_preview.h
index e16a9d8..16bc06c2 100644
--- a/ash/shelf/window_preview.h
+++ b/ash/shelf/window_preview.h
@@ -45,6 +45,10 @@
   WindowPreview(aura::Window* window,
                 Delegate* delegate,
                 const ui::NativeTheme* theme);
+
+  WindowPreview(const WindowPreview&) = delete;
+  WindowPreview& operator=(const WindowPreview&) = delete;
+
   ~WindowPreview() override;
 
   // views::View:
@@ -71,8 +75,6 @@
 
   // Unowned pointer to the delegate. The delegate should outlive this instance.
   Delegate* delegate_;
-
-  DISALLOW_COPY_AND_ASSIGN(WindowPreview);
 };
 
 }  // namespace ash
diff --git a/ash/shell.cc b/ash/shell.cc
index e42b1609..ca8d6eb 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -147,7 +147,6 @@
 #include "ash/wm/desks/desks_controller.h"
 #include "ash/wm/desks/persistent_desks_bar_controller.h"
 #include "ash/wm/event_client_impl.h"
-#include "ash/wm/full_restore/full_restore_controller.h"
 #include "ash/wm/gestures/back_gesture/back_gesture_event_handler.h"
 #include "ash/wm/immersive_context_ash.h"
 #include "ash/wm/lock_state_controller.h"
@@ -168,6 +167,7 @@
 #include "ash/wm/window_cycle/window_cycle_controller.h"
 #include "ash/wm/window_positioner.h"
 #include "ash/wm/window_properties.h"
+#include "ash/wm/window_restore/window_restore_controller.h"
 #include "ash/wm/window_util.h"
 #include "ash/wm/wm_shadow_controller_delegate.h"
 #include "ash/wm/workspace_controller.h"
@@ -657,7 +657,7 @@
   keyboard_controller_->DestroyVirtualKeyboard();
 
   // Depends on |tablet_mode_controller_|.
-  full_restore_controller_.reset();
+  window_restore_controller_.reset();
   shelf_controller_->Shutdown();
   shelf_config_->Shutdown();
 
@@ -1243,10 +1243,10 @@
   // WindowTreeHostManager to host the keyboard window.
   keyboard_controller_->CreateVirtualKeyboard(std::move(keyboard_ui_factory));
 
-  // Create full restore controller after WindowTreeHostManager::InitHosts()
+  // Create window restore controller after WindowTreeHostManager::InitHosts()
   // since it may need to add observers to root windows.
   if (full_restore::features::IsFullRestoreEnabled())
-    full_restore_controller_ = std::make_unique<FullRestoreController>();
+    window_restore_controller_ = std::make_unique<WindowRestoreController>();
 
   cursor_manager_->HideCursor();  // Hide the mouse cursor on startup.
   cursor_manager_->SetCursor(ui::mojom::CursorType::kPointer);
diff --git a/ash/shell.h b/ash/shell.h
index eb62f70..12122b7 100644
--- a/ash/shell.h
+++ b/ash/shell.h
@@ -121,7 +121,7 @@
 class EventClientImpl;
 class EventRewriterControllerImpl;
 class EventTransformationHandler;
-class FullRestoreController;
+class WindowRestoreController;
 class FocusCycler;
 class FrameThrottlingController;
 class FullscreenMagnifierController;
@@ -224,6 +224,9 @@
  public:
   typedef std::vector<RootWindowController*> RootWindowControllerList;
 
+  Shell(const Shell&) = delete;
+  Shell& operator=(const Shell&) = delete;
+
   // Creates the single Shell instance.
   static Shell* CreateInstance(ShellInitParams init_params);
 
@@ -722,7 +725,7 @@
   std::unique_ptr<DisplaySpeakerController> display_speaker_controller_;
   std::unique_ptr<DragDropController> drag_drop_controller_;
   std::unique_ptr<FocusCycler> focus_cycler_;
-  std::unique_ptr<FullRestoreController> full_restore_controller_;
+  std::unique_ptr<WindowRestoreController> window_restore_controller_;
   std::unique_ptr<HoldingSpaceController> holding_space_controller_;
   std::unique_ptr<ImeControllerImpl> ime_controller_;
   std::unique_ptr<chromeos::ImmersiveContext> immersive_context_;
@@ -901,8 +904,6 @@
   base::ObserverList<ShellObserver>::Unchecked shell_observers_;
 
   base::WeakPtrFactory<Shell> weak_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(Shell);
 };
 
 }  // namespace ash
diff --git a/ash/style/ash_color_provider.cc b/ash/style/ash_color_provider.cc
index 785b277..71c4736 100644
--- a/ash/style/ash_color_provider.cc
+++ b/ash/style/ash_color_provider.cc
@@ -354,6 +354,12 @@
   if (!features::IsDarkLightModeEnabled() && override_light_mode_as_default_)
     return false;
 
+  // Keep colors in OOBE as LIGHT regardless `kDarkLightMode` is enabled or not.
+  if (Shell::Get()->session_controller()->GetSessionState() ==
+      session_manager::SessionState::OOBE) {
+    return false;
+  }
+
   // Keep it at dark mode if it is not in an active user session or
   // kDarkLightMode feature is not enabled.
   // TODO(minch): Make LIGHT as the color mode while it is not in an active user
diff --git a/ash/style/ash_color_provider_unittests.cc b/ash/style/ash_color_provider_unittests.cc
new file mode 100644
index 0000000..fb2ab1e
--- /dev/null
+++ b/ash/style/ash_color_provider_unittests.cc
@@ -0,0 +1,40 @@
+// 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 "ash/style/ash_color_provider.h"
+
+#include "ash/constants/ash_features.h"
+#include "ash/session/test_session_controller_client.h"
+#include "ash/test/ash_test_base.h"
+#include "base/test/scoped_feature_list.h"
+
+namespace ash {
+
+using AshColorProviderTest = AshTestBase;
+
+// Tests the color mode in non-active user sessions.
+TEST_F(AshColorProviderTest, ColorModeInNonActiveUserSessions) {
+  auto* client = GetSessionControllerClient();
+  auto* color_provider = AshColorProvider::Get();
+
+  // When dark/light mode is enabled. Color mode in non-active user sessions
+  // (e.g, login page) should be DARK, but LIGHT while in OOBE.
+  base::test::ScopedFeatureList enable_dark_light;
+  enable_dark_light.InitAndEnableFeature(features::kDarkLightMode);
+  client->SetSessionState(session_manager::SessionState::UNKNOWN);
+  EXPECT_TRUE(color_provider->IsDarkModeEnabled());
+  client->SetSessionState(session_manager::SessionState::OOBE);
+  EXPECT_FALSE(color_provider->IsDarkModeEnabled());
+
+  // When dark/light mode is disabled. Color mode in non-active user sessions
+  // (e.g, login page) should still be DARK, but LIGHT while in OOBE.
+  base::test::ScopedFeatureList disable_dark_light;
+  disable_dark_light.InitAndDisableFeature(features::kDarkLightMode);
+  client->SetSessionState(session_manager::SessionState::UNKNOWN);
+  EXPECT_TRUE(color_provider->IsDarkModeEnabled());
+  client->SetSessionState(session_manager::SessionState::OOBE);
+  EXPECT_FALSE(color_provider->IsDarkModeEnabled());
+}
+
+}  // namespace ash
diff --git a/ash/system/accessibility/tray_accessibility_unittest.cc b/ash/system/accessibility/tray_accessibility_unittest.cc
index e0982900..cc78f245 100644
--- a/ash/system/accessibility/tray_accessibility_unittest.cc
+++ b/ash/system/accessibility/tray_accessibility_unittest.cc
@@ -104,6 +104,10 @@
 }  // namespace
 
 class TrayAccessibilityTest : public AshTestBase, public AccessibilityObserver {
+ public:
+  TrayAccessibilityTest(const TrayAccessibilityTest&) = delete;
+  TrayAccessibilityTest& operator=(const TrayAccessibilityTest&) = delete;
+
  protected:
   TrayAccessibilityTest() = default;
   ~TrayAccessibilityTest() override = default;
@@ -385,8 +389,6 @@
 
   std::unique_ptr<DetailedViewDelegate> delegate_;
   std::unique_ptr<tray::AccessibilityDetailedView> detailed_menu_;
-
-  DISALLOW_COPY_AND_ASSIGN(TrayAccessibilityTest);
 };
 
 TEST_F(TrayAccessibilityTest, CheckMenuVisibilityOnDetailMenu) {
@@ -748,12 +750,15 @@
 }
 
 class TrayAccessibilityLoginScreenTest : public TrayAccessibilityTest {
+ public:
+  TrayAccessibilityLoginScreenTest(const TrayAccessibilityLoginScreenTest&) =
+      delete;
+  TrayAccessibilityLoginScreenTest& operator=(
+      const TrayAccessibilityLoginScreenTest&) = delete;
+
  protected:
   TrayAccessibilityLoginScreenTest() { set_start_session(false); }
   ~TrayAccessibilityLoginScreenTest() override = default;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(TrayAccessibilityLoginScreenTest);
 };
 
 TEST_F(TrayAccessibilityLoginScreenTest, CheckMarksOnDetailMenu) {
diff --git a/ash/system/bluetooth/bluetooth_notification_controller.cc b/ash/system/bluetooth/bluetooth_notification_controller.cc
index a005243..23885099 100644
--- a/ash/system/bluetooth/bluetooth_notification_controller.cc
+++ b/ash/system/bluetooth/bluetooth_notification_controller.cc
@@ -52,6 +52,11 @@
                                        const std::string& address,
                                        const std::string& notification_id);
 
+  BluetoothPairingNotificationDelegate(
+      const BluetoothPairingNotificationDelegate&) = delete;
+  BluetoothPairingNotificationDelegate& operator=(
+      const BluetoothPairingNotificationDelegate&) = delete;
+
  protected:
   ~BluetoothPairingNotificationDelegate() override;
 
@@ -72,8 +77,6 @@
   // Address of the device being paired.
   const std::string address_;
   const std::string notification_id_;
-
-  DISALLOW_COPY_AND_ASSIGN(BluetoothPairingNotificationDelegate);
 };
 
 BluetoothPairingNotificationDelegate::BluetoothPairingNotificationDelegate(
@@ -140,6 +143,11 @@
  public:
   BluetoothPairedNotificationDelegate() = default;
 
+  BluetoothPairedNotificationDelegate(
+      const BluetoothPairedNotificationDelegate&) = delete;
+  BluetoothPairedNotificationDelegate& operator=(
+      const BluetoothPairedNotificationDelegate&) = delete;
+
  protected:
   ~BluetoothPairedNotificationDelegate() override = default;
 
@@ -149,9 +157,6 @@
     if (TrayPopupUtils::CanOpenWebUISettings())
       Shell::Get()->system_tray_model()->client()->ShowBluetoothSettings();
   }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(BluetoothPairedNotificationDelegate);
 };
 
 BluetoothNotificationController::BluetoothNotificationController(
diff --git a/ash/system/bluetooth/bluetooth_notification_controller_unittest.cc b/ash/system/bluetooth/bluetooth_notification_controller_unittest.cc
index a261520..8236c1c 100644
--- a/ash/system/bluetooth/bluetooth_notification_controller_unittest.cc
+++ b/ash/system/bluetooth/bluetooth_notification_controller_unittest.cc
@@ -61,6 +61,11 @@
  public:
   BluetoothNotificationControllerTest() = default;
 
+  BluetoothNotificationControllerTest(
+      const BluetoothNotificationControllerTest&) = delete;
+  BluetoothNotificationControllerTest& operator=(
+      const BluetoothNotificationControllerTest&) = delete;
+
   void SetUp() override {
     AshTestBase::SetUp();
 
@@ -156,8 +161,6 @@
   TestSystemTrayClient* system_tray_client_;
   std::unique_ptr<device::MockBluetoothDevice> bluetooth_device_1_;
   std::unique_ptr<device::MockBluetoothDevice> bluetooth_device_2_;
-
-  DISALLOW_COPY_AND_ASSIGN(BluetoothNotificationControllerTest);
 };
 
 TEST_F(BluetoothNotificationControllerTest, DiscoverableNotification) {
diff --git a/ash/system/ime_menu/ime_menu_tray.cc b/ash/system/ime_menu/ime_menu_tray.cc
index b38331f..44300131 100644
--- a/ash/system/ime_menu/ime_menu_tray.cc
+++ b/ash/system/ime_menu/ime_menu_tray.cc
@@ -268,6 +268,9 @@
    public:
     Delegate() : DetailedViewDelegate(nullptr /* tray_controller */) {}
 
+    Delegate(const Delegate&) = delete;
+    Delegate& operator=(const Delegate&) = delete;
+
     // DetailedViewDelegate:
     void TransitionToMainView(bool restore_focus) override {}
     void CloseBubble() override {}
@@ -275,9 +278,6 @@
     gfx::Insets GetInsetsForDetailedView() const override {
       return gfx::Insets();
     }
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(Delegate);
   };
 
   explicit ImeMenuListView(std::unique_ptr<Delegate> delegate)
diff --git a/ash/system/locale/locale_update_controller_impl.cc b/ash/system/locale/locale_update_controller_impl.cc
index b68f86f0..42c9fe8 100644
--- a/ash/system/locale/locale_update_controller_impl.cc
+++ b/ash/system/locale/locale_update_controller_impl.cc
@@ -35,6 +35,10 @@
   explicit LocaleNotificationDelegate(
       base::OnceCallback<void(LocaleNotificationResult)> callback);
 
+  LocaleNotificationDelegate(const LocaleNotificationDelegate&) = delete;
+  LocaleNotificationDelegate& operator=(const LocaleNotificationDelegate&) =
+      delete;
+
  protected:
   ~LocaleNotificationDelegate() override;
 
@@ -45,8 +49,6 @@
 
  private:
   base::OnceCallback<void(LocaleNotificationResult)> callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(LocaleNotificationDelegate);
 };
 
 LocaleNotificationDelegate::LocaleNotificationDelegate(
diff --git a/ash/system/message_center/message_center_ui_controller_unittest.cc b/ash/system/message_center/message_center_ui_controller_unittest.cc
index 3a60369..3ef5679 100644
--- a/ash/system/message_center/message_center_ui_controller_unittest.cc
+++ b/ash/system/message_center/message_center_ui_controller_unittest.cc
@@ -25,10 +25,11 @@
  public:
   TestNotificationDelegate() = default;
 
+  TestNotificationDelegate(const TestNotificationDelegate&) = delete;
+  TestNotificationDelegate& operator=(const TestNotificationDelegate&) = delete;
+
  private:
   ~TestNotificationDelegate() override = default;
-
-  DISALLOW_COPY_AND_ASSIGN(TestNotificationDelegate);
 };
 
 class MockDelegate : public MessageCenterUiDelegate {
diff --git a/ash/system/message_center/notifier_settings_view.cc b/ash/system/message_center/notifier_settings_view.cc
index 033412a9..76ad2bd 100644
--- a/ash/system/message_center/notifier_settings_view.cc
+++ b/ash/system/message_center/notifier_settings_view.cc
@@ -220,6 +220,9 @@
  public:
   ScrollContentsView() = default;
 
+  ScrollContentsView(const ScrollContentsView&) = delete;
+  ScrollContentsView& operator=(const ScrollContentsView&) = delete;
+
   // views::View:
   const char* GetClassName() const override { return "ScrollContentsView"; }
 
@@ -247,8 +250,6 @@
     canvas->ClipRect(shadowed_area, SkClipOp::kDifference);
     canvas->DrawRect(shadowed_area, flags);
   }
-
-  DISALLOW_COPY_AND_ASSIGN(ScrollContentsView);
 };
 
 // EmptyNotifierView -----------------------------------------------------------
@@ -285,6 +286,9 @@
     label_ = AddChildView(label);
   }
 
+  EmptyNotifierView(const EmptyNotifierView&) = delete;
+  EmptyNotifierView& operator=(const EmptyNotifierView&) = delete;
+
   // views::View:
   const char* GetClassName() const override { return "EmptyNotifierView"; }
 
@@ -296,7 +300,6 @@
   }
 
   views::Label* label_;
-  DISALLOW_COPY_AND_ASSIGN(EmptyNotifierView);
 };
 
 class NotifierViewCheckbox : public views::Checkbox {
diff --git a/ash/system/network/auto_connect_notifier_unittest.cc b/ash/system/network/auto_connect_notifier_unittest.cc
index ce15a34..316d239 100644
--- a/ash/system/network/auto_connect_notifier_unittest.cc
+++ b/ash/system/network/auto_connect_notifier_unittest.cc
@@ -36,6 +36,10 @@
 }  // namespace
 
 class AutoConnectNotifierTest : public AshTestBase {
+ public:
+  AutoConnectNotifierTest(const AutoConnectNotifierTest&) = delete;
+  AutoConnectNotifierTest& operator=(const AutoConnectNotifierTest&) = delete;
+
  protected:
   AutoConnectNotifierTest() = default;
   ~AutoConnectNotifierTest() override = default;
@@ -99,8 +103,6 @@
       network_handler_test_helper_;
   std::unique_ptr<chromeos::network_config::CrosNetworkConfigTestHelper>
       network_config_helper_;
-
-  DISALLOW_COPY_AND_ASSIGN(AutoConnectNotifierTest);
 };
 
 TEST_F(AutoConnectNotifierTest, NoExplicitConnectionRequested) {
diff --git a/ash/system/network/network_icon.cc b/ash/system/network/network_icon.cc
index bd951780..38c390a 100644
--- a/ash/system/network/network_icon.cc
+++ b/ash/system/network/network_icon.cc
@@ -50,6 +50,9 @@
                   IconType icon_type,
                   NetworkType network_type);
 
+  NetworkIconImpl(const NetworkIconImpl&) = delete;
+  NetworkIconImpl& operator=(const NetworkIconImpl&) = delete;
+
   // Determines whether or not the associated network might be dirty and if so
   // updates and generates the icon. Does nothing if network no longer exists.
   void Update(const NetworkStateProperties* network, bool show_vpn_badge);
@@ -82,8 +85,6 @@
 
   // Generated icon image.
   gfx::ImageSkia image_;
-
-  DISALLOW_COPY_AND_ASSIGN(NetworkIconImpl);
 };
 
 //------------------------------------------------------------------------------
diff --git a/ash/system/network/vpn_list.h b/ash/system/network/vpn_list.h
index 77ab02b..5096e3ee 100644
--- a/ash/system/network/vpn_list.h
+++ b/ash/system/network/vpn_list.h
@@ -32,16 +32,19 @@
   // the primary user's profile changes.
   class Observer {
    public:
+    Observer& operator=(const Observer&) = delete;
+
     virtual void OnVpnProvidersChanged() = 0;
 
    protected:
     virtual ~Observer();
-
-   private:
-    DISALLOW_ASSIGN(Observer);
   };
 
   explicit VpnList(TrayNetworkStateModel* model);
+
+  VpnList(const VpnList&) = delete;
+  VpnList& operator=(const VpnList&) = delete;
+
   ~VpnList() override;
 
   const std::vector<VpnProviderPtr>& extension_vpn_providers() {
@@ -90,8 +93,6 @@
   std::vector<VpnProviderPtr> arc_vpn_providers_;
 
   base::ObserverList<Observer>::Unchecked observer_list_;
-
-  DISALLOW_COPY_AND_ASSIGN(VpnList);
 };
 
 }  // namespace ash
diff --git a/ash/system/network/vpn_list_view.cc b/ash/system/network/vpn_list_view.cc
index 96414ec..c5379d5 100644
--- a/ash/system/network/vpn_list_view.cc
+++ b/ash/system/network/vpn_list_view.cc
@@ -162,6 +162,9 @@
     tri_view->AddView(TriView::Container::END, add_vpn_button);
   }
 
+  VPNListProviderEntry(const VPNListProviderEntry&) = delete;
+  VPNListProviderEntry& operator=(const VPNListProviderEntry&) = delete;
+
   // views::View:
   const char* GetClassName() const override { return "VPNListProviderEntry"; }
 
@@ -200,8 +203,6 @@
   }
 
   VpnProviderPtr vpn_provider_;
-
-  DISALLOW_COPY_AND_ASSIGN(VPNListProviderEntry);
 };
 
 // A list entry that represents a network. If the network is currently
diff --git a/ash/system/palette/common_palette_tool.h b/ash/system/palette/common_palette_tool.h
index 8765849..27d6502 100644
--- a/ash/system/palette/common_palette_tool.h
+++ b/ash/system/palette/common_palette_tool.h
@@ -23,6 +23,10 @@
 class CommonPaletteTool : public PaletteTool, public ViewClickListener {
  protected:
   explicit CommonPaletteTool(Delegate* delegate);
+
+  CommonPaletteTool(const CommonPaletteTool&) = delete;
+  CommonPaletteTool& operator=(const CommonPaletteTool&) = delete;
+
   ~CommonPaletteTool() override;
 
   // PaletteTool:
@@ -46,8 +50,6 @@
   // start_time_ is initialized when the tool becomes active.
   // Used for recording UMA metrics.
   base::TimeTicks start_time_;
-
-  DISALLOW_COPY_AND_ASSIGN(CommonPaletteTool);
 };
 
 }  // namespace ash
diff --git a/ash/system/palette/palette_tool.h b/ash/system/palette/palette_tool.h
index b0be956..c48d963 100644
--- a/ash/system/palette/palette_tool.h
+++ b/ash/system/palette/palette_tool.h
@@ -67,6 +67,10 @@
 
   // |delegate| must outlive this tool instance.
   explicit PaletteTool(Delegate* delegate);
+
+  PaletteTool(const PaletteTool&) = delete;
+  PaletteTool& operator=(const PaletteTool&) = delete;
+
   virtual ~PaletteTool();
 
   // The group this tool belongs to. Only one tool per group can be active at
@@ -111,8 +115,6 @@
 
   // Unowned pointer to the delegate. The delegate should outlive this instance.
   Delegate* delegate_;
-
-  DISALLOW_COPY_AND_ASSIGN(PaletteTool);
 };
 
 }  // namespace ash
diff --git a/ash/system/palette/palette_tool_manager.h b/ash/system/palette/palette_tool_manager.h
index 939685f5..c953e648 100644
--- a/ash/system/palette/palette_tool_manager.h
+++ b/ash/system/palette/palette_tool_manager.h
@@ -64,6 +64,10 @@
 
   // Creates the tool manager.
   PaletteToolManager(Delegate* delegate);
+
+  PaletteToolManager(const PaletteToolManager&) = delete;
+  PaletteToolManager& operator=(const PaletteToolManager&) = delete;
+
   ~PaletteToolManager() override;
 
   // Returns true if the given tool has been added to the tool manager.
@@ -121,8 +125,6 @@
 
   // Owned list of all tools.
   std::vector<std::unique_ptr<PaletteTool>> tools_;
-
-  DISALLOW_COPY_AND_ASSIGN(PaletteToolManager);
 };
 
 }  // namespace ash
diff --git a/ash/system/palette/palette_tool_manager_unittest.cc b/ash/system/palette/palette_tool_manager_unittest.cc
index 868f541..3b890df 100644
--- a/ash/system/palette/palette_tool_manager_unittest.cc
+++ b/ash/system/palette/palette_tool_manager_unittest.cc
@@ -22,6 +22,9 @@
   TestTool(Delegate* delegate, PaletteGroup group, PaletteToolId tool_id)
       : PaletteTool(delegate), group_(group), tool_id_(tool_id) {}
 
+  TestTool(const TestTool&) = delete;
+  TestTool& operator=(const TestTool&) = delete;
+
   // PaletteTool:
   PaletteGroup GetGroup() const override { return group_; }
   PaletteToolId GetToolId() const override { return tool_id_; }
@@ -39,8 +42,6 @@
 
   PaletteGroup group_;
   PaletteToolId tool_id_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestTool);
 };
 
 // Base class for tool manager unittests.
diff --git a/ash/system/power/peripheral_battery_notifier_listener_integration_test.cc b/ash/system/power/peripheral_battery_notifier_listener_integration_test.cc
index 57a97ef1..7d8da40 100644
--- a/ash/system/power/peripheral_battery_notifier_listener_integration_test.cc
+++ b/ash/system/power/peripheral_battery_notifier_listener_integration_test.cc
@@ -163,11 +163,13 @@
   PeripheralBatteryNotifierListenerIncompleteDevicesTest() {
     set_complete_devices(false);
   }
-  ~PeripheralBatteryNotifierListenerIncompleteDevicesTest() override {}
 
- private:
-  DISALLOW_COPY_AND_ASSIGN(
-      PeripheralBatteryNotifierListenerIncompleteDevicesTest);
+  PeripheralBatteryNotifierListenerIncompleteDevicesTest(
+      const PeripheralBatteryNotifierListenerIncompleteDevicesTest&) = delete;
+  PeripheralBatteryNotifierListenerIncompleteDevicesTest& operator=(
+      const PeripheralBatteryNotifierListenerIncompleteDevicesTest&) = delete;
+
+  ~PeripheralBatteryNotifierListenerIncompleteDevicesTest() override {}
 };
 
 TEST_F(PeripheralBatteryNotifierListenerTest, Basic) {
diff --git a/ash/system/power/power_button_controller_unittest.cc b/ash/system/power/power_button_controller_unittest.cc
index 47d5693..f820322d 100644
--- a/ash/system/power/power_button_controller_unittest.cc
+++ b/ash/system/power/power_button_controller_unittest.cc
@@ -1115,6 +1115,11 @@
         switches::kAshPowerButtonPosition, json_position_info);
   }
 
+  PowerButtonControllerWithPositionTest(
+      const PowerButtonControllerWithPositionTest&) = delete;
+  PowerButtonControllerWithPositionTest& operator=(
+      const PowerButtonControllerWithPositionTest&) = delete;
+
   bool IsLeftOrRightPosition() const {
     return power_button_position_ == PowerButtonPosition::LEFT ||
            power_button_position_ == PowerButtonPosition::RIGHT;
@@ -1140,8 +1145,6 @@
 
  private:
   PowerButtonPosition power_button_position_;
-
-  DISALLOW_COPY_AND_ASSIGN(PowerButtonControllerWithPositionTest);
 };
 
 // TODO(crbug.com/1010194).
diff --git a/ash/system/power/power_button_screenshot_controller_unittest.cc b/ash/system/power/power_button_screenshot_controller_unittest.cc
index 6ef577a..87e1b9e 100644
--- a/ash/system/power/power_button_screenshot_controller_unittest.cc
+++ b/ash/system/power/power_button_screenshot_controller_unittest.cc
@@ -318,14 +318,17 @@
  public:
   PowerButtonScreenshotControllerWithKeyCodeTest() : key_code_(GetParam()) {}
 
+  PowerButtonScreenshotControllerWithKeyCodeTest(
+      const PowerButtonScreenshotControllerWithKeyCodeTest&) = delete;
+  PowerButtonScreenshotControllerWithKeyCodeTest& operator=(
+      const PowerButtonScreenshotControllerWithKeyCodeTest&) = delete;
+
   ui::KeyboardCode key_code() const { return key_code_; }
 
  private:
   // Value of the |key_code_| will only be ui::VKEY_VOLUME_DOWN or
   // ui::VKEY_VOLUME_UP.
   ui::KeyboardCode key_code_ = ui::VKEY_UNKNOWN;
-
-  DISALLOW_COPY_AND_ASSIGN(PowerButtonScreenshotControllerWithKeyCodeTest);
 };
 
 // Tests power button screenshot accelerator works in tablet mode only.
diff --git a/ash/system/power/power_notification_controller.cc b/ash/system/power/power_notification_controller.cc
index 842c5771..40f46a4 100644
--- a/ash/system/power/power_notification_controller.cc
+++ b/ash/system/power/power_notification_controller.cc
@@ -37,6 +37,9 @@
   explicit UsbNotificationDelegate(PowerNotificationController* controller)
       : controller_(controller) {}
 
+  UsbNotificationDelegate(const UsbNotificationDelegate&) = delete;
+  UsbNotificationDelegate& operator=(const UsbNotificationDelegate&) = delete;
+
   // Overridden from message_center::NotificationDelegate.
   void Close(bool by_user) override {
     if (by_user)
@@ -47,8 +50,6 @@
   ~UsbNotificationDelegate() override = default;
 
   PowerNotificationController* const controller_;
-
-  DISALLOW_COPY_AND_ASSIGN(UsbNotificationDelegate);
 };
 
 std::string GetNotificationStateString(
diff --git a/ash/system/power/power_prefs_unittest.cc b/ash/system/power/power_prefs_unittest.cc
index 9f5cd56..520ffae 100644
--- a/ash/system/power/power_prefs_unittest.cc
+++ b/ash/system/power/power_prefs_unittest.cc
@@ -180,6 +180,10 @@
 }  // namespace
 
 class PowerPrefsTest : public NoSessionAshTestBase {
+ public:
+  PowerPrefsTest(const PowerPrefsTest&) = delete;
+  PowerPrefsTest& operator=(const PowerPrefsTest&) = delete;
+
  protected:
   PowerPrefsTest() = default;
   ~PowerPrefsTest() override = default;
@@ -268,9 +272,6 @@
       base::MakeRefCounted<PrefRegistrySimple>();
 
   std::unique_ptr<PrefService> local_state_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(PowerPrefsTest);
 };
 
 TEST_F(PowerPrefsTest, LoginScreen) {
diff --git a/ash/system/power/power_status.h b/ash/system/power/power_status.h
index 79057b8..6575b43 100644
--- a/ash/system/power/power_status.h
+++ b/ash/system/power/power_status.h
@@ -100,6 +100,9 @@
   // percentage of charge remaining.
   static const double kCriticalBatteryChargePercentage;
 
+  PowerStatus(const PowerStatus&) = delete;
+  PowerStatus& operator=(const PowerStatus&) = delete;
+
   // Sets the global instance. Must be called before any calls to Get().
   static void Initialize();
 
@@ -230,8 +233,6 @@
 
   // Current state.
   power_manager::PowerSupplyProperties proto_;
-
-  DISALLOW_COPY_AND_ASSIGN(PowerStatus);
 };
 
 }  // namespace ash
diff --git a/ash/system/session/logout_confirmation_controller_unittest.cc b/ash/system/session/logout_confirmation_controller_unittest.cc
index 9eea6c3..d3504af 100644
--- a/ash/system/session/logout_confirmation_controller_unittest.cc
+++ b/ash/system/session/logout_confirmation_controller_unittest.cc
@@ -29,6 +29,12 @@
 constexpr char kUserEmail[] = "user1@test.com";
 
 class LogoutConfirmationControllerTest : public testing::Test {
+ public:
+  LogoutConfirmationControllerTest(const LogoutConfirmationControllerTest&) =
+      delete;
+  LogoutConfirmationControllerTest& operator=(
+      const LogoutConfirmationControllerTest&) = delete;
+
  protected:
   LogoutConfirmationControllerTest();
   ~LogoutConfirmationControllerTest() override;
@@ -41,9 +47,6 @@
   base::ThreadTaskRunnerHandle runner_handle_;
 
   LogoutConfirmationController controller_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(LogoutConfirmationControllerTest);
 };
 
 LogoutConfirmationControllerTest::LogoutConfirmationControllerTest()
diff --git a/ash/system/session/session_limit_notification_controller_unittest.cc b/ash/system/session/session_limit_notification_controller_unittest.cc
index cf8ef1a2b..5bd16cec 100644
--- a/ash/system/session/session_limit_notification_controller_unittest.cc
+++ b/ash/system/session/session_limit_notification_controller_unittest.cc
@@ -169,8 +169,10 @@
  public:
   SessionLimitNotificationControllerLoginTest() { set_start_session(false); }
 
- private:
-  DISALLOW_COPY_AND_ASSIGN(SessionLimitNotificationControllerLoginTest);
+  SessionLimitNotificationControllerLoginTest(
+      const SessionLimitNotificationControllerLoginTest&) = delete;
+  SessionLimitNotificationControllerLoginTest& operator=(
+      const SessionLimitNotificationControllerLoginTest&) = delete;
 };
 
 TEST_F(SessionLimitNotificationControllerLoginTest,
diff --git a/ash/system/status_area_widget.h b/ash/system/status_area_widget.h
index c032b0c..e13736a 100644
--- a/ash/system/status_area_widget.h
+++ b/ash/system/status_area_widget.h
@@ -60,6 +60,10 @@
   };
 
   StatusAreaWidget(aura::Window* status_container, Shelf* shelf);
+
+  StatusAreaWidget(const StatusAreaWidget&) = delete;
+  StatusAreaWidget& operator=(const StatusAreaWidget&) = delete;
+
   ~StatusAreaWidget() override;
 
   // Returns the status area widget for the display that |window| is on.
@@ -252,8 +256,6 @@
   int tray_bubble_count_ = 0;
 
   base::WeakPtrFactory<StatusAreaWidget> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(StatusAreaWidget);
 };
 
 }  // namespace ash
diff --git a/ash/system/status_area_widget_test_helper.h b/ash/system/status_area_widget_test_helper.h
index c28158a..c8e6c87 100644
--- a/ash/system/status_area_widget_test_helper.h
+++ b/ash/system/status_area_widget_test_helper.h
@@ -15,6 +15,11 @@
 
 class StatusAreaWidgetTestHelper {
  public:
+  StatusAreaWidgetTestHelper() = delete;
+  StatusAreaWidgetTestHelper(const StatusAreaWidgetTestHelper&) = delete;
+  StatusAreaWidgetTestHelper& operator=(const StatusAreaWidgetTestHelper&) =
+      delete;
+
   static LoginStatus GetUserLoginStatus();
 
   // Returns the StatusAreaWidget that appears on the primary display.
@@ -28,9 +33,6 @@
 
   // Waits until one child view's layer animations are over.
   static void WaitForLayerAnimationEnd(ui::Layer* layer);
-
- private:
-  DISALLOW_IMPLICIT_CONSTRUCTORS(StatusAreaWidgetTestHelper);
 };
 
 }  // namespace ash
diff --git a/ash/system/tray/size_range_layout_unittest.cc b/ash/system/tray/size_range_layout_unittest.cc
index 97f8228..498fc9b 100644
--- a/ash/system/tray/size_range_layout_unittest.cc
+++ b/ash/system/tray/size_range_layout_unittest.cc
@@ -15,6 +15,9 @@
  public:
   SizeRangeLayoutTest();
 
+  SizeRangeLayoutTest(const SizeRangeLayoutTest&) = delete;
+  SizeRangeLayoutTest& operator=(const SizeRangeLayoutTest&) = delete;
+
   // Wrapper function to access the minimum preferred size of |layout|.
   gfx::Size GetMinSize(const SizeRangeLayout* layout) const;
 
@@ -26,9 +29,6 @@
 
   const gfx::Size kAbsoluteMinSize;
   const gfx::Size kAbsoluteMaxSize;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(SizeRangeLayoutTest);
 };
 
 SizeRangeLayoutTest::SizeRangeLayoutTest()
diff --git a/ash/system/tray/tray_background_view.cc b/ash/system/tray/tray_background_view.cc
index b7b0c6ed..2fc46c5 100644
--- a/ash/system/tray/tray_background_view.cc
+++ b/ash/system/tray/tray_background_view.cc
@@ -145,6 +145,9 @@
  public:
   explicit TrayWidgetObserver(TrayBackgroundView* host) : host_(host) {}
 
+  TrayWidgetObserver(const TrayWidgetObserver&) = delete;
+  TrayWidgetObserver& operator=(const TrayWidgetObserver&) = delete;
+
   void OnWidgetBoundsChanged(views::Widget* widget,
                              const gfx::Rect& new_bounds) override {
     host_->AnchorUpdated();
@@ -160,8 +163,6 @@
   TrayBackgroundView* host_;
   base::ScopedMultiSourceObservation<views::Widget, views::WidgetObserver>
       observations_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(TrayWidgetObserver);
 };
 
 // Handles `TrayBackgroundView`'s animation on session changed.
diff --git a/ash/system/tray/tray_popup_utils.h b/ash/system/tray/tray_popup_utils.h
index 342dddc..92bae35 100644
--- a/ash/system/tray/tray_popup_utils.h
+++ b/ash/system/tray/tray_popup_utils.h
@@ -50,6 +50,10 @@
     kSystemInfo,
   };
 
+  TrayPopupUtils() = delete;
+  TrayPopupUtils(const TrayPopupUtils&) = delete;
+  TrayPopupUtils& operator=(const TrayPopupUtils&) = delete;
+
   // Creates a default container view to be used by system menu rows that are
   // either a single targetable area or not targetable at all. The caller takes
   // over ownership of the created view.
@@ -209,9 +213,6 @@
 
   // Sets the font list for |label| based on |style|.
   static void SetLabelFontList(views::Label* label, FontStyle style);
-
- private:
-  DISALLOW_IMPLICIT_CONSTRUCTORS(TrayPopupUtils);
 };
 
 }  // namespace ash
diff --git a/ash/system/tray/tri_view.cc b/ash/system/tray/tri_view.cc
index 3660e9e..d1b0583b 100644
--- a/ash/system/tray/tri_view.cc
+++ b/ash/system/tray/tri_view.cc
@@ -34,11 +34,11 @@
  public:
   RelayoutView() = default;
 
+  RelayoutView(const RelayoutView&) = delete;
+  RelayoutView& operator=(const RelayoutView&) = delete;
+
   // views::View:
   void ChildPreferredSizeChanged(View* child) override { Layout(); }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(RelayoutView);
 };
 
 }  // namespace
diff --git a/ash/system/tray/tri_view_unittest.cc b/ash/system/tray/tri_view_unittest.cc
index f16bcb9..528f30f1 100644
--- a/ash/system/tray/tri_view_unittest.cc
+++ b/ash/system/tray/tri_view_unittest.cc
@@ -33,6 +33,9 @@
  public:
   TriViewTest();
 
+  TriViewTest(const TriViewTest&) = delete;
+  TriViewTest& operator=(const TriViewTest&) = delete;
+
  protected:
   // Convenience function to get the minimum height of |container|.
   int GetMinHeight(TriView::Container container) const;
@@ -46,9 +49,6 @@
 
   // The test target.
   std::unique_ptr<TriView> tri_view_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(TriViewTest);
 };
 
 TriViewTest::TriViewTest() : tri_view_(std::make_unique<TriView>()) {}
diff --git a/ash/system/unified/custom_shape_button.cc b/ash/system/unified/custom_shape_button.cc
index 91e0bafa..babbe633 100644
--- a/ash/system/unified/custom_shape_button.cc
+++ b/ash/system/unified/custom_shape_button.cc
@@ -23,13 +23,15 @@
  public:
   CustomShapeButtonHighlightPathGenerator() = default;
 
+  CustomShapeButtonHighlightPathGenerator(
+      const CustomShapeButtonHighlightPathGenerator&) = delete;
+  CustomShapeButtonHighlightPathGenerator& operator=(
+      const CustomShapeButtonHighlightPathGenerator&) = delete;
+
   SkPath GetHighlightPath(const views::View* view) override {
     return static_cast<const ash::CustomShapeButton*>(view)
         ->CreateCustomShapePath(view->GetLocalBounds());
   }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CustomShapeButtonHighlightPathGenerator);
 };
 }  // namespace
 
diff --git a/ash/system/unified/notification_counter_view.cc b/ash/system/unified/notification_counter_view.cc
index 9d040ab..457c56c 100644
--- a/ash/system/unified/notification_counter_view.cc
+++ b/ash/system/unified/notification_counter_view.cc
@@ -71,6 +71,9 @@
     DCHECK_LE(count_, kTrayNotificationMaxCount + 1);
   }
 
+  NumberIconImageSource(const NumberIconImageSource&) = delete;
+  NumberIconImageSource& operator=(const NumberIconImageSource&) = delete;
+
   void Draw(gfx::Canvas* canvas) override {
     SkColor tray_icon_color =
         TrayIconColor(Shell::Get()->session_controller()->GetSessionState());
@@ -97,8 +100,6 @@
 
  private:
   size_t count_;
-
-  DISALLOW_COPY_AND_ASSIGN(NumberIconImageSource);
 };
 
 }  // namespace
diff --git a/ash/system/unified/top_shortcuts_view.h b/ash/system/unified/top_shortcuts_view.h
index 8761538..579a417 100644
--- a/ash/system/unified/top_shortcuts_view.h
+++ b/ash/system/unified/top_shortcuts_view.h
@@ -56,6 +56,9 @@
  public:
   explicit TopShortcutsView(UnifiedSystemTrayController* controller);
 
+  TopShortcutsView(const TopShortcutsView&) = delete;
+  TopShortcutsView& operator=(const TopShortcutsView&) = delete;
+
   static void RegisterLocalStatePrefs(PrefRegistrySimple* registry);
 
   // Change the expanded state. CollapseButton icon will rotate.
@@ -80,8 +83,6 @@
   CollapseButton* collapse_button_ = nullptr;
 
   PrefChangeRegistrar local_state_pref_change_registrar_;
-
-  DISALLOW_COPY_AND_ASSIGN(TopShortcutsView);
 };
 
 }  // namespace ash
diff --git a/ash/system/unified/user_chooser_view.cc b/ash/system/unified/user_chooser_view.cc
index a02ec0b4..58bab84c 100644
--- a/ash/system/unified/user_chooser_view.cc
+++ b/ash/system/unified/user_chooser_view.cc
@@ -99,7 +99,8 @@
             ContentLayerType::kSeparatorColor)));
   }
 
-  DISALLOW_COPY_AND_ASSIGN(Separator);
+  Separator(const Separator&) = delete;
+  Separator& operator=(const Separator&) = delete;
 };
 
 views::View* CreateAddUserErrorView(const std::u16string& message) {
diff --git a/ash/test/toplevel_window.h b/ash/test/toplevel_window.h
index bf07671d..3249cf2e6 100644
--- a/ash/test/toplevel_window.h
+++ b/ash/test/toplevel_window.h
@@ -20,6 +20,10 @@
     bool can_maximize;
     bool use_saved_placement;
   };
+
+  ToplevelWindow(const ToplevelWindow&) = delete;
+  ToplevelWindow& operator=(const ToplevelWindow&) = delete;
+
   static views::Widget* CreateToplevelWindow(const CreateParams& params);
 
   // Clears saved show state and bounds used to position
@@ -41,8 +45,6 @@
                                ui::WindowShowState* show_state) const override;
 
   bool use_saved_placement_ = true;
-
-  DISALLOW_COPY_AND_ASSIGN(ToplevelWindow);
 };
 
 }  // namespace shell
diff --git a/ash/touch/touch_hud_debug.cc b/ash/touch/touch_hud_debug.cc
index c78345e..88a3bed2 100644
--- a/ash/touch/touch_hud_debug.cc
+++ b/ash/touch/touch_hud_debug.cc
@@ -93,6 +93,9 @@
 
   TouchTrace() = default;
 
+  TouchTrace(const TouchTrace&) = delete;
+  TouchTrace& operator=(const TouchTrace&) = delete;
+
   void AddTouchPoint(const ui::TouchEvent& touch) {
     log_.push_back(TouchPointLog(touch));
   }
@@ -108,8 +111,6 @@
 
  private:
   std::vector<TouchPointLog> log_;
-
-  DISALLOW_COPY_AND_ASSIGN(TouchTrace);
 };
 
 // A TouchLog keeps track of all touch events of all touch points.
@@ -117,6 +118,9 @@
  public:
   TouchLog() : next_trace_index_(0) {}
 
+  TouchLog(const TouchLog&) = delete;
+  TouchLog& operator=(const TouchLog&) = delete;
+
   void AddTouchPoint(const ui::TouchEvent& touch) {
     if (touch.type() == ui::ET_TOUCH_PRESSED)
       StartTrace(touch);
@@ -161,8 +165,6 @@
   int next_trace_index_;
 
   std::map<int, int> touch_id_to_trace_index_;
-
-  DISALLOW_COPY_AND_ASSIGN(TouchLog);
 };
 
 // TouchHudCanvas draws touch traces in |FULLSCREEN| and |REDUCED_SCALE| modes.
diff --git a/ash/touch/touch_hud_debug.h b/ash/touch/touch_hud_debug.h
index e35780c..9baa8cd 100644
--- a/ash/touch/touch_hud_debug.h
+++ b/ash/touch/touch_hud_debug.h
@@ -36,6 +36,9 @@
 
   explicit TouchHudDebug(aura::Window* initial_root);
 
+  TouchHudDebug(const TouchHudDebug&) = delete;
+  TouchHudDebug& operator=(const TouchHudDebug&) = delete;
+
   // Changes the display mode (e.g. scale, visibility). Calling this repeatedly
   // cycles between a fixed number of display modes.
   void ChangeToNextMode();
@@ -69,8 +72,6 @@
   TouchHudCanvas* canvas_;
   views::View* label_container_;
   views::Label* touch_labels_[kMaxTouchPoints];
-
-  DISALLOW_COPY_AND_ASSIGN(TouchHudDebug);
 };
 
 }  // namespace ash
diff --git a/ash/touch/touch_hud_projection.h b/ash/touch/touch_hud_projection.h
index 22ba9c62..496dcd5 100644
--- a/ash/touch/touch_hud_projection.h
+++ b/ash/touch/touch_hud_projection.h
@@ -18,6 +18,9 @@
  public:
   explicit TouchHudProjection(aura::Window* initial_root);
 
+  TouchHudProjection(const TouchHudProjection&) = delete;
+  TouchHudProjection& operator=(const TouchHudProjection&) = delete;
+
   // TouchObserverHud:
   void Clear() override;
 
@@ -34,8 +37,6 @@
 
   // TouchHudRenderer draws out the touch points.
   std::unique_ptr<TouchHudRenderer> touch_hud_renderer_;
-
-  DISALLOW_COPY_AND_ASSIGN(TouchHudProjection);
 };
 
 }  // namespace ash
diff --git a/ash/touch/touch_observer_hud.h b/ash/touch/touch_observer_hud.h
index f4e1c1f..4c7ce36 100644
--- a/ash/touch/touch_observer_hud.h
+++ b/ash/touch/touch_observer_hud.h
@@ -34,6 +34,9 @@
       public display::DisplayConfigurator::Observer,
       public WindowTreeHostManager::Observer {
  public:
+  TouchObserverHud(const TouchObserverHud&) = delete;
+  TouchObserverHud& operator=(const TouchObserverHud&) = delete;
+
   // Called to clear touch points and traces from the screen.
   virtual void Clear() = 0;
 
@@ -85,8 +88,6 @@
   views::Widget* widget_;
 
   display::ScopedDisplayObserver display_observer_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(TouchObserverHud);
 };
 
 }  // namespace ash
diff --git a/ash/wallpaper/wallpaper_view.cc b/ash/wallpaper/wallpaper_view.cc
index d03ffba..167a496 100644
--- a/ash/wallpaper/wallpaper_view.cc
+++ b/ash/wallpaper/wallpaper_view.cc
@@ -43,6 +43,9 @@
     view->SetPaintToLayer();
   }
 
+  WallpaperWidgetDelegate(const WallpaperWidgetDelegate&) = delete;
+  WallpaperWidgetDelegate& operator=(const WallpaperWidgetDelegate&) = delete;
+
   // Overrides views::View.
   void Layout() override {
     aura::Window* window = GetWidget()->GetNativeWindow();
@@ -63,9 +66,6 @@
       child->SetTransform(transform);
     }
   }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(WallpaperWidgetDelegate);
 };
 
 }  // namespace
diff --git a/ash/webui/common/resources/navigation_shared_vars.html b/ash/webui/common/resources/navigation_shared_vars.html
index 63953f2..f370e268b 100644
--- a/ash/webui/common/resources/navigation_shared_vars.html
+++ b/ash/webui/common/resources/navigation_shared_vars.html
@@ -2,6 +2,9 @@
   <style>
     html {
       --areas-no-header-nav: "sideNav main";
+      --areas-no-header-nav-banner: "banner banner"
+                                    "sideNav main";
+      --left-aligned-top-offset: 75px;
     }
 
    /* calc formula: (viewport width - (padding + side nav size)) */
@@ -9,6 +12,9 @@
       html {
         --areas-nav: "head head"
                  "main main";
+        --areas-nav-banner: "head head"
+                            "banner banner"
+                            "main main";
         --columns-nav: 1fr 1fr;
         --container-padding-nav: 24px;
         --container-max-width-nav: calc(100vw - 48px);
@@ -19,6 +25,9 @@
       html {
         --areas-nav: "head head"
                  "sideNav main";
+        --areas-nav-banner: "head head"
+                            "banner banner"
+                            "sideNav main";
         --columns-nav: 192px 1fr;
         --container-padding-nav: 40px;
         --container-max-width-nav: calc(100vw - 272px);
diff --git a/ash/webui/common/resources/navigation_view_panel.html b/ash/webui/common/resources/navigation_view_panel.html
index 53f0a4b..d04999a 100644
--- a/ash/webui/common/resources/navigation_view_panel.html
+++ b/ash/webui/common/resources/navigation_view_panel.html
@@ -6,6 +6,28 @@
     position: fixed;
   }
 
+  ::slotted([slot=banner]) {
+    grid-area: banner;
+  }
+
+  :host([show-banner]) {
+    --left-aligned-top-offset: 150px;
+  }
+
+  :host([show-banner][show-tool-bar]) #container {
+    display: grid;
+    grid-template-areas: var(--areas-nav-banner);
+    grid-template-columns: var(--columns-nav);
+    width: 100%;
+  }
+
+  :host([show-banner]:not([show-tool-bar])) #container {
+    display: grid;
+    grid-template-areas: var(--areas-no-header-nav-banner);
+    grid-template-columns: var(--columns-nav);
+    width: 100%;
+  }
+
   :host([show-tool-bar]) #container {
     display: grid;
     grid-template-areas: var(--areas-nav);
@@ -26,6 +48,13 @@
     z-index: 3;
   }
 
+  :host([show-banner]) #banner {
+    grid-area: banner;
+    position: sticky;
+    top: 72px;
+    z-index: 3;
+  }
+
   cr-drawer {
     --cr-separator-line: none;
     --cr-drawer-header-color: var(--cros-text-color-secondary);
@@ -57,7 +86,7 @@
 
   .left-aligned {
     position: sticky;
-    top: 75px;
+    top: var(--left-aligned-top-offset);
   }
 
   page-toolbar {
@@ -76,6 +105,11 @@
       </page-toolbar>
     </div>
   </template>
+  <template is="dom-if" if="[[showBanner]]">
+    <div id="banner">
+      <slot name="banner"></slot>
+    </div>
+  </template>
   <cr-drawer id="drawer" heading="[[title]]">
     <div slot="header-icon">
       <iron-icon id="iconButton" icon="cr20:menu"
diff --git a/ash/webui/common/resources/navigation_view_panel.js b/ash/webui/common/resources/navigation_view_panel.js
index f737ce4..5b81956 100644
--- a/ash/webui/common/resources/navigation_view_panel.js
+++ b/ash/webui/common/resources/navigation_view_panel.js
@@ -74,6 +74,20 @@
 
       /**
        * Can only be set to True if specified from the parent element by
+       * adding show-banner as an attribute to <navigation-view-panel>. If
+       * True, a banner will appear above the 2 column view (sidebar +
+       * page). If False, banner grid-area will not show and regular grid
+       * layout will be used based on show-tool-bar property.
+       * @type {boolean}
+       */
+      showBanner: {
+        type: Boolean,
+        value: false,
+        reflectToAttribute: true,
+      },
+
+      /**
+       * Can only be set to True if specified from the parent element by
        * adding show-tool-bar as an attribute to <navigation-view-panel>. If
        * True, a toolbar will appear at the top of the navigation view panel
        * with a 2 column view below it (sidebar + page). If False,
diff --git a/ash/webui/diagnostics_ui/backend/networking_log.cc b/ash/webui/diagnostics_ui/backend/networking_log.cc
index 48a82ab..bca1751 100644
--- a/ash/webui/diagnostics_ui/backend/networking_log.cc
+++ b/ash/webui/diagnostics_ui/backend/networking_log.cc
@@ -55,6 +55,11 @@
 const char kNetworkRemovedEventTemplate[] = "%s network [%s] removed\n";
 const char kNetworkStateChangedEventTemplate[] =
     "%s network [%s] changed state from %s to %s\n";
+const char kJoinedWiFiEventTemplate[] =
+    "%s network [%s] joined SSID '%s' on access point [%s]\n";
+const char kLeftWiFiEventTemplate[] = "%s network [%s] left SSID '%s'\n";
+const char kAccessPointRoamingEventTemplate[] =
+    "%s network [%s] on SSID '%s' roamed from access point [%s] to [%s]\n";
 
 std::string GetSubnetMask(int prefix) {
   uint32_t mask = (0xFFFFFFFF << (32 - prefix)) & 0xFFFFFFFF;
@@ -82,6 +87,37 @@
   }
 }
 
+std::string GetSsid(const mojom::NetworkPtr& network) {
+  DCHECK(network->type == mojom::NetworkType::kWiFi);
+  return network->type_properties ? network->type_properties->get_wifi()->ssid
+                                  : "";
+}
+
+std::string GetBssid(const mojom::NetworkPtr& network) {
+  DCHECK(network->type == mojom::NetworkType::kWiFi);
+  return network->type_properties ? network->type_properties->get_wifi()->bssid
+                                  : "";
+}
+
+bool HasJoinedWiFiNetwork(const mojom::NetworkPtr& old_state,
+                          const mojom::NetworkPtr& new_state) {
+  const std::string old_ssid = GetSsid(old_state);
+  return old_ssid.empty() && (old_ssid != GetSsid(new_state));
+}
+
+bool HasLeftWiFiNetwork(const mojom::NetworkPtr& old_state,
+                        const mojom::NetworkPtr& new_state) {
+  const std::string new_ssid = GetSsid(new_state);
+  return new_ssid.empty() && (new_ssid != GetSsid(old_state));
+}
+
+bool HasRoamedAccessPoint(const mojom::NetworkPtr& old_state,
+                          const mojom::NetworkPtr& new_state) {
+  const std::string new_ssid = GetSsid(new_state);
+  return !new_ssid.empty() && (new_ssid == GetSsid(old_state)) &&
+         (GetBssid(old_state) != GetBssid(new_state));
+}
+
 void AddWifiInfoToLog(const mojom::NetworkTypeProperties& type_props,
                       std::stringstream& output) {
   output << kWifiSignalStrengthTitle << type_props.get_wifi()->signal_strength
@@ -275,6 +311,17 @@
   DCHECK(base::Contains(latest_network_states_, new_state->observer_guid));
   const mojom::NetworkPtr& old_state =
       latest_network_states_.at(new_state->observer_guid);
+
+  if (new_state->type == mojom::NetworkType::kWiFi) {
+    if (HasJoinedWiFiNetwork(old_state, new_state)) {
+      LogJoinedWiFiNetwork(new_state);
+    } else if (HasLeftWiFiNetwork(old_state, new_state)) {
+      LogLeftWiFiNetwork(new_state, GetSsid(old_state));
+    } else if (HasRoamedAccessPoint(old_state, new_state)) {
+      LogWiFiRoamedAccessPoint(new_state, GetBssid(old_state));
+    }
+  }
+
   if (old_state->state != new_state->state) {
     LogNetworkStateChanged(old_state, new_state);
   }
@@ -291,5 +338,30 @@
   LogEvent(line);
 }
 
+void NetworkingLog::LogJoinedWiFiNetwork(const mojom::NetworkPtr& network) {
+  const std::string line = base::StringPrintf(
+      kJoinedWiFiEventTemplate, GetNetworkType(network->type).c_str(),
+      network->mac_address.value_or("").c_str(), GetSsid(network).c_str(),
+      GetBssid(network).c_str());
+  LogEvent(line);
+}
+
+void NetworkingLog::LogLeftWiFiNetwork(const mojom::NetworkPtr& network,
+                                       const std::string& old_ssid) {
+  const std::string line = base::StringPrintf(
+      kLeftWiFiEventTemplate, GetNetworkType(network->type).c_str(),
+      network->mac_address.value_or("").c_str(), old_ssid.c_str());
+  LogEvent(line);
+}
+
+void NetworkingLog::LogWiFiRoamedAccessPoint(const mojom::NetworkPtr& network,
+                                             const std::string& old_bssid) {
+  const std::string line = base::StringPrintf(
+      kAccessPointRoamingEventTemplate, GetNetworkType(network->type).c_str(),
+      network->mac_address.value_or("").c_str(), GetSsid(network).c_str(),
+      old_bssid.c_str(), GetBssid(network).c_str());
+  LogEvent(line);
+}
+
 }  // namespace diagnostics
 }  // namespace ash
diff --git a/ash/webui/diagnostics_ui/backend/networking_log.h b/ash/webui/diagnostics_ui/backend/networking_log.h
index fd21fb7..6ad14e0e 100644
--- a/ash/webui/diagnostics_ui/backend/networking_log.h
+++ b/ash/webui/diagnostics_ui/backend/networking_log.h
@@ -57,6 +57,17 @@
   void LogNetworkStateChanged(const mojom::NetworkPtr& old_state,
                               const mojom::NetworkPtr& new_state);
 
+  // Logs when a WiFi network is joined.
+  void LogJoinedWiFiNetwork(const mojom::NetworkPtr& network);
+
+  // Logs when a WiFi network is left.
+  void LogLeftWiFiNetwork(const mojom::NetworkPtr& network,
+                          const std::string& old_ssid);
+
+  // Logs when a WiFi network roams between access points.
+  void LogWiFiRoamedAccessPoint(const mojom::NetworkPtr& network,
+                                const std::string& old_bssid);
+
   AsyncLog event_log_;
   std::string active_guid_;
   base::flat_map<std::string, mojom::NetworkPtr> latest_network_states_;
diff --git a/ash/webui/diagnostics_ui/backend/networking_log_unittest.cc b/ash/webui/diagnostics_ui/backend/networking_log_unittest.cc
index d446757..8a2cab2a5 100644
--- a/ash/webui/diagnostics_ui/backend/networking_log_unittest.cc
+++ b/ash/webui/diagnostics_ui/backend/networking_log_unittest.cc
@@ -248,10 +248,11 @@
   mojom::NetworkPtr new_state = test_info.Clone();
   new_state->state = mojom::NetworkState::kDisabled;
   log.UpdateNetworkState(std::move(new_state));
-  task_environment_.RunUntilIdle();
 
   // Remove the network.
   log.UpdateNetworkList({}, "expected_guid");
+
+  // Make sure all the updates are committed.
   task_environment_.RunUntilIdle();
 
   // Split the log for verification.
@@ -278,5 +279,104 @@
   ExpectCorrectLogLine(expected_line, events_lines[upto_line++]);
 }
 
+TEST_F(NetworkingLogTest, WiFiNetworkEvents) {
+  const uint32_t expected_signal_strength = 99;
+  const uint16_t expected_frequency = 5785;
+  const std::string expected_ssid = "ssid";
+  const std::string expected_bssid = "bssid";
+  const std::string expected_bssid_roamed = "bssid_roamed";
+  const std::string expected_subnet_mask = "128.0.0.0";
+  const std::string expected_gateway = "192.0.0.1";
+  const std::string expected_ip_address = "192.168.1.1";
+  const std::string expected_security_type = "WEP";
+  const std::string name_server1 = "192.168.1.100";
+  const std::string name_server2 = "192.168.1.101";
+
+  std::vector<std::string> expected_name_servers = {name_server1, name_server2};
+  const std::string expected_guid = "guid";
+  const std::string expected_name = "name";
+  const std::string expected_mac_address = "84:C5:A6:30:3F:31";
+
+  mojom::NetworkPtr test_info = CreateWiFiNetworkPtr(
+      expected_signal_strength, expected_frequency, expected_ssid,
+      expected_bssid, /*routing_prefix=*/1, expected_gateway,
+      expected_ip_address, std::move(expected_name_servers), expected_guid,
+      expected_name, expected_mac_address, mojom::SecurityType::kWepPsk);
+
+  NetworkingLog log(temp_dir_.GetPath());
+
+  // Add the network.
+  log.UpdateNetworkList({expected_guid}, expected_guid);
+  log.UpdateNetworkState(test_info.Clone());
+
+  // Leave the WiFi network.
+  mojom::NetworkPtr new_state = test_info.Clone();
+  new_state->state = mojom::NetworkState::kNotConnected;
+  new_state->type_properties->get_wifi()->ssid = "";
+  log.UpdateNetworkState(std::move(new_state));
+
+  // Rejoin the WiFi network.
+  new_state = test_info.Clone();
+  new_state->state = mojom::NetworkState::kOnline;
+  new_state->type_properties->get_wifi()->ssid = expected_ssid;
+  log.UpdateNetworkState(std::move(new_state));
+
+  // Roam to a new access point.
+  new_state = test_info.Clone();
+  new_state->state = mojom::NetworkState::kOnline;
+  new_state->type_properties->get_wifi()->bssid = expected_bssid_roamed;
+  log.UpdateNetworkState(std::move(new_state));
+
+  // Remove the network.
+  log.UpdateNetworkList({}, "expected_guid");
+
+  // Make sure all the updates are committed.
+  task_environment_.RunUntilIdle();
+
+  // Split the log for verification.
+  const std::string events_log = log.GetNetworkEvents();
+  const std::vector<std::string> events_lines = GetLogLines(events_log);
+  EXPECT_EQ(8u, events_lines.size());
+
+  // Verify section header.
+  size_t upto_line = 0;
+  EXPECT_EQ("--- Network Events ---", events_lines[upto_line++]);
+
+  // Verify add event.
+  std::string expected_line =
+      "WiFi network [" + expected_mac_address + "] started in state Online";
+  ExpectCorrectLogLine(expected_line, events_lines[upto_line++]);
+
+  // Verify network leave event.
+  expected_line = "WiFi network [" + expected_mac_address + "] left SSID '" +
+                  expected_ssid + "'";
+  ExpectCorrectLogLine(expected_line, events_lines[upto_line++]);
+
+  // Verify state change event.
+  expected_line = "WiFi network [" + expected_mac_address +
+                  "] changed state from Online to Not Connected";
+  ExpectCorrectLogLine(expected_line, events_lines[upto_line++]);
+
+  // Verify network join event.
+  expected_line = "WiFi network [" + expected_mac_address + "] joined SSID '" +
+                  expected_ssid + "' on access point [" + expected_bssid + "]";
+  ExpectCorrectLogLine(expected_line, events_lines[upto_line++]);
+
+  // Verify state change event.
+  expected_line = "WiFi network [" + expected_mac_address +
+                  "] changed state from Not Connected to Online";
+  ExpectCorrectLogLine(expected_line, events_lines[upto_line++]);
+
+  // Verify access point roam event.
+  expected_line = "WiFi network [" + expected_mac_address + "] on SSID '" +
+                  expected_ssid + "' roamed from access point [" +
+                  expected_bssid + "] to [" + expected_bssid_roamed + "]";
+  ExpectCorrectLogLine(expected_line, events_lines[upto_line++]);
+
+  // Verify remove event.
+  expected_line = "WiFi network [" + expected_mac_address + "] removed";
+  ExpectCorrectLogLine(expected_line, events_lines[upto_line++]);
+}
+
 }  // namespace diagnostics
 }  // namespace ash
diff --git a/ash/webui/diagnostics_ui/diagnostics_ui.cc b/ash/webui/diagnostics_ui/diagnostics_ui.cc
index bba5438..003a9ea3 100644
--- a/ash/webui/diagnostics_ui/diagnostics_ui.cc
+++ b/ash/webui/diagnostics_ui/diagnostics_ui.cc
@@ -223,6 +223,7 @@
       {"networkTechnologyLteAdvancedLabel",
        IDS_NETWORK_DIAGNOSTICS_CELLULAR_LTE_ADVANCED},
       {"networkTechnologyUmtsLabel", IDS_NETWORK_DIAGNOSTICS_CELLULAR_UMTS},
+      {"noIpAddressText", IDS_NETWORK_DIAGNOSTICS_NO_IP_ADDRESS_TEXT},
       {"notEnoughAvailableMemoryMessage",
        IDS_DIAGNOSTICS_NOT_ENOUGH_AVAILABLE_MEMORY},
       {"percentageLabel", IDS_DIAGNOSTICS_PERCENTAGE_LABEL},
@@ -265,6 +266,8 @@
       {"troubleConnecting", IDS_DIAGNOSTICS_TROUBLE_CONNECTING},
       {"troubleshootingText", IDS_DIAGNOSTICS_TROUBLESHOOTING_TEXT},
       {"versionInfo", IDS_DIAGNOSTICS_VERSION_INFO_TEXT},
+      {"visitSettingsToConfigureLinkText",
+       IDS_NETWORK_DIAGNOSTICS_VISIT_SETTINGS_TO_CONFIGURE_LINK_TEXT},
       {"wifiGroupLabel", IDS_NETWORK_DIAGNOSTICS_WIFI_GROUP},
       {"wifiLabel", IDS_NETWORK_TYPE_WIFI},
   };
diff --git a/ash/webui/diagnostics_ui/resources/BUILD.gn b/ash/webui/diagnostics_ui/resources/BUILD.gn
index 552d580..f926e08d 100644
--- a/ash/webui/diagnostics_ui/resources/BUILD.gn
+++ b/ash/webui/diagnostics_ui/resources/BUILD.gn
@@ -19,6 +19,7 @@
     ":diagnostics_browser_proxy",
     ":diagnostics_card",
     ":diagnostics_card_frame",
+    ":diagnostics_sticky_banner",
     ":diagnostics_types",
     ":diagnostics_utils",
     ":ethernet_info",
@@ -104,6 +105,7 @@
 
 js_library("diagnostics_app") {
   deps = [
+    ":diagnostics_sticky_banner",
     ":network_list",
     ":system_page",
     "//ash/webui/common/resources:navigation_view_panel",
@@ -135,6 +137,13 @@
   deps = [ "//ash/webui/diagnostics_ui/mojom:mojom_js_library_for_compile" ]
 }
 
+js_library("diagnostics_sticky_banner") {
+  deps = [
+    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+    "//ui/webui/resources/cr_elements/cr_button:cr_button.m",
+  ]
+}
+
 js_library("diagnostics_utils") {
   deps = [ "//ui/webui/resources/js:load_time_data.m" ]
 }
@@ -350,6 +359,7 @@
     ":cpu_card",
     ":diagnostics_browser_proxy",
     ":diagnostics_card",
+    ":diagnostics_sticky_banner",
     ":diagnostics_types",
     ":input_list",
     ":memory_card",
@@ -390,6 +400,7 @@
     "diagnostics_card.js",
     "diagnostics_card_frame.js",
     "diagnostics_fonts_css.js",
+    "diagnostics_sticky_banner.js",
     "diagnostics_shared_css.js",
     "ethernet_info.js",
     "icons.js",
diff --git a/ash/webui/diagnostics_ui/resources/cellular_info.html b/ash/webui/diagnostics_ui/resources/cellular_info.html
index 12b76a6e..4a94e27 100644
--- a/ash/webui/diagnostics_ui/resources/cellular_info.html
+++ b/ash/webui/diagnostics_ui/resources/cellular_info.html
@@ -1,4 +1,7 @@
 <style include="diagnostics-shared diagnostics-fonts">
+  :host {
+    --divider-horizontal-height: 100%;
+  }
 </style>
 <div id="cellularInfoContainer">
   <div class="horizontal-data-point-container">
diff --git a/ash/webui/diagnostics_ui/resources/diagnostics_app.html b/ash/webui/diagnostics_ui/resources/diagnostics_app.html
index d5bbe11..a9534c42 100644
--- a/ash/webui/diagnostics_ui/resources/diagnostics_app.html
+++ b/ash/webui/diagnostics_ui/resources/diagnostics_app.html
@@ -18,16 +18,13 @@
 </style>
 <div id="diagnosticsAppContainer">
   <div hidden$="[[!showNavPanel_]]">
-    <navigation-view-panel id="navigationPanel"
-        title="[[i18n('diagnosticsTitle')]]" show-tool-bar>
-      <div slot="bottom-nav-content-panel" class="session-log-container">
-        <cr-button on-click="onSessionLogClick_" class="session-log-button"
-            hidden="[[!isLoggedIn_]]">
-          <iron-icon icon="diagnostics:download" id="download-icon"></iron-icon>
-          <span>[[i18n('sessionLog')]]</span>
-        </cr-button>
-      </div>
-      <div slot="bottom-nav-content-drawer" class="session-log-container">
+    <navigation-view-panel id="navigationPanel" show-tool-bar
+        title="[[i18n('diagnosticsTitle')]]"
+        show-banner=[[bannerMessage_.length]]>
+      <diagnostics-sticky-banner slot="banner"
+          banner-message="{{bannerMessage_}}">
+      </diagnostics-sticky-banner>
+      <div slot="bottom-nav-content" class="session-log-container">
         <cr-button on-click="onSessionLogClick_" class="session-log-button"
             hidden="[[!isLoggedIn_]]">
           <iron-icon icon="diagnostics:download" id="download-icon"></iron-icon>
diff --git a/ash/webui/diagnostics_ui/resources/diagnostics_app.js b/ash/webui/diagnostics_ui/resources/diagnostics_app.js
index cfaad7d..fa48d86 100644
--- a/ash/webui/diagnostics_ui/resources/diagnostics_app.js
+++ b/ash/webui/diagnostics_ui/resources/diagnostics_app.js
@@ -5,6 +5,7 @@
 import 'chrome://resources/ash/common/navigation_view_panel.js';
 import 'chrome://resources/ash/common/page_toolbar.js';
 import 'chrome://resources/cr_elements/cr_toast/cr_toast.js';
+import './diagnostics_sticky_banner.js';
 import './input_list.js';
 import './network_list.js';
 import './strings.m.js';
@@ -34,6 +35,17 @@
   browserProxy_: null,
 
   properties: {
+    /**
+     * Used in navigation-view-panel to set show-banner when banner is expected
+     * to be shown.
+     * @protected
+     * @type {string}
+     */
+    bannerMessage_: {
+      type: Boolean,
+      value: '',
+    },
+
     /** @private {boolean} */
     showNavPanel_: {
       type: Boolean,
diff --git a/ash/webui/diagnostics_ui/resources/diagnostics_app_resources.grd b/ash/webui/diagnostics_ui/resources/diagnostics_app_resources.grd
index 499b8af8..79bcf94 100644
--- a/ash/webui/diagnostics_ui/resources/diagnostics_app_resources.grd
+++ b/ash/webui/diagnostics_ui/resources/diagnostics_app_resources.grd
@@ -54,6 +54,7 @@
       <include name="IDR_DIAGNOSTICS_ROUTINE_RESULT_LIST_JS" file="${root_gen_dir}/ash/webui/diagnostics_ui/resources/routine_result_list.js" resource_path="routine_result_list.js" use_base_dir="false" type="BINDATA"/>
       <include name="IDR_DIAGNOSTICS_ROUTINE_SECTION_JS" file="${root_gen_dir}/ash/webui/diagnostics_ui/resources/routine_section.js" resource_path="routine_section.js" use_base_dir="false" type="BINDATA"/>
       <include name="IDR_DIAGNOSTICS_SHARED_CSS_JS" file="${root_gen_dir}/ash/webui/diagnostics_ui/resources/diagnostics_shared_css.js" resource_path="diagnostics_shared_css.js" use_base_dir="false" type="BINDDATA"/>
+      <include name="IDR_DIAGNOSTICS_STICKY_BANNER_JS" file="${root_gen_dir}/ash/webui/diagnostics_ui/resources/diagnostics_sticky_banner.js" resource_path="diagnostics_sticky_banner.js" use_base_dir="false" type="BINDDATA"/>
       <include name="IDR_DIAGNOSTICS_SYSTEM_DATA_PROVIDER_MOJO_LITE_JS" file="${root_gen_dir}/ash/webui/diagnostics_ui/mojom/system_data_provider.mojom-lite.js" resource_path="system_data_provider.mojom-lite.js" use_base_dir="false" type="BINDATA" />
       <include name="IDR_DIAGNOSTICS_SYSTEM_PAGE_JS" file="${root_gen_dir}/ash/webui/diagnostics_ui/resources/system_page.js" resource_path="system_page.js" use_base_dir="false" type="BINDATA"/>
       <include name="IDR_DIAGNOSTICS_SYSTEM_ROUTINE_CONTROLLER_MOJO_LITE_JS" file="${root_gen_dir}/ash/webui/diagnostics_ui/mojom/system_routine_controller.mojom-lite.js" resource_path="system_routine_controller.mojom-lite.js" use_base_dir="false" type="BINDATA" />
diff --git a/ash/webui/diagnostics_ui/resources/diagnostics_sticky_banner.html b/ash/webui/diagnostics_ui/resources/diagnostics_sticky_banner.html
new file mode 100644
index 0000000..30bfa36c
--- /dev/null
+++ b/ash/webui/diagnostics_ui/resources/diagnostics_sticky_banner.html
@@ -0,0 +1,32 @@
+<style include="cr-shared-style diagnostics-shared diagnostics-fonts">
+  #banner {
+    align-items: center;
+    background-color: var(--google-blue-50);
+    display: flex;
+    height: 56px;
+    position: sticky;
+    top: 0;
+    width: 100vw;
+    z-index: 1;
+  }
+
+  #bannerIcon {
+    --iron-icon-height: 20px;
+    --iron-icon-width: 20px;
+    fill: var(--google-blue-600);
+    padding-inline-end: 16px;
+    padding-inline-start: 40px;
+  }
+
+  #bannerMsg {
+    @apply --diagnostics-caution-banner-font;
+  }
+
+  .elevation-2 {
+    box-shadow: var(--diagnostics-box-shadow-elevation-2);
+  }
+</style>
+<div id="banner" hidden$="[[!bannerMessage]]" class$="[[scrollingClass_]]">
+  <iron-icon icon="diagnostics:info" id="bannerIcon"></iron-icon>
+  <span id="bannerMsg">[[bannerMessage]]</span>
+</div>
diff --git a/ash/webui/diagnostics_ui/resources/diagnostics_sticky_banner.js b/ash/webui/diagnostics_ui/resources/diagnostics_sticky_banner.js
new file mode 100644
index 0000000..eadb7ee
--- /dev/null
+++ b/ash/webui/diagnostics_ui/resources/diagnostics_sticky_banner.js
@@ -0,0 +1,123 @@
+// 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.
+
+import 'chrome://resources/cr_elements/icons.m.js';
+import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
+import './diagnostics_fonts_css.js';
+import './diagnostics_shared_css.js';
+
+import {assert} from 'chrome://resources/js/assert.m.js';
+import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+export class DiagnosticsStickyBannerElement extends PolymerElement {
+  static get is() {
+    return 'diagnostics-sticky-banner';
+  }
+
+  static get template() {
+    return html`{__html_template__}`
+  }
+
+  static get properties() {
+    return {
+      /** @type {string} */
+      bannerMessage: {
+        type: String,
+        value: '',
+        notify: true,
+      },
+
+      /** @protected {string} */
+      scrollingClass_: {
+        type: String,
+        value: '',
+      },
+
+      /** @private */
+      scrollTimerId_: {
+        type: Number,
+        value: -1,
+      },
+    };
+  }
+
+  /** @override */
+  constructor() {
+    super();
+
+    /**
+     * Event callback for 'show-caution-banner' which is triggered from routine-
+     * section. Event will contain message to display on message property of
+     * event found on path `event.detail.message`.
+     * @private {?Function}
+     */
+    this.showCautionBannerHandler_ = (/** @type {!CustomEvent} */ e) => {
+      assert(e.detail.message);
+
+      this.bannerMessage = e.detail.message;
+    };
+
+    /**
+     * Event callback for 'dismiss-caution-banner' which is triggered from
+     * routine-section.
+     * @private {?Function}
+     */
+    this.dismissCautionBannerHandler_ = () => {
+      this.bannerMessage = '';
+    };
+
+    /**
+     * Event callback for 'scroll'.
+     * @private {?Function}
+     */
+    this.scrollClassHandler_ = () => {
+      this.onScroll_();
+    };
+  }
+
+  /** @override */
+  connectedCallback() {
+    super.connectedCallback();
+    window.addEventListener(
+        'show-caution-banner', this.showCautionBannerHandler_);
+    window.addEventListener(
+        'dismiss-caution-banner', this.dismissCautionBannerHandler_);
+    window.addEventListener('scroll', this.scrollClassHandler_);
+  }
+
+  /** @override */
+  disconnectedCallback() {
+    super.disconnectedCallback();
+    window.removeEventListener(
+        'show-caution-banner', this.showCautionBannerHandler_);
+    window.removeEventListener(
+        'dismiss-caution-banner', this.dismissCautionBannerHandler_);
+    window.removeEventListener('scroll', this.scrollClassHandler_);
+  }
+
+  /**
+   * Event handler for 'scroll' to ensure shadow and elevation of banner is
+   * correct while scrolling. Timer is used to clear class after 300ms.
+   * @private
+   */
+  onScroll_() {
+    if (!this.bannerMessage) {
+      return;
+    }
+
+    // Reset timer since we've received another 'scroll' event.
+    if (this.scrollTimerId_ !== -1) {
+      this.scrollingClass_ = 'elevation-2';
+      clearTimeout(this.scrollTimerId_);
+    }
+
+    // Remove box shadow from banner since the user has stopped scrolling
+    // for at least 300ms.
+    this.scrollTimerId_ =
+        window.setTimeout(() => this.scrollingClass_ = '', 300);
+  }
+};
+
+customElements.define(
+    DiagnosticsStickyBannerElement.is, DiagnosticsStickyBannerElement);
diff --git a/ash/webui/diagnostics_ui/resources/diagnostics_types.js b/ash/webui/diagnostics_ui/resources/diagnostics_types.js
index 0d11ab6..3919ac6 100644
--- a/ash/webui/diagnostics_ui/resources/diagnostics_types.js
+++ b/ash/webui/diagnostics_ui/resources/diagnostics_types.js
@@ -412,6 +412,15 @@
 export let RoutineProperties;
 
 /**
+ * @typedef {{
+ *   header: string,
+ *   linkText: string,
+ *   url: string,
+ * }}
+ */
+export let TroubleshootingInfo;
+
+/**
  * Type alias for ConnectionType.
  * @typedef {ash.diagnostics.mojom.ConnectionType}
  */
diff --git a/ash/webui/diagnostics_ui/resources/diagnostics_utils.js b/ash/webui/diagnostics_ui/resources/diagnostics_utils.js
index 69d3423..ba3fb3c0 100644
--- a/ash/webui/diagnostics_ui/resources/diagnostics_utils.js
+++ b/ash/webui/diagnostics_ui/resources/diagnostics_utils.js
@@ -266,3 +266,18 @@
       return '';
   }
 }
+
+/**
+ * @param {!NetworkState} state
+ * @return {boolean}
+ */
+export function isConnectedOrOnline(state) {
+  switch (state) {
+    case NetworkState.kOnline:
+    case NetworkState.kConnected:
+    case NetworkState.kConnecting:
+      return true;
+    default:
+      return false;
+  }
+}
diff --git a/ash/webui/diagnostics_ui/resources/ethernet_info.html b/ash/webui/diagnostics_ui/resources/ethernet_info.html
index be09fed..5f33272 100644
--- a/ash/webui/diagnostics_ui/resources/ethernet_info.html
+++ b/ash/webui/diagnostics_ui/resources/ethernet_info.html
@@ -1,4 +1,7 @@
 <style include="diagnostics-shared diagnostics-fonts">
+  :host {
+    --divider-horizontal-height: 100%;
+  }
 </style>
 <div id="ethernetInfoContainer" class="horizontal-data-point-container">
   <div class="data-point-container">
diff --git a/ash/webui/diagnostics_ui/resources/ip_config_info_drawer.html b/ash/webui/diagnostics_ui/resources/ip_config_info_drawer.html
index 41a38d3..b2c03c80 100644
--- a/ash/webui/diagnostics_ui/resources/ip_config_info_drawer.html
+++ b/ash/webui/diagnostics_ui/resources/ip_config_info_drawer.html
@@ -1,4 +1,7 @@
 <style include="diagnostics-shared diagnostics-fonts">
+  :host {
+    --divider-horizontal-height: 100%;
+  }
 </style>
 <cr-expand-button id="drawerToggle" expanded="{{expanded_}}">
   <span id="drawerTitle" aria-hidden="true">
diff --git a/ash/webui/diagnostics_ui/resources/network_card.html b/ash/webui/diagnostics_ui/resources/network_card.html
index 4990808..0917213 100644
--- a/ash/webui/diagnostics_ui/resources/network_card.html
+++ b/ash/webui/diagnostics_ui/resources/network_card.html
@@ -3,11 +3,10 @@
 <diagnostics-card is-networking-card
     hide-data-points="[[!showNetworkDataPoints_]]">
     <!-- TODO(michaelcheco): Add localized strings. -->
-  <template is="dom-if" if="[[showTroubleConnectingState_]]">
+  <template is="dom-if" if="[[showTroubleshootingCard_]]">
     <network-troubleshooting id="networkTroubleshooting"
         slot="left-panel"
-        network-type="[[networkType_]]"
-        disabled="[[isNetworkDisabled_(network.state)]]">
+        troubleshooting-info="[[troubleshootingInfo_]]">
     </network-troubleshooting>
   </template>
   <div id="cardTitle" slot="title">
diff --git a/ash/webui/diagnostics_ui/resources/network_card.js b/ash/webui/diagnostics_ui/resources/network_card.js
index 1473854ba7..7a64bf1 100644
--- a/ash/webui/diagnostics_ui/resources/network_card.js
+++ b/ash/webui/diagnostics_ui/resources/network_card.js
@@ -12,10 +12,23 @@
 import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js';
 import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {Network, NetworkHealthProviderInterface, NetworkState, NetworkStateObserverInterface, NetworkStateObserverReceiver, NetworkType} from './diagnostics_types.js';
-import {formatMacAddress, getNetworkState, getNetworkType} from './diagnostics_utils.js';
+import {Network, NetworkHealthProviderInterface, NetworkState, NetworkStateObserverInterface, NetworkStateObserverReceiver, NetworkType, TroubleshootingInfo} from './diagnostics_types.js';
+import {formatMacAddress, getNetworkState, getNetworkType, isConnectedOrOnline} from './diagnostics_utils.js';
 import {getNetworkHealthProvider} from './mojo_interface_provider.js';
 
+const BASE_SUPPORT_URL = 'https://support.google.com/chromebook?p=diagnostics_';
+const SETTINGS_URL = 'chrome://os-settings/';
+
+/**
+ * Represents the state of the network troubleshooting banner.
+ * @enum {number}
+ */
+export let TroubleshootingState = {
+  kDisabled: 0,
+  kNotConnected: 1,
+  kMissingIpAddress: 2,
+};
+
 /**
  * @fileoverview
  * 'network-card' is a styling wrapper for a network-info element.
@@ -65,13 +78,14 @@
     /** @protected {boolean} */
     showNetworkDataPoints_: {
       type: Boolean,
-      computed: 'computeShouldShowNetworkDataPoints_(network.state)',
+      computed: 'computeShouldShowNetworkDataPoints_(network.state,' +
+          ' unableToObtainIpAddress_)',
     },
 
     /** @protected {boolean} */
-    showTroubleConnectingState_: {
+    showTroubleshootingCard_: {
       type: Boolean,
-      computed: 'computeShouldShowTroubleConnecting_(network.state)',
+      value: false,
     },
 
     /** @protected {string} */
@@ -79,6 +93,25 @@
       type: String,
       value: '',
     },
+
+    /** @protected {boolean} */
+    unableToObtainIpAddress_: {
+      type: Boolean,
+      value: false,
+    },
+
+    /** @protected {TroubleshootingInfo} */
+    troubleshootingInfo_: {
+      type: Object,
+      computed: 'computeTroubleshootingInfo_(network.*,' +
+          ' unableToObtainIpAddress_)',
+    },
+
+    /** @private */
+    timerId_: {
+      type: Number,
+      value: -1,
+    },
   },
 
   observers: ['observeNetwork_(guid)'],
@@ -119,6 +152,26 @@
     this.networkState_ = getNetworkState(network.state);
     this.macAddress_ = network.macAddress || '';
     this.set('network', network);
+    let isIpAddressMissing = !network.ipConfig || !network.ipConfig.ipAddress;
+    let isTimerInProgress = this.timerId_ !== -1;
+
+    if (!isIpAddressMissing && this.unableToObtainIpAddress_) {
+      this.unableToObtainIpAddress_ = false;
+    }
+
+    if (isIpAddressMissing && !isTimerInProgress) {
+      // Seconds to wait before displaying the troubleshooting banner.
+      let maxTicks = 30;
+      let tickCount = 0;
+      this.timerId_ = setInterval(() => {
+        if (tickCount >= maxTicks) {
+          clearInterval(this.timerId_);
+          this.timerId_ = -1;
+          this.unableToObtainIpAddress_ = true;
+        }
+        tickCount++;
+      }, 1000);
+    }
   },
 
   /** @protected */
@@ -145,6 +198,10 @@
       return false;
     }
 
+    if (this.unableToObtainIpAddress_) {
+      return false;
+    }
+
     // Show the data-points when portal, online, connected, or connecting.
     switch (this.network.state) {
       case NetworkState.kPortal:
@@ -193,4 +250,104 @@
     }
     return formatMacAddress(this.macAddress_);
   },
+
+  /**
+   * @private
+   * @return {!TroubleshootingInfo}
+   */
+  getDisabledTroubleshootingInfo_() {
+    return {
+      header: this.i18n('disabledText', this.networkType_),
+      linkText: this.i18n('reconnectLinkText'),
+      url: SETTINGS_URL,
+    }
+  },
+
+  /**
+   * @private
+   * @return {!TroubleshootingInfo}
+   */
+  getNotConnectedTroubleshootingInfo_() {
+    return {
+      header: this.i18n('troubleshootingText', this.networkType_),
+      linkText: this.i18n('troubleConnecting'),
+      url: BASE_SUPPORT_URL,
+    }
+  },
+
+  /**
+   * @private
+   * @return {!TroubleshootingInfo}
+   */
+  computeTroubleshootingInfo_() {
+    let troubleshootingState = null;
+    if (!this.network || isConnectedOrOnline(this.network.state)) {
+      // Hide the troubleshooting banner if we're in an active state
+      // unlesss the network's IP Address has been missing for >=30
+      // seconds in which case we'd like to display the bannner to
+      // the user.
+      if (this.unableToObtainIpAddress_) {
+        troubleshootingState = TroubleshootingState.kMissingIpAddress;
+      }
+
+      if (troubleshootingState == null) {
+        this.showTroubleshootingCard_ = false;
+        return {
+          header: '',
+          linkText: '',
+          url: '',
+        };
+      }
+    }
+
+    let isDisabled = this.network.state === NetworkState.kDisabled;
+    let isNotConnected = this.network.state === NetworkState.kNotConnected;
+    // Override the |troubleshootingState| value if necessary since the
+    // disabled and not connected states take precedence.
+    if (isNotConnected) {
+      troubleshootingState = TroubleshootingState.kNotConnected;
+    }
+
+    if (isDisabled) {
+      troubleshootingState = TroubleshootingState.kDisabled;
+    }
+
+    // At this point, |isConnectedOrOnline| was falsy which means
+    // out network state is either disabled or not connected.
+    this.showTroubleshootingCard_ = true;
+    return this.getInfoProperties_(
+        /** @type {!TroubleshootingState} */ (troubleshootingState));
+  },
+
+  /**
+   * @private
+   * @return {!TroubleshootingInfo}
+   */
+  getMissingIpAddressInfo_() {
+    return {
+      header: this.i18n('noIpAddressText'),
+      linkText: this.i18n('visitSettingsToConfigureLinkText'),
+      url: SETTINGS_URL,
+    }
+  },
+
+  /**
+   * @private
+   * @param {!TroubleshootingState} state
+   * @return {!TroubleshootingInfo}
+   */
+  getInfoProperties_(state) {
+    switch (state) {
+      case TroubleshootingState.kDisabled:
+        return this.getDisabledTroubleshootingInfo_();
+      case TroubleshootingState.kNotConnected:
+        return this.getNotConnectedTroubleshootingInfo_();
+      case TroubleshootingState.kMissingIpAddress:
+        return this.getMissingIpAddressInfo_();
+      default:
+        return {
+          header: '', linkText: '', url: '',
+        }
+    }
+  },
 });
diff --git a/ash/webui/diagnostics_ui/resources/network_troubleshooting.html b/ash/webui/diagnostics_ui/resources/network_troubleshooting.html
index 063fd77f..d0cc1aa 100644
--- a/ash/webui/diagnostics_ui/resources/network_troubleshooting.html
+++ b/ash/webui/diagnostics_ui/resources/network_troubleshooting.html
@@ -1,9 +1,9 @@
 <style include="diagnostics-shared diagnostics-fonts">
-  #troubleConnectingText {
+  #troubleshootingText {
     @apply --diagnostics-no-ethernet-font;
   }
 
-  #troubleConnectingContainer {
+  #troubleshootingContainer {
     align-items: center;
     display: flex;
     flex-direction: column;
@@ -12,18 +12,18 @@
     padding-top: 22px;
   }
 
-  #troubleConnectingLinkText {
+  #troubleshootingLinkText {
     @apply --diagnostics-connecting-link-font;
     margin-top: 8px;
   }
 </style>
 
-<div id="troubleConnectingContainer" class="grey-container">
-  <span id="troubleConnectingText">
-    [[computeTroubleConnectingText_(networkType)]]
+<div id="troubleshootingContainer" class="grey-container">
+  <span id="troubleshootingText">
+    [[troubleshootingInfo.header]]
   </span>
-  <span id="troubleConnectingLinkText" class="link-text"
-      on-click="onTroubleConnectingClicked_">
-    [[computeLinkText_(disabled)]]
+  <span id="troubleshootingLinkText" class="link-text"
+      on-click="onLinkTextClicked_">
+    [[troubleshootingInfo.linkText]]
   </span>
 </div>
diff --git a/ash/webui/diagnostics_ui/resources/network_troubleshooting.js b/ash/webui/diagnostics_ui/resources/network_troubleshooting.js
index 8dd7e37..48d601e 100644
--- a/ash/webui/diagnostics_ui/resources/network_troubleshooting.js
+++ b/ash/webui/diagnostics_ui/resources/network_troubleshooting.js
@@ -6,9 +6,10 @@
 import './diagnostics_shared_css.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
-import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import {TroubleshootingInfo} from './diagnostics_types.js';
+
 /**
  * @constructor
  * @extends {PolymerElement}
@@ -30,35 +31,16 @@
 
   static get properties() {
     return {
-      networkType: {type: String, value: ''}, disabled: {type: Boolean},
+      /** @type {TroubleshootingInfo} */
+      troubleshootingInfo: {
+        type: Object,
+      },
     }
   }
 
   /** @protected */
-  onTroubleConnectingClicked_() {
-    let url = this.disabled ?
-        'chrome://os-settings/' :
-        'https://support.google.com/chromebook?p=diagnostics_';
-    // TODO(michaelcheco): Add correct support URL.
-    window.open(url);
-  }
-
-  /**
-   * @protected
-   * @return {string}
-   */
-  computeTroubleConnectingText_() {
-    let stringId = this.disabled ? 'disabledText' : 'troubleshootingText';
-    return loadTimeData.getStringF(stringId, this.networkType);
-  }
-
-  /**
-   * @protected
-   * @return {string}
-   */
-  computeLinkText_() {
-    return loadTimeData.getString(
-        this.disabled ? 'reconnectLinkText' : 'troubleConnecting');
+  onLinkTextClicked_() {
+    window.open(this.troubleshootingInfo.url);
   }
 }
 
diff --git a/ash/webui/diagnostics_ui/resources/routine_result_entry.html b/ash/webui/diagnostics_ui/resources/routine_result_entry.html
index c7cb1256..1c078e3 100644
--- a/ash/webui/diagnostics_ui/resources/routine_result_entry.html
+++ b/ash/webui/diagnostics_ui/resources/routine_result_entry.html
@@ -59,7 +59,7 @@
     display: inline-flex;
   }
 
-  .routineLinkContainer {
+  .failedTestTextContainer {
     margin-left: 8px;
   }
 
@@ -125,14 +125,10 @@
   </template>
  </div>
   <div id="routine" aria-hidden="true">
-    <span>[[routineType_]]</span>
-    <span class="routineLinkContainer" hidden$="[[!routineLink_]]">
-      <a href="[[routineLink_]]" class="routineLink" aria-labelledby="routine">
-        <iron-icon icon="cr:open-in-new"></iron-icon>
-      </a>
-    </span>
-    <span id="failedTestText" class="routineLinkContainer"
-        hidden$="[[!item.failedTest]]">
+    <span tabindex="0">[[routineType_]]</span>
+    <span id="failedTestText" class="failedTestTextContainer"
+        hidden$="[[!item.failedTest]]"
+        tabindex="0">
       [[computeFailedTestText_(item.failedTest)]]
     </span>
   </div>
diff --git a/ash/webui/diagnostics_ui/resources/routine_result_entry.js b/ash/webui/diagnostics_ui/resources/routine_result_entry.js
index f9698db..b393049 100644
--- a/ash/webui/diagnostics_ui/resources/routine_result_entry.js
+++ b/ash/webui/diagnostics_ui/resources/routine_result_entry.js
@@ -74,37 +74,6 @@
 }
 
 /**
- * Maps routine to help doc URL
- * @param {!RoutineType} routineType
- * @return {string} url to help docs
- */
-export function lookupLinkForRoutine(routineType) {
-  let url = '';
-  // TODO(ashleydp): Get actual routine links.
-  switch (routineType) {
-    case RoutineType.kCaptivePortal:
-    case RoutineType.kDnsLatency:
-    case RoutineType.kDnsResolution:
-    case RoutineType.kDnsResolverPresent:
-    case RoutineType.kGatewayCanBePinged:
-    case RoutineType.kHasSecureWiFiConnection:
-    case RoutineType.kHttpFirewall:
-    case RoutineType.kHttpsFirewall:
-    case RoutineType.kHttpsLatency:
-    case RoutineType.kLanConnectivity:
-    case RoutineType.kSignalStrength:
-    case RoutineType.kArcHttp:
-    case RoutineType.kArcPing:
-    case RoutineType.kArcDnsResolution:
-      url = '#'
-      break;
-    default:
-      break;
-  }
-  return url;
-}
-
-/**
  * @param {!RoutineResult} result
  * @return {?StandardRoutineResult}
  */
@@ -149,12 +118,6 @@
       computed: 'getRunningRoutineString_(item.*)',
     },
 
-    /** @protected */
-    routineLink_: {
-      type: String,
-      computed: 'getRoutineLink_(item.*)',
-    },
-
     /** @protected {!BadgeType} */
     badgeType_: {
       type: String,
@@ -207,16 +170,6 @@
   },
 
   /**
-   * Get routine's help/info link from lookup function
-   * @return {string}
-   * @private
-   */
-  getRoutineLink_() {
-    // TODO(michaelcheco): Use |lookupLinkForRoutine| to get correct links.
-    return this.usingRoutineGroups ? '#' : '';
-  },
-
-  /**
    * @private
    */
   entryStatusChanged_() {
diff --git a/ash/webui/diagnostics_ui/resources/system_page.js b/ash/webui/diagnostics_ui/resources/system_page.js
index 34a4163..380cb57e8 100644
--- a/ash/webui/diagnostics_ui/resources/system_page.js
+++ b/ash/webui/diagnostics_ui/resources/system_page.js
@@ -114,7 +114,11 @@
     this.fetchSystemInfo_();
     this.browserProxy_ = DiagnosticsBrowserProxyImpl.getInstance();
     this.browserProxy_.initialize();
-    this.addCautionBannerEventListeners_();
+
+    // Only use inner banner behavior if system page is in stand-alone mode.
+    if (!this.isNetworkingEnabled) {
+      this.addCautionBannerEventListeners_();
+    }
   },
 
   /** @private */
diff --git a/ash/webui/diagnostics_ui/resources/wifi_info.html b/ash/webui/diagnostics_ui/resources/wifi_info.html
index fc8552ad..7c365fe 100644
--- a/ash/webui/diagnostics_ui/resources/wifi_info.html
+++ b/ash/webui/diagnostics_ui/resources/wifi_info.html
@@ -1,4 +1,7 @@
 <style include="diagnostics-shared diagnostics-fonts">
+  :host {
+    --divider-horizontal-height: 100%;
+  }
 </style>
 <div id="wifiInfoContainer">
   <div class="horizontal-data-point-container">
diff --git a/ash/webui/shortcut_customization_ui/resources/accelerator_view.js b/ash/webui/shortcut_customization_ui/resources/accelerator_view.js
index d7998666..5c1d705 100644
--- a/ash/webui/shortcut_customization_ui/resources/accelerator_view.js
+++ b/ash/webui/shortcut_customization_ui/resources/accelerator_view.js
@@ -471,31 +471,34 @@
    */
   requestUpdateAccelerator_(newKeys) {
     if (this.viewState === ViewState.EDIT) {
-      this.requestReplaceAccelerator_(newKeys);
-      return;
+      this.shortcutProvider_
+          .replaceAccelerator(
+              this.source, this.action, this.acceleratorInfo.accelerator,
+              newKeys)
+          .then((result) => {
+            // TODO(jimmyxgong): Handle other error cases.
+            if (result === AcceleratorConfigResult.kSuccess) {
+              this.lookupManager_.replaceAccelerator(
+                  this.source, this.action, this.acceleratorInfo.accelerator,
+                  newKeys);
+              this.fireUpdateEvent_();
+            }
+          });
+      ;
     }
-    // TODO(jimmyxgong): Handle ViewState.ADD.
-  }
 
-  /**
-   * @param {!AcceleratorKeys} newKeys
-   * @private
-   */
-  requestReplaceAccelerator_(newKeys) {
-    this.shortcutProvider_
-        .replaceAccelerator(
-            this.source, this.action, this.acceleratorInfo.accelerator, newKeys)
-        .then((result) => {
-          // TODO(jimmyxgong): Handle other error cases.
-          if (result === AcceleratorConfigResult.kSuccess) {
-            this.lookupManager_.replaceAccelerator(
-                this.source, this.action, this.acceleratorInfo.accelerator,
-                newKeys);
-            // End capture and update accelerators.
-            this.fireUpdateEvent_();
-            this.endCapture_();
-          }
-        });
+    if (this.viewState === ViewState.ADD) {
+      this.shortcutProvider_
+          .addUserAccelerator(this.source, this.action, newKeys)
+          .then((result) => {
+            // TODO(jimmyxgong): Handle other error cases.
+            if (result === AcceleratorConfigResult.kSuccess) {
+              this.lookupManager_.addAccelerator(
+                  this.source, this.action, newKeys);
+              this.fireUpdateEvent_();
+            }
+          });
+    }
   }
 
   /** @private */
@@ -505,6 +508,9 @@
       composed: true,
       detail: {source: this.source, action: this.action}
     }));
+
+    // Always end input capturing if an update event was fired.
+    this.endCapture_();
   }
 }
 
diff --git a/ash/wm/ash_focus_rules.cc b/ash/wm/ash_focus_rules.cc
index 5f1a912..a68916e 100644
--- a/ash/wm/ash_focus_rules.cc
+++ b/ash/wm/ash_focus_rules.cc
@@ -10,8 +10,8 @@
 #include "ash/shell_delegate.h"
 #include "ash/wm/container_finder.h"
 #include "ash/wm/desks/desks_util.h"
-#include "ash/wm/full_restore/full_restore_controller.h"
 #include "ash/wm/mru_window_tracker.h"
+#include "ash/wm/window_restore/window_restore_controller.h"
 #include "ash/wm/window_state.h"
 #include "base/containers/contains.h"
 #include "components/app_restore/full_restore_utils.h"
@@ -102,13 +102,13 @@
   if (!window)
     return true;
 
-  if (!FullRestoreController::CanActivateFullRestoredWindow(window))
+  if (!WindowRestoreController::CanActivateFullRestoredWindow(window))
     return false;
 
   // Special case during Full Restore that prevents the app list from being
   // activated during tablet mode if the topmost window of any root window is a
   // Full Restore'd window. See http://crbug/1202923.
-  if (!FullRestoreController::CanActivateAppList(window))
+  if (!WindowRestoreController::CanActivateAppList(window))
     return false;
 
   if (!BaseFocusRules::CanActivateWindow(window))
diff --git a/ash/wm/container_finder.cc b/ash/wm/container_finder.cc
index ddcee4f..68203b7a43 100644
--- a/ash/wm/container_finder.cc
+++ b/ash/wm/container_finder.cc
@@ -92,11 +92,11 @@
     target_root = FindContainerRoot(bounds_in_screen);
   }
 
-  // For full restore, the window may be created before the associated full
+  // For window restore, the window may be created before the associated window
   // restore data can be retrieved. In this case, we will place it in a hidden
-  // container and will move it to a desk container when the full restore data
+  // container and will move it to a desk container when the window restore data
   // can be retrieved. An example would be ARC windows, which can be created
-  // before their associated tasks are, which are required to retrieve full
+  // before their associated tasks are, which are required to retrieve window
   // restore data.
   if (window->GetProperty(app_restore::kParentToHiddenContainerKey))
     return target_root->GetChildById(kShellWindowId_UnparentedContainer);
diff --git a/ash/wm/desks/desks_controller.cc b/ash/wm/desks/desks_controller.cc
index b71660c..b81baa1 100644
--- a/ash/wm/desks/desks_controller.cc
+++ b/ash/wm/desks/desks_controller.cc
@@ -25,7 +25,6 @@
 #include "ash/wm/desks/desks_animations.h"
 #include "ash/wm/desks/desks_restore_util.h"
 #include "ash/wm/desks/desks_util.h"
-#include "ash/wm/full_restore/full_restore_util.h"
 #include "ash/wm/mru_window_tracker.h"
 #include "ash/wm/overview/overview_controller.h"
 #include "ash/wm/overview/overview_grid.h"
@@ -35,6 +34,7 @@
 #include "ash/wm/switchable_windows.h"
 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "ash/wm/window_cycle/window_cycle_controller.h"
+#include "ash/wm/window_restore/window_restore_util.h"
 #include "ash/wm/window_util.h"
 #include "base/auto_reset.h"
 #include "base/bind.h"
diff --git a/ash/wm/desks/desks_controller.h b/ash/wm/desks/desks_controller.h
index 7f73521d..96c2bb2 100644
--- a/ash/wm/desks/desks_controller.h
+++ b/ash/wm/desks/desks_controller.h
@@ -74,6 +74,10 @@
   };
 
   DesksController();
+
+  DesksController(const DesksController&) = delete;
+  DesksController& operator=(const DesksController&) = delete;
+
   ~DesksController() override;
 
   // Convenience method for returning the DesksController instance.
@@ -370,8 +374,6 @@
 
   // Scheduler for reporting the weekly active desks metric.
   base::OneShotTimer weekly_active_desks_scheduler_;
-
-  DISALLOW_COPY_AND_ASSIGN(DesksController);
 };
 
 }  // namespace ash
diff --git a/ash/wm/lock_action_handler_layout_manager_unittest.cc b/ash/wm/lock_action_handler_layout_manager_unittest.cc
index 8d61ebe..aa2a6af 100644
--- a/ash/wm/lock_action_handler_layout_manager_unittest.cc
+++ b/ash/wm/lock_action_handler_layout_manager_unittest.cc
@@ -170,6 +170,14 @@
     : public LockActionHandlerLayoutManagerTest {
  public:
   LockActionHandlerLayoutManagerTestWithTestBackgroundController() = default;
+
+  LockActionHandlerLayoutManagerTestWithTestBackgroundController(
+      const LockActionHandlerLayoutManagerTestWithTestBackgroundController&) =
+      delete;
+  LockActionHandlerLayoutManagerTestWithTestBackgroundController& operator=(
+      const LockActionHandlerLayoutManagerTestWithTestBackgroundController&) =
+      delete;
+
   ~LockActionHandlerLayoutManagerTestWithTestBackgroundController() override =
       default;
 
@@ -194,9 +202,6 @@
   // The lock screen action background controller created by
   // |CreateActionBackgroundController|.
   TestLockScreenActionBackgroundController* background_controller_ = nullptr;
-
-  DISALLOW_COPY_AND_ASSIGN(
-      LockActionHandlerLayoutManagerTestWithTestBackgroundController);
 };
 
 TEST_F(LockActionHandlerLayoutManagerTest, PreserveNormalWindowBounds) {
diff --git a/ash/wm/mru_window_tracker.cc b/ash/wm/mru_window_tracker.cc
index 1ce3533..338462c3 100644
--- a/ash/wm/mru_window_tracker.cc
+++ b/ash/wm/mru_window_tracker.cc
@@ -13,8 +13,8 @@
 #include "ash/shell.h"
 #include "ash/wm/ash_focus_rules.h"
 #include "ash/wm/desks/desks_util.h"
-#include "ash/wm/full_restore/full_restore_controller.h"
 #include "ash/wm/switchable_windows.h"
+#include "ash/wm/window_restore/window_restore_controller.h"
 #include "ash/wm/window_state.h"
 #include "ash/wm/window_util.h"
 #include "base/containers/adapters.h"
@@ -303,7 +303,7 @@
   SetActiveWindow(gained_active);
 
   if (gained_active && full_restore::features::IsFullRestoreEnabled())
-    FullRestoreController::Get()->OnWindowActivated(gained_active);
+    WindowRestoreController::Get()->OnWindowActivated(gained_active);
 }
 
 void MruWindowTracker::OnWindowDestroyed(aura::Window* window) {
@@ -327,7 +327,7 @@
   // their MRU order.
   window->AddObserver(this);
   mru_windows_.insert(
-      FullRestoreController::GetWindowToInsertBefore(window, mru_windows_),
+      WindowRestoreController::GetWindowToInsertBefore(window, mru_windows_),
       window);
 }
 
diff --git a/ash/wm/overview/overview_highlight_controller.h b/ash/wm/overview/overview_highlight_controller.h
index d8a3620..ef761f7f 100644
--- a/ash/wm/overview/overview_highlight_controller.h
+++ b/ash/wm/overview/overview_highlight_controller.h
@@ -82,6 +82,11 @@
   };
 
   explicit OverviewHighlightController(OverviewSession* overview_session);
+
+  OverviewHighlightController(const OverviewHighlightController&) = delete;
+  OverviewHighlightController& operator=(const OverviewHighlightController&) =
+      delete;
+
   ~OverviewHighlightController();
 
   // Moves the focus ring to the next traversable view.
@@ -151,8 +156,6 @@
 
   // The current view that is being tab dragged, if any.
   OverviewHighlightableView* tab_dragged_view_ = nullptr;
-
-  DISALLOW_COPY_AND_ASSIGN(OverviewHighlightController);
 };
 
 }  // namespace ash
diff --git a/ash/wm/root_window_layout_manager_unittest.cc b/ash/wm/root_window_layout_manager_unittest.cc
index 62ced3f1..68556c8 100644
--- a/ash/wm/root_window_layout_manager_unittest.cc
+++ b/ash/wm/root_window_layout_manager_unittest.cc
@@ -15,6 +15,9 @@
  public:
   explicit WindowDeleter(aura::Window* window) : target_(window) {}
 
+  WindowDeleter(const WindowDeleter&) = delete;
+  WindowDeleter& operator=(const WindowDeleter&) = delete;
+
   // aura::WindowObserver::
   void OnWindowBoundsChanged(aura::Window* window,
                              const gfx::Rect& old_bounds,
@@ -25,8 +28,6 @@
 
  private:
   aura::Window* target_;
-
-  DISALLOW_COPY_AND_ASSIGN(WindowDeleter);
 };
 
 }  // namespace
diff --git a/ash/wm/screen_pinning_controller.cc b/ash/wm/screen_pinning_controller.cc
index 8ef5b03d..65c70df 100644
--- a/ash/wm/screen_pinning_controller.cc
+++ b/ash/wm/screen_pinning_controller.cc
@@ -69,13 +69,17 @@
       ScreenPinningController* controller)
       : controller_(controller) {}
 
+  PinnedContainerChildWindowObserver(
+      const PinnedContainerChildWindowObserver&) = delete;
+  PinnedContainerChildWindowObserver& operator=(
+      const PinnedContainerChildWindowObserver&) = delete;
+
   void OnWindowStackingChanged(aura::Window* window) override {
     controller_->OnPinnedContainerWindowStackingChanged(window);
   }
 
  private:
   ScreenPinningController* controller_;
-  DISALLOW_COPY_AND_ASSIGN(PinnedContainerChildWindowObserver);
 };
 
 // Adapter to translate OnWindowAdded/OnWillRemoveWindow for the container
@@ -86,6 +90,10 @@
   explicit PinnedContainerWindowObserver(ScreenPinningController* controller)
       : controller_(controller) {}
 
+  PinnedContainerWindowObserver(const PinnedContainerWindowObserver&) = delete;
+  PinnedContainerWindowObserver& operator=(
+      const PinnedContainerWindowObserver&) = delete;
+
   void OnWindowAdded(aura::Window* new_window) override {
     controller_->OnWindowAddedToPinnedContainer(new_window);
   }
@@ -99,7 +107,6 @@
 
  private:
   ScreenPinningController* controller_;
-  DISALLOW_COPY_AND_ASSIGN(PinnedContainerWindowObserver);
 };
 
 // Adapter to fire OnSystemModalContainerWindowStackingChanged().
@@ -110,13 +117,17 @@
       ScreenPinningController* controller)
       : controller_(controller) {}
 
+  SystemModalContainerChildWindowObserver(
+      const SystemModalContainerChildWindowObserver&) = delete;
+  SystemModalContainerChildWindowObserver& operator=(
+      const SystemModalContainerChildWindowObserver&) = delete;
+
   void OnWindowStackingChanged(aura::Window* window) override {
     controller_->OnSystemModalContainerWindowStackingChanged(window);
   }
 
  private:
   ScreenPinningController* controller_;
-  DISALLOW_COPY_AND_ASSIGN(SystemModalContainerChildWindowObserver);
 };
 
 // Adapter to translate OnWindowAdded/OnWillRemoveWindow for the
@@ -128,6 +139,11 @@
       ScreenPinningController* controller)
       : controller_(controller) {}
 
+  SystemModalContainerWindowObserver(
+      const SystemModalContainerWindowObserver&) = delete;
+  SystemModalContainerWindowObserver& operator=(
+      const SystemModalContainerWindowObserver&) = delete;
+
   void OnWindowAdded(aura::Window* new_window) override {
     controller_->OnWindowAddedToSystemModalContainer(new_window);
   }
@@ -141,7 +157,6 @@
 
  private:
   ScreenPinningController* controller_;
-  DISALLOW_COPY_AND_ASSIGN(SystemModalContainerWindowObserver);
 };
 
 ScreenPinningController::ScreenPinningController()
diff --git a/ash/wm/session_state_animator.h b/ash/wm/session_state_animator.h
index febf5b5..7ca47f4 100644
--- a/ash/wm/session_state_animator.h
+++ b/ash/wm/session_state_animator.h
@@ -166,6 +166,10 @@
   };
 
   SessionStateAnimator();
+
+  SessionStateAnimator(const SessionStateAnimator&) = delete;
+  SessionStateAnimator& operator=(const SessionStateAnimator&) = delete;
+
   virtual ~SessionStateAnimator();
 
   // Reports animation duration for |speed|.
@@ -199,9 +203,6 @@
 
   // Hides the wallpaper immediately.
   virtual void HideWallpaper() = 0;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(SessionStateAnimator);
 };
 
 }  // namespace ash
diff --git a/ash/wm/session_state_animator_impl.cc b/ash/wm/session_state_animator_impl.cc
index a7e159d..236dca9d 100644
--- a/ash/wm/session_state_animator_impl.cc
+++ b/ash/wm/session_state_animator_impl.cc
@@ -342,6 +342,9 @@
         sequences_attached_(0),
         sequences_completed_(0) {}
 
+  AnimationSequence(const AnimationSequence&) = delete;
+  AnimationSequence& operator=(const AnimationSequence&) = delete;
+
   // SessionStateAnimator::AnimationSequence:
   void StartAnimation(int container_mask,
                       SessionStateAnimator::AnimationType type,
@@ -380,8 +383,6 @@
 
   // Number of sequences either ended or aborted.
   int sequences_completed_;
-
-  DISALLOW_COPY_AND_ASSIGN(AnimationSequence);
 };
 
 bool SessionStateAnimatorImpl::TestApi::ContainersAreAnimated(
diff --git a/ash/wm/session_state_animator_impl.h b/ash/wm/session_state_animator_impl.h
index 9e7e8fe..7794cfd 100644
--- a/ash/wm/session_state_animator_impl.h
+++ b/ash/wm/session_state_animator_impl.h
@@ -26,6 +26,9 @@
     explicit TestApi(SessionStateAnimatorImpl* animator)
         : animator_(animator) {}
 
+    TestApi(const TestApi&) = delete;
+    TestApi& operator=(const TestApi&) = delete;
+
     // Returns true if containers of a given |container_mask|
     // were last animated with |type| (probably; the analysis is fairly ad-hoc).
     // |container_mask| is a bitfield of a Container.
@@ -38,11 +41,13 @@
 
    private:
     SessionStateAnimatorImpl* animator_;  // not owned
-
-    DISALLOW_COPY_AND_ASSIGN(TestApi);
   };
 
   SessionStateAnimatorImpl();
+
+  SessionStateAnimatorImpl(const SessionStateAnimatorImpl&) = delete;
+  SessionStateAnimatorImpl& operator=(const SessionStateAnimatorImpl&) = delete;
+
   ~SessionStateAnimatorImpl() override;
 
   // Fills |containers| with the containers included in |container_mask|.
@@ -78,8 +83,6 @@
                              SessionStateAnimator::AnimationType type,
                              SessionStateAnimator::AnimationSpeed speed,
                              ui::LayerAnimationObserver* observer);
-
-  DISALLOW_COPY_AND_ASSIGN(SessionStateAnimatorImpl);
 };
 
 }  // namespace ash
diff --git a/ash/wm/splitview/split_view_controller.cc b/ash/wm/splitview/split_view_controller.cc
index 0df2511..e79eefb 100644
--- a/ash/wm/splitview/split_view_controller.cc
+++ b/ash/wm/splitview/split_view_controller.cc
@@ -22,7 +22,6 @@
 #include "ash/style/default_color_constants.h"
 #include "ash/style/default_colors.h"
 #include "ash/wm/desks/desks_controller.h"
-#include "ash/wm/full_restore/full_restore_controller.h"
 #include "ash/wm/mru_window_tracker.h"
 #include "ash/wm/overview/overview_controller.h"
 #include "ash/wm/overview/overview_grid.h"
@@ -38,6 +37,7 @@
 #include "ash/wm/window_positioning_utils.h"
 #include "ash/wm/window_properties.h"
 #include "ash/wm/window_resizer.h"
+#include "ash/wm/window_restore/window_restore_controller.h"
 #include "ash/wm/window_state.h"
 #include "ash/wm/window_transient_descendant_iterator.h"
 #include "ash/wm/window_util.h"
@@ -786,12 +786,12 @@
   if (!WindowState::Get(window)->CanSnap())
     return false;
 
-  // Windows created by full restore are not activatable while being restored.
+  // Windows created by window restore are not activatable while being restored.
   // However, we still want to be able to snap these windows at this point.
   bool restoring_snap_state = false;
   if (full_restore::features::IsFullRestoreEnabled()) {
     restoring_snap_state =
-        FullRestoreController::Get()->is_restoring_snap_state();
+        WindowRestoreController::Get()->is_restoring_snap_state();
   }
 
   // TODO(sammiequon): Investigate if we need to check for window activation.
diff --git a/ash/wm/splitview/split_view_divider.cc b/ash/wm/splitview/split_view_divider.cc
index fce56cc..47689b3 100644
--- a/ash/wm/splitview/split_view_divider.cc
+++ b/ash/wm/splitview/split_view_divider.cc
@@ -250,6 +250,14 @@
   split_view_window_targeter_ = std::make_unique<aura::ScopedWindowTargeter>(
       always_on_top_container, std::make_unique<AlwaysOnTopWindowTargeter>(
                                    divider_widget_->GetNativeWindow()));
+
+  // Observe currently snapped windows.
+  for (auto snap_pos : {SplitViewController::SnapPosition::LEFT,
+                        SplitViewController::SnapPosition::RIGHT}) {
+    auto* window = controller_->GetSnappedWindow(snap_pos);
+    if (window)
+      AddObservedWindow(window);
+  }
 }
 
 SplitViewDivider::~SplitViewDivider() {
diff --git a/ash/wm/splitview/split_view_metrics_controller.cc b/ash/wm/splitview/split_view_metrics_controller.cc
index 590f3343..b28554f 100644
--- a/ash/wm/splitview/split_view_metrics_controller.cc
+++ b/ash/wm/splitview/split_view_metrics_controller.cc
@@ -9,12 +9,12 @@
 #include "ash/shell.h"
 #include "ash/wm/desks/desk.h"
 #include "ash/wm/desks/desks_util.h"
-#include "ash/wm/full_restore/full_restore_controller.h"
 #include "ash/wm/mru_window_tracker.h"
 #include "ash/wm/overview/overview_controller.h"
 #include "ash/wm/splitview/split_view_controller.h"
 #include "ash/wm/switchable_windows.h"
 #include "ash/wm/window_positioning_utils.h"
+#include "ash/wm/window_restore/window_restore_controller.h"
 #include "ash/wm/window_state.h"
 #include "ash/wm/window_util.h"
 #include "base/check_op.h"
@@ -435,9 +435,9 @@
   // `WindowStateObserver` will be added later in `OnWindowParentChanged`.
   window->AddObserver(this);
   no_state_observed_windows_.insert(window);
-  observed_windows_.insert(
-      FullRestoreController::GetWindowToInsertBefore(window, observed_windows_),
-      window);
+  observed_windows_.insert(WindowRestoreController::GetWindowToInsertBefore(
+                               window, observed_windows_),
+                           window);
 }
 
 void SplitViewMetricsController::StartRecordSplitViewMetrics() {
diff --git a/ash/wm/splitview/split_view_metrics_controller.h b/ash/wm/splitview/split_view_metrics_controller.h
index 208d2df..bb7dc415 100644
--- a/ash/wm/splitview/split_view_metrics_controller.h
+++ b/ash/wm/splitview/split_view_metrics_controller.h
@@ -219,9 +219,9 @@
   // Observed windows on the active desk.
   std::vector<aura::Window*> observed_windows_;
 
-  // Windows that recovered by full restore have no parents at the initialize
+  // Windows that recovered by window restore have no parents at the initialize
   // stage, so their window states cannot be observed when are inserted into
-  // `observed_windows_` list. This set contains the windows recovered by full
+  // `observed_windows_` list. This set contains the windows recovered by window
   // restored whose window states have not been observed yet.
   std::set<aura::Window*> no_state_observed_windows_;
 
diff --git a/ash/wm/system_gesture_event_filter_unittest.cc b/ash/wm/system_gesture_event_filter_unittest.cc
index eb177d8..0f028e9 100644
--- a/ash/wm/system_gesture_event_filter_unittest.cc
+++ b/ash/wm/system_gesture_event_filter_unittest.cc
@@ -57,6 +57,9 @@
  public:
   MaxSizeNCFV() = default;
 
+  MaxSizeNCFV(const MaxSizeNCFV&) = delete;
+  MaxSizeNCFV& operator=(const MaxSizeNCFV&) = delete;
+
  private:
   gfx::Size GetMaximumSize() const override { return gfx::Size(200, 200); }
   gfx::Rect GetBoundsForClientView() const override { return gfx::Rect(); }
@@ -76,8 +79,6 @@
   void UpdateWindowIcon() override {}
   void UpdateWindowTitle() override {}
   void SizeConstraintsChanged() override {}
-
-  DISALLOW_COPY_AND_ASSIGN(MaxSizeNCFV);
 };
 
 class MaxSizeWidgetDelegate : public views::WidgetDelegateView {
diff --git a/ash/wm/tablet_mode/tablet_mode_window_manager.cc b/ash/wm/tablet_mode/tablet_mode_window_manager.cc
index d14b5da..7041066 100644
--- a/ash/wm/tablet_mode/tablet_mode_window_manager.cc
+++ b/ash/wm/tablet_mode/tablet_mode_window_manager.cc
@@ -19,6 +19,7 @@
 #include "ash/wm/overview/overview_controller.h"
 #include "ash/wm/overview/overview_session.h"
 #include "ash/wm/overview/overview_utils.h"
+#include "ash/wm/splitview/split_view_constants.h"
 #include "ash/wm/splitview/split_view_controller.h"
 #include "ash/wm/splitview/split_view_utils.h"
 #include "ash/wm/tablet_mode/scoped_skip_user_session_blocked_check.h"
@@ -559,21 +560,32 @@
 
   const bool horizontal = SplitViewController::IsLayoutHorizontal(display);
   const bool primary = SplitViewController::IsLayoutPrimary(display);
+
+  // We need to expand (or shrink) the width of the snapped windows by the half
+  // of the divider width when to-clamshell (or to-tablet) transition happens
+  // accordingly, because in tablet mode the "center" of the split view should
+  // be the center of the divider.
+  const int divider_padding =
+      (clamshell_to_tablet ? -1 : 1) * kSplitviewDividerShortSideLength / 2;
   if (horizontal) {
     if (primary) {
-      return left_window ? left_window_bounds.width()
-                         : work_area.width() - right_window_bounds.width();
+      return left_window ? left_window_bounds.width() + divider_padding
+                         : work_area.width() - right_window_bounds.width() -
+                               divider_padding;
     } else {
-      return left_window ? work_area.width() - left_window_bounds.width()
-                         : right_window_bounds.width();
+      return left_window ? work_area.width() - left_window_bounds.width() -
+                               divider_padding
+                         : right_window_bounds.width() + divider_padding;
     }
   } else {
     if (primary) {
-      return left_window ? left_window_bounds.height()
-                         : work_area.height() - right_window_bounds.height();
+      return left_window ? left_window_bounds.height() + divider_padding
+                         : work_area.height() - right_window_bounds.height() -
+                               divider_padding;
     } else {
-      return left_window ? work_area.height() - left_window_bounds.height()
-                         : right_window_bounds.height();
+      return left_window ? work_area.height() - left_window_bounds.height() -
+                               divider_padding
+                         : right_window_bounds.height() + divider_padding;
     }
   }
 }
diff --git a/ash/wm/tablet_mode/tablet_mode_window_manager_unittest.cc b/ash/wm/tablet_mode/tablet_mode_window_manager_unittest.cc
index 03daf97..bd3561b 100644
--- a/ash/wm/tablet_mode/tablet_mode_window_manager_unittest.cc
+++ b/ash/wm/tablet_mode/tablet_mode_window_manager_unittest.cc
@@ -1740,8 +1740,7 @@
             1200 * 0.33 - kSplitviewDividerShortSideLength / 2);
   // Exit tablet mode and verify the window stays in the same position.
   DestroyTabletModeWindowManager();
-  EXPECT_EQ(window->bounds().width(),
-            1200 * 0.33 - kSplitviewDividerShortSideLength / 2);
+  EXPECT_EQ(window->bounds().width(), 1200 * 0.33);
 
   // Now test the 2 windows case.
   std::unique_ptr<aura::Window> window2(
@@ -1764,8 +1763,7 @@
             1200 - window->bounds().width() - kSplitviewDividerShortSideLength);
   // Exit tablet mode and verify the windows stay in the same position.
   DestroyTabletModeWindowManager();
-  EXPECT_EQ(window->bounds().width(),
-            1200 * 0.33 - kSplitviewDividerShortSideLength / 2);
+  EXPECT_EQ(window->bounds().width(), 1200 * 0.33);
   EXPECT_EQ(window2->bounds().width(), 1200 - window->bounds().width());
 }
 
diff --git a/ash/wm/test_activation_delegate.h b/ash/wm/test_activation_delegate.h
index 4ab490ed..1e2fdde 100644
--- a/ash/wm/test_activation_delegate.h
+++ b/ash/wm/test_activation_delegate.h
@@ -25,6 +25,9 @@
   TestActivationDelegate();
   explicit TestActivationDelegate(bool activate);
 
+  TestActivationDelegate(const TestActivationDelegate&) = delete;
+  TestActivationDelegate& operator=(const TestActivationDelegate&) = delete;
+
   // Associates this delegate with a Window.
   void SetWindow(aura::Window* window);
 
@@ -54,8 +57,6 @@
   int activated_count_;
   int lost_active_count_;
   mutable int should_activate_count_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestActivationDelegate);
 };
 
 }  // namespace ash
diff --git a/ash/wm/video_detector.h b/ash/wm/video_detector.h
index 542529a..ec46973 100644
--- a/ash/wm/video_detector.h
+++ b/ash/wm/video_detector.h
@@ -56,6 +56,10 @@
   };
 
   VideoDetector();
+
+  VideoDetector(const VideoDetector&) = delete;
+  VideoDetector& operator=(const VideoDetector&) = delete;
+
   ~VideoDetector() override;
 
   State state() const { return state_; }
@@ -112,8 +116,6 @@
   mojo::Receiver<viz::mojom::VideoDetectorObserver> receiver_{this};
 
   base::WeakPtrFactory<VideoDetector> weak_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(VideoDetector);
 };
 
 }  // namespace ash
diff --git a/ash/wm/video_detector_unittest.cc b/ash/wm/video_detector_unittest.cc
index de0f3cd4..08266a9e 100644
--- a/ash/wm/video_detector_unittest.cc
+++ b/ash/wm/video_detector_unittest.cc
@@ -30,6 +30,9 @@
  public:
   TestObserver() = default;
 
+  TestObserver(const TestObserver&) = delete;
+  TestObserver& operator=(const TestObserver&) = delete;
+
   bool empty() const { return states_.empty(); }
   void reset() { states_.clear(); }
 
@@ -49,8 +52,6 @@
  private:
   // States in the order they were received.
   base::circular_deque<VideoDetector::State> states_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestObserver);
 };
 
 class VideoDetectorTest : public AshTestBase {
diff --git a/ash/wm/window_animations_unittest.cc b/ash/wm/window_animations_unittest.cc
index 6913032..b888a18 100644
--- a/ash/wm/window_animations_unittest.cc
+++ b/ash/wm/window_animations_unittest.cc
@@ -35,14 +35,14 @@
  public:
   WindowAnimationsTest() = default;
 
+  WindowAnimationsTest(const WindowAnimationsTest&) = delete;
+  WindowAnimationsTest& operator=(const WindowAnimationsTest&) = delete;
+
   void SetUp() override {
     base::CommandLine::ForCurrentProcess()->AppendSwitch(
         keyboard::switches::kEnableVirtualKeyboard);
     AshTestBase::SetUp();
   }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(WindowAnimationsTest);
 };
 
 // Listens to animation scheduled notifications. Remembers the transition
@@ -55,6 +55,11 @@
     // RemoveObserver is called when the first animation is scheduled and so
     // there should be no need for now to remove it in destructor.
   }
+
+  MinimizeAnimationObserver(const MinimizeAnimationObserver&) = delete;
+  MinimizeAnimationObserver& operator=(const MinimizeAnimationObserver&) =
+      delete;
+
   base::TimeDelta duration() { return duration_; }
 
  protected:
@@ -70,8 +75,6 @@
  private:
   ui::LayerAnimator* animator_;
   base::TimeDelta duration_;
-
-  DISALLOW_COPY_AND_ASSIGN(MinimizeAnimationObserver);
 };
 
 TEST_F(WindowAnimationsTest, HideShowBrightnessGrayscaleAnimation) {
diff --git a/ash/wm/window_dimmer.h b/ash/wm/window_dimmer.h
index a9a82489..10d7e70 100644
--- a/ash/wm/window_dimmer.h
+++ b/ash/wm/window_dimmer.h
@@ -53,6 +53,10 @@
   explicit WindowDimmer(aura::Window* parent,
                         bool animate = true,
                         Delegate* delegate = nullptr);
+
+  WindowDimmer(const WindowDimmer&) = delete;
+  WindowDimmer& operator=(const WindowDimmer&) = delete;
+
   ~WindowDimmer() override;
 
   aura::Window* parent() { return parent_; }
@@ -84,8 +88,6 @@
   aura::Window* window_;
 
   Delegate* delegate_;  // Not owned.
-
-  DISALLOW_COPY_AND_ASSIGN(WindowDimmer);
 };
 
 }  // namespace ash
diff --git a/ash/wm/window_manager_unittest.cc b/ash/wm/window_manager_unittest.cc
index 1bf5269..dcd2ae2a 100644
--- a/ash/wm/window_manager_unittest.cc
+++ b/ash/wm/window_manager_unittest.cc
@@ -103,10 +103,11 @@
  public:
   NonFocusableDelegate() = default;
 
+  NonFocusableDelegate(const NonFocusableDelegate&) = delete;
+  NonFocusableDelegate& operator=(const NonFocusableDelegate&) = delete;
+
  private:
   bool CanFocus() override { return false; }
-
-  DISALLOW_COPY_AND_ASSIGN(NonFocusableDelegate);
 };
 
 class HitTestWindowDelegate : public aura::test::TestWindowDelegate {
diff --git a/ash/wm/full_restore/OWNERS b/ash/wm/window_restore/OWNERS
similarity index 99%
rename from ash/wm/full_restore/OWNERS
rename to ash/wm/window_restore/OWNERS
index 51c2d97..ceaf393 100644
--- a/ash/wm/full_restore/OWNERS
+++ b/ash/wm/window_restore/OWNERS
@@ -1,2 +1,2 @@
-sammiequon@chromium.org
 chinsenj@chromium.org
+sammiequon@chromium.org
diff --git a/ash/wm/full_restore/full_restore_controller.cc b/ash/wm/window_restore/window_restore_controller.cc
similarity index 87%
rename from ash/wm/full_restore/full_restore_controller.cc
rename to ash/wm/window_restore/window_restore_controller.cc
index 2548870..d2e2dea 100644
--- a/ash/wm/full_restore/full_restore_controller.cc
+++ b/ash/wm/window_restore/window_restore_controller.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ash/wm/full_restore/full_restore_controller.h"
+#include "ash/wm/window_restore/window_restore_controller.h"
 
 #include <cstdint>
 
@@ -15,10 +15,10 @@
 #include "ash/shell.h"
 #include "ash/wm/container_finder.h"
 #include "ash/wm/desks/desks_util.h"
-#include "ash/wm/full_restore/full_restore_util.h"
 #include "ash/wm/mru_window_tracker.h"
 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "ash/wm/window_positioning_utils.h"
+#include "ash/wm/window_restore/window_restore_util.h"
 #include "ash/wm/window_state.h"
 #include "ash/wm/wm_event.h"
 #include "base/auto_reset.h"
@@ -42,11 +42,11 @@
 
 namespace {
 
-FullRestoreController* g_instance = nullptr;
+WindowRestoreController* g_instance = nullptr;
 
 // Callback for testing which is run when `SaveWindowImpl()` triggers a write to
 // file.
-FullRestoreController::SaveWindowCallback g_save_window_callback_for_testing;
+WindowRestoreController::SaveWindowCallback g_save_window_callback_for_testing;
 
 // The list of possible app window parents.
 constexpr ShellWindowId kAppParentContainers[10] = {
@@ -62,9 +62,9 @@
     kShellWindowId_UnparentedContainer,
 };
 
-// The types of apps currently supported by full restore.
+// The types of apps currently supported by window restore.
 // TODO(crbug.com/1164472): Checking app type is temporary solution until we
-// can get windows which are allowed to full restore from the
+// can get windows which are allowed to window restore from the
 // FullRestoreService.
 constexpr AppType kSupportedAppTypes[3] = {
     AppType::BROWSER, AppType::CHROME_APP, AppType::ARC_APP};
@@ -130,7 +130,7 @@
                              aura::Window* parent) override {
     if (!parent)
       return;
-    FullRestoreController::Get()->SaveAllWindows();
+    WindowRestoreController::Get()->SaveAllWindows();
     delete this;
   }
   void OnWindowDestroying(aura::Window* window) override { delete this; }
@@ -141,7 +141,7 @@
 
 }  // namespace
 
-FullRestoreController::FullRestoreController() {
+WindowRestoreController::WindowRestoreController() {
   DCHECK_EQ(nullptr, g_instance);
   g_instance = this;
 
@@ -150,18 +150,18 @@
       full_restore::FullRestoreInfo::GetInstance());
 }
 
-FullRestoreController::~FullRestoreController() {
+WindowRestoreController::~WindowRestoreController() {
   DCHECK_EQ(this, g_instance);
   g_instance = nullptr;
 }
 
 // static
-FullRestoreController* FullRestoreController::Get() {
+WindowRestoreController* WindowRestoreController::Get() {
   return g_instance;
 }
 
 // static
-bool FullRestoreController::CanActivateFullRestoredWindow(
+bool WindowRestoreController::CanActivateFullRestoredWindow(
     const aura::Window* window) {
   if (!window->GetProperty(app_restore::kLaunchedFromFullRestoreKey))
     return true;
@@ -196,7 +196,7 @@
 }
 
 // static
-bool FullRestoreController::CanActivateAppList(const aura::Window* window) {
+bool WindowRestoreController::CanActivateAppList(const aura::Window* window) {
   auto* tablet_mode_controller = Shell::Get()->tablet_mode_controller();
   if (!tablet_mode_controller || !tablet_mode_controller->InTabletMode())
     return true;
@@ -229,7 +229,7 @@
 
 // static
 std::vector<aura::Window*>::const_iterator
-FullRestoreController::GetWindowToInsertBefore(
+WindowRestoreController::GetWindowToInsertBefore(
     aura::Window* window,
     const std::vector<aura::Window*>& windows) {
   int32_t* activation_index =
@@ -253,11 +253,11 @@
   return it;
 }
 
-void FullRestoreController::SaveWindow(WindowState* window_state) {
+void WindowRestoreController::SaveWindow(WindowState* window_state) {
   SaveWindowImpl(window_state, /*activation_index=*/absl::nullopt);
 }
 
-void FullRestoreController::SaveAllWindows() {
+void WindowRestoreController::SaveAllWindows() {
   auto mru_windows =
       Shell::Get()->mru_window_tracker()->BuildMruWindowList(kAllDesks);
   for (int i = 0; i < static_cast<int>(mru_windows.size()); ++i) {
@@ -269,29 +269,29 @@
   }
 }
 
-void FullRestoreController::OnWindowActivated(aura::Window* gained_active) {
+void WindowRestoreController::OnWindowActivated(aura::Window* gained_active) {
   SaveAllWindows();
 }
 
-void FullRestoreController::OnTabletModeStarted() {
+void WindowRestoreController::OnTabletModeStarted() {
   SaveAllWindows();
 }
 
-void FullRestoreController::OnTabletModeEnded() {
+void WindowRestoreController::OnTabletModeEnded() {
   SaveAllWindows();
 }
 
-void FullRestoreController::OnTabletControllerDestroyed() {
+void WindowRestoreController::OnTabletControllerDestroyed() {
   tablet_mode_observation_.Reset();
 }
 
-void FullRestoreController::OnRestorePrefChanged(const AccountId& account_id,
-                                                 bool could_restore) {
+void WindowRestoreController::OnRestorePrefChanged(const AccountId& account_id,
+                                                   bool could_restore) {
   if (could_restore)
     SaveAllWindows();
 }
 
-void FullRestoreController::OnAppLaunched(aura::Window* window) {
+void WindowRestoreController::OnAppLaunched(aura::Window* window) {
   // Non ARC windows will already be saved as this point, as this is for cases
   // where an ARC window is created without a task.
   if (!IsArcWindow(window))
@@ -309,7 +309,7 @@
   new ParentChangeObserver(window);
 }
 
-void FullRestoreController::OnWidgetInitialized(views::Widget* widget) {
+void WindowRestoreController::OnWidgetInitialized(views::Widget* widget) {
   DCHECK(widget);
 
   aura::Window* window = widget->GetNativeWindow();
@@ -327,7 +327,7 @@
   MaybeRestoreOutOfBoundsWindows(window);
 }
 
-void FullRestoreController::OnARCTaskReadyForUnparentedWindow(
+void WindowRestoreController::OnARCTaskReadyForUnparentedWindow(
     aura::Window* window) {
   DCHECK(window);
   DCHECK(window->GetProperty(app_restore::kParentToHiddenContainerKey));
@@ -351,16 +351,16 @@
   UpdateAndObserveWindow(window);
 }
 
-void FullRestoreController::OnWindowPropertyChanged(aura::Window* window,
-                                                    const void* key,
-                                                    intptr_t old) {
+void WindowRestoreController::OnWindowPropertyChanged(aura::Window* window,
+                                                      const void* key,
+                                                      intptr_t old) {
   // If the ARC ghost window becomes ARC app's window, it should be applied
   // the activation delay.
   if (key == app_restore::kRealArcTaskWindow &&
       window->GetProperty(app_restore::kRealArcTaskWindow)) {
     window->SetProperty(app_restore::kLaunchedFromFullRestoreKey, true);
     restore_property_clear_callbacks_.emplace(
-        window, base::BindOnce(&FullRestoreController::ClearLaunchedKey,
+        window, base::BindOnce(&WindowRestoreController::ClearLaunchedKey,
                                weak_ptr_factory_.GetWeakPtr(), window));
     base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
         FROM_HERE, restore_property_clear_callbacks_[window].callback(),
@@ -382,8 +382,8 @@
     CancelAndRemoveRestorePropertyClearCallback(window);
 }
 
-void FullRestoreController::OnWindowVisibilityChanged(aura::Window* window,
-                                                      bool visible) {
+void WindowRestoreController::OnWindowVisibilityChanged(aura::Window* window,
+                                                        bool visible) {
   // `OnWindowVisibilityChanged` fires for children of a window as well, but we
   // are only interested in the window we originally observed.
   if (!windows_observation_.IsObservingSource(window))
@@ -414,7 +414,7 @@
     app_list_widget->Deactivate();
 }
 
-void FullRestoreController::OnWindowDestroying(aura::Window* window) {
+void WindowRestoreController::OnWindowDestroying(aura::Window* window) {
   DCHECK(windows_observation_.IsObservingSource(window));
   windows_observation_.RemoveObservation(window);
 
@@ -422,7 +422,7 @@
     ClearLaunchedKey(window);
 }
 
-void FullRestoreController::UpdateAndObserveWindow(aura::Window* window) {
+void WindowRestoreController::UpdateAndObserveWindow(aura::Window* window) {
   DCHECK(window);
   DCHECK(window->parent());
   windows_observation_.AddObservation(window);
@@ -449,12 +449,12 @@
   // Stack the window.
   auto siblings = window->parent()->children();
   auto insertion_point =
-      FullRestoreController::GetWindowToInsertBefore(window, siblings);
+      WindowRestoreController::GetWindowToInsertBefore(window, siblings);
   if (insertion_point != siblings.end())
     window->parent()->StackChildBelow(window, *insertion_point);
 }
 
-void FullRestoreController::SaveWindowImpl(
+void WindowRestoreController::SaveWindowImpl(
     WindowState* window_state,
     absl::optional<int> activation_index) {
   DCHECK(window_state);
@@ -495,7 +495,7 @@
     g_save_window_callback_for_testing.Run(*window_info);
 }
 
-void FullRestoreController::RestoreStateTypeAndClearLaunchedKey(
+void WindowRestoreController::RestoreStateTypeAndClearLaunchedKey(
     aura::Window* window) {
   app_restore::WindowInfo* window_info = GetWindowInfo(window);
   if (window_info) {
@@ -525,8 +525,8 @@
     }
   }
 
-  // Window that are launched from full restore are not activatable initially to
-  // prevent them from taking activation when Widget::Show() is called. Make
+  // Window that are launched from window restore are not activatable initially
+  // to prevent them from taking activation when Widget::Show() is called. Make
   // these windows activatable once they are launched. Use a post task since it
   // is quite common for some widgets to explicitly call Show() after
   // initialized.
@@ -534,7 +534,7 @@
   // and enabling it here, use ShowInactive() instead of Show() when the widget
   // is created.
   restore_property_clear_callbacks_.emplace(
-      window, base::BindOnce(&FullRestoreController::ClearLaunchedKey,
+      window, base::BindOnce(&WindowRestoreController::ClearLaunchedKey,
                              weak_ptr_factory_.GetWeakPtr(), window));
 
   // Also, for some ARC and chrome apps, the client can request activation after
@@ -555,7 +555,7 @@
       FROM_HERE, restore_property_clear_callbacks_[window].callback(), delay);
 }
 
-void FullRestoreController::ClearLaunchedKey(aura::Window* window) {
+void WindowRestoreController::ClearLaunchedKey(aura::Window* window) {
   CancelAndRemoveRestorePropertyClearCallback(window);
 
   // If the window is destroying then prevent extra work by not clearing the
@@ -564,7 +564,7 @@
     window->SetProperty(app_restore::kLaunchedFromFullRestoreKey, false);
 }
 
-void FullRestoreController::CancelAndRemoveRestorePropertyClearCallback(
+void WindowRestoreController::CancelAndRemoveRestorePropertyClearCallback(
     aura::Window* window) {
   DCHECK(window);
   DCHECK(base::Contains(restore_property_clear_callbacks_, window));
@@ -573,7 +573,7 @@
   restore_property_clear_callbacks_.erase(window);
 }
 
-void FullRestoreController::SetSaveWindowCallbackForTesting(
+void WindowRestoreController::SetSaveWindowCallbackForTesting(
     SaveWindowCallback callback) {
   g_save_window_callback_for_testing = std::move(callback);
 }
diff --git a/ash/wm/full_restore/full_restore_controller.h b/ash/wm/window_restore/window_restore_controller.h
similarity index 89%
rename from ash/wm/full_restore/full_restore_controller.h
rename to ash/wm/window_restore/window_restore_controller.h
index fe5b313..6fc3b784 100644
--- a/ash/wm/full_restore/full_restore_controller.h
+++ b/ash/wm/window_restore/window_restore_controller.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef ASH_WM_FULL_RESTORE_FULL_RESTORE_CONTROLLER_H_
-#define ASH_WM_FULL_RESTORE_FULL_RESTORE_CONTROLLER_H_
+#ifndef ASH_WM_WINDOW_RESTORE_WINDOW_RESTORE_CONTROLLER_H_
+#define ASH_WM_WINDOW_RESTORE_WINDOW_RESTORE_CONTROLLER_H_
 
 #include "ash/ash_export.h"
 #include "ash/public/cpp/tablet_mode_observer.h"
@@ -30,7 +30,7 @@
 
 class WindowState;
 
-class ASH_EXPORT FullRestoreController
+class ASH_EXPORT WindowRestoreController
     : public TabletModeObserver,
       public full_restore::FullRestoreInfo::Observer,
       public aura::WindowObserver {
@@ -38,14 +38,14 @@
   using SaveWindowCallback =
       base::RepeatingCallback<void(const app_restore::WindowInfo&)>;
 
-  FullRestoreController();
-  FullRestoreController(const FullRestoreController&) = delete;
-  FullRestoreController& operator=(const FullRestoreController&) = delete;
-  ~FullRestoreController() override;
+  WindowRestoreController();
+  WindowRestoreController(const WindowRestoreController&) = delete;
+  WindowRestoreController& operator=(const WindowRestoreController&) = delete;
+  ~WindowRestoreController() override;
 
   // Convenience function to get the controller which is created and owned by
   // Shell.
-  static FullRestoreController* Get();
+  static WindowRestoreController* Get();
 
   // Returns whether a Full Restore'd window can be activated. Only ghost
   // windows, windows without the `app_restore::kLaunchedFromFullRestoreKey`,
@@ -104,7 +104,7 @@
   bool is_restoring_snap_state() const { return is_restoring_snap_state_; }
 
  private:
-  friend class FullRestoreControllerTest;
+  friend class WindowRestoreControllerTest;
 
   // Updates the window state, activation and stacking of `window`. Also
   // observes `window` as we need to do further updates when the window is
@@ -135,7 +135,7 @@
   void CancelAndRemoveRestorePropertyClearCallback(aura::Window* window);
 
   // Sets a callback for testing that will be fired immediately when
-  // SaveWindowImpl is about to notify the full restore component we want to
+  // SaveWindowImpl is about to notify the window restore component we want to
   // write to file.
   void SetSaveWindowCallbackForTesting(SaveWindowCallback callback);
 
@@ -160,13 +160,13 @@
                           full_restore::FullRestoreInfo::Observer>
       full_restore_info_observation_{this};
 
-  // Observes windows launched by full restore.
+  // Observes windows launched by window restore.
   base::ScopedMultiSourceObservation<aura::Window, aura::WindowObserver>
       windows_observation_{this};
 
-  base::WeakPtrFactory<FullRestoreController> weak_ptr_factory_{this};
+  base::WeakPtrFactory<WindowRestoreController> weak_ptr_factory_{this};
 };
 
 }  // namespace ash
 
-#endif  // ASH_WM_FULL_RESTORE_FULL_RESTORE_CONTROLLER_H_
+#endif  // ASH_WM_WINDOW_RESTORE_WINDOW_RESTORE_CONTROLLER_H_
diff --git a/ash/wm/full_restore/full_restore_controller_unittest.cc b/ash/wm/window_restore/window_restore_controller_unittest.cc
similarity index 89%
rename from ash/wm/full_restore/full_restore_controller_unittest.cc
rename to ash/wm/window_restore/window_restore_controller_unittest.cc
index 346afa8..07b5eb7 100644
--- a/ash/wm/full_restore/full_restore_controller_unittest.cc
+++ b/ash/wm/window_restore/window_restore_controller_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ash/wm/full_restore/full_restore_controller.h"
+#include "ash/wm/window_restore/window_restore_controller.h"
 
 #include "ash/accelerators/accelerator_controller_impl.h"
 #include "ash/app_list/app_list_controller_impl.h"
@@ -54,28 +54,29 @@
 
 }  // namespace
 
-class FullRestoreControllerTest : public AshTestBase, public aura::EnvObserver {
+class WindowRestoreControllerTest : public AshTestBase,
+                                    public aura::EnvObserver {
  public:
-  // Struct which is the data in our fake full restore file.
+  // Struct which is the data in our fake window restore file.
   struct WindowInfo {
     int call_count = 0;
     std::unique_ptr<app_restore::WindowInfo> info;
   };
 
-  FullRestoreControllerTest() = default;
-  FullRestoreControllerTest(const FullRestoreControllerTest&) = delete;
-  FullRestoreControllerTest& operator=(const FullRestoreControllerTest&) =
+  WindowRestoreControllerTest() = default;
+  WindowRestoreControllerTest(const WindowRestoreControllerTest&) = delete;
+  WindowRestoreControllerTest& operator=(const WindowRestoreControllerTest&) =
       delete;
-  ~FullRestoreControllerTest() override = default;
+  ~WindowRestoreControllerTest() override = default;
 
   // Returns the number of times |window| has been saved to file since the last
   // ResetSaveWindowsCount call.
   int GetSaveWindowsCount(aura::Window* window) const {
     const int32_t restore_window_id =
         window->GetProperty(app_restore::kRestoreWindowIdKey);
-    if (!base::Contains(fake_full_restore_file_, restore_window_id))
+    if (!base::Contains(fake_window_restore_file_, restore_window_id))
       return 0;
-    return fake_full_restore_file_.at(restore_window_id).call_count;
+    return fake_window_restore_file_.at(restore_window_id).call_count;
   }
 
   // Returns the total number of saves since the last ResetSaveWindowsCount
@@ -83,14 +84,14 @@
   int GetTotalSaveWindowsCount() const {
     int count = 0;
     for (const std::pair<int32_t, WindowInfo>& member :
-         fake_full_restore_file_) {
+         fake_window_restore_file_) {
       count += member.second.call_count;
     }
     return count;
   }
 
   void ResetSaveWindowsCount() {
-    for (std::pair<int32_t, WindowInfo>& member : fake_full_restore_file_)
+    for (std::pair<int32_t, WindowInfo>& member : fake_window_restore_file_)
       member.second.call_count = 0;
   }
 
@@ -98,9 +99,9 @@
   app_restore::WindowInfo* GetWindowInfo(aura::Window* window) const {
     const int32_t restore_window_id =
         window->GetProperty(app_restore::kRestoreWindowIdKey);
-    if (!base::Contains(fake_full_restore_file_, restore_window_id))
+    if (!base::Contains(fake_window_restore_file_, restore_window_id))
       return nullptr;
-    return fake_full_restore_file_.at(restore_window_id).info.get();
+    return fake_window_restore_file_.at(restore_window_id).info.get();
   }
 
   // Returns the stored activation index for |window|.
@@ -115,17 +116,17 @@
   // Returns the restore property clear callbacks.
   const std::map<aura::Window*, base::CancelableOnceClosure>&
   GetRestorePropertyClearCallbacks() {
-    return FullRestoreController::Get()->restore_property_clear_callbacks_;
+    return WindowRestoreController::Get()->restore_property_clear_callbacks_;
   }
 
-  // Mocks creating a widget that is launched from full restore service.
+  // Mocks creating a widget that is launched from window restore service.
   views::Widget* CreateTestFullRestoredWidget(
       int32_t activation_index,
       const gfx::Rect& bounds = gfx::Rect(200, 200),
       aura::Window* root_window = Shell::GetPrimaryRootWindow()) {
     // If this is a new window, finds and sets a new restore window id.
     int32_t restore_window_id = 1;
-    while (fake_full_restore_file_.contains(restore_window_id))
+    while (fake_window_restore_file_.contains(restore_window_id))
       ++restore_window_id;
 
     AddEntryToFakeFile(restore_window_id, bounds,
@@ -138,17 +139,17 @@
   }
 
   // Mocks creating a widget based on the window info in
-  // `fake_full_restore_file_`. Returns nullptr if there is not an entry that
+  // `fake_window_restore_file_`. Returns nullptr if there is not an entry that
   // matches `restore_window_id`.
   views::Widget* CreateTestFullRestoredWidgetFromRestoreId(
       int32_t restore_window_id,
       AppType app_type,
       bool is_taskless_arc_app) {
-    if (!fake_full_restore_file_.contains(restore_window_id))
+    if (!fake_window_restore_file_.contains(restore_window_id))
       return nullptr;
 
     app_restore::WindowInfo* info =
-        fake_full_restore_file_[restore_window_id].info.get();
+        fake_window_restore_file_[restore_window_id].info.get();
     DCHECK(info);
     DCHECK(info->current_bounds);
     DCHECK(info->window_state_type);
@@ -163,9 +164,9 @@
       context = Shell::GetPrimaryRootWindow();
     DCHECK(context->IsRootWindow());
 
-    // Full restore widgets are inactive when created as we do not want to take
-    // activation from a possible activated window, and we want to stack them in
-    // a certain order.
+    // Window restore widgets are inactive when created as we do not want to
+    // take activation from a possible activated window, and we want to stack
+    // them in a certain order.
     TestWidgetBuilder widget_builder;
     widget_builder.SetWidgetType(views::Widget::InitParams::TYPE_WINDOW)
         .SetBounds(*info->current_bounds)
@@ -184,7 +185,7 @@
     views::Widget* widget = widget_builder.BuildOwnedByNativeWidget();
     SetResizable(widget);
     if (!is_taskless_arc_app)
-      FullRestoreController::Get()->OnWidgetInitialized(widget);
+      WindowRestoreController::Get()->OnWidgetInitialized(widget);
     if (info->window_state_type != chromeos::WindowStateType::kMinimized)
       widget->Show();
     return widget;
@@ -206,8 +207,8 @@
       EXPECT_EQ(children[i], expected_windows[i]);
   }
 
-  // Adds an entry to the fake full restore file. Calling
-  // If `CreateTestFullRestoreWidget` is called with a matching
+  // Adds an entry to the fake window restore file. If
+  // `CreateTestFullRestoreWidget` is called with a matching
   // `restore_window_id`, it will read and set the values set here.
   void AddEntryToFakeFile(int restore_window_id,
                           const gfx::Rect& bounds,
@@ -215,14 +216,14 @@
                           int32_t activation_index,
                           int64_t display_id,
                           int32_t desk_id) {
-    DCHECK(!fake_full_restore_file_.contains(restore_window_id));
+    DCHECK(!fake_window_restore_file_.contains(restore_window_id));
     auto window_info = std::make_unique<app_restore::WindowInfo>();
     window_info->current_bounds = bounds;
     window_info->window_state_type = window_state_type;
     window_info->activation_index = activation_index;
     window_info->display_id = display_id;
     window_info->desk_id = desk_id;
-    fake_full_restore_file_[restore_window_id].info = std::move(window_info);
+    fake_window_restore_file_[restore_window_id].info = std::move(window_info);
   }
 
   void AddEntryToFakeFile(int restore_window_id,
@@ -258,8 +259,8 @@
 
     AshTestBase::SetUp();
 
-    FullRestoreController::Get()->SetSaveWindowCallbackForTesting(
-        base::BindRepeating(&FullRestoreControllerTest::OnSaveWindow,
+    WindowRestoreController::Get()->SetSaveWindowCallbackForTesting(
+        base::BindRepeating(&WindowRestoreControllerTest::OnSaveWindow,
                             base::Unretained(this)));
     env_observation_.Observe(aura::Env::GetInstance());
 
@@ -288,51 +289,51 @@
     // If this is a new window, finds and sets a new restore window id.
     if (window->GetProperty(app_restore::kRestoreWindowIdKey) == 0) {
       int32_t restore_window_id = 1;
-      while (fake_full_restore_file_.contains(restore_window_id))
+      while (fake_window_restore_file_.contains(restore_window_id))
         ++restore_window_id;
       window->SetProperty(app_restore::kRestoreWindowIdKey, restore_window_id);
     }
 
-    // FullRestoreController relies on getting OnWindowInitialized events from
+    // WindowRestoreController relies on getting OnWindowInitialized events from
     // aura::Env via full_restore::FullRestoreInfo. That object does not exist
     // for ash unit tests, so we will observe aura::Env ourselves and forward
-    // the event to FullRestoreController.
-    FullRestoreController::Get()->OnWindowInitialized(window);
+    // the event to WindowRestoreController.
+    WindowRestoreController::Get()->OnWindowInitialized(window);
   }
 
  private:
-  // Called when FullRestoreController saves a window to the file. Immediately
-  // writes to our fake file |fake_full_restore_file_|.
+  // Called when WindowRestoreController saves a window to the file. Immediately
+  // writes to our fake file |fake_window_restore_file_|.
   void OnSaveWindow(const app_restore::WindowInfo& window_info) {
     aura::Window* window = window_info.window;
     DCHECK(window);
 
     const int32_t restore_window_id =
         window->GetProperty(app_restore::kRestoreWindowIdKey);
-    if (fake_full_restore_file_.contains(restore_window_id)) {
-      fake_full_restore_file_[restore_window_id].call_count++;
+    if (fake_window_restore_file_.contains(restore_window_id)) {
+      fake_window_restore_file_[restore_window_id].call_count++;
     } else {
-      fake_full_restore_file_[restore_window_id].info =
+      fake_window_restore_file_[restore_window_id].info =
           std::make_unique<app_restore::WindowInfo>();
     }
 
     CopyWindowInfo(window_info,
-                   fake_full_restore_file_[restore_window_id].info.get());
+                   fake_window_restore_file_[restore_window_id].info.get());
   }
 
-  // Callback function that is run when FullRestoreController tries to read
+  // Callback function that is run when WindowRestoreController tries to read
   // window data from the file. Immediately reads from our fake file
-  // `fake_full_restore_file_`.
+  // `fake_window_restore_file_`.
   std::unique_ptr<app_restore::WindowInfo> OnGetWindowInfo(
       aura::Window* window) {
     DCHECK(window);
     const int32_t restore_window_id =
         window->GetProperty(app_restore::kRestoreWindowIdKey);
-    if (!fake_full_restore_file_.contains(restore_window_id))
+    if (!fake_window_restore_file_.contains(restore_window_id))
       return nullptr;
 
     auto window_info = std::make_unique<app_restore::WindowInfo>();
-    CopyWindowInfo(*fake_full_restore_file_[restore_window_id].info,
+    CopyWindowInfo(*fake_window_restore_file_[restore_window_id].info,
                    window_info.get());
     return window_info;
   }
@@ -349,8 +350,8 @@
     out_dst->display_id = src.display_id;
   }
 
-  // A map which is a fake representation of the full restore file.
-  base::flat_map<int32_t, WindowInfo> fake_full_restore_file_;
+  // A map which is a fake representation of the window restore file.
+  base::flat_map<int32_t, WindowInfo> fake_window_restore_file_;
 
   base::ScopedObservation<aura::Env, aura::EnvObserver> env_observation_{this};
 
@@ -358,13 +359,13 @@
 };
 
 // Tests window save with setting on or off.
-TEST_F(FullRestoreControllerTest, WindowSaveDisabled) {
+TEST_F(WindowRestoreControllerTest, WindowSaveDisabled) {
   auto account_id = Shell::Get()->session_controller()->GetActiveAccountId();
   auto window1 = CreateAppWindow(gfx::Rect(600, 600), AppType::BROWSER);
   auto window2 = CreateAppWindow(gfx::Rect(600, 600), AppType::BROWSER);
   ResetSaveWindowsCount();
 
-  // Disable full restore.
+  // Disable window restore.
   full_restore::FullRestoreInfo::GetInstance()->SetRestorePref(account_id,
                                                                false);
 
@@ -378,7 +379,7 @@
   EXPECT_EQ(0, GetSaveWindowsCount(window1.get()));
   EXPECT_EQ(0, GetSaveWindowsCount(window2.get()));
 
-  // Enable full restore.
+  // Enable window restore.
   full_restore::FullRestoreInfo::GetInstance()->SetRestorePref(account_id,
                                                                true);
 
@@ -389,7 +390,7 @@
 }
 
 // Tests that data gets saved when changing a window's window state.
-TEST_F(FullRestoreControllerTest, WindowStateChanged) {
+TEST_F(WindowRestoreControllerTest, WindowStateChanged) {
   auto window = CreateAppWindow(gfx::Rect(600, 600), AppType::BROWSER);
   ResetSaveWindowsCount();
 
@@ -417,7 +418,7 @@
 }
 
 // Tests that data gets saved when moving a window to another desk.
-TEST_F(FullRestoreControllerTest, WindowMovedDesks) {
+TEST_F(WindowRestoreControllerTest, WindowMovedDesks) {
   auto* desks_controller = DesksController::Get();
   desks_controller->NewDesk(DesksCreationRemovalSource::kButton);
   ASSERT_EQ(0, desks_controller->GetDeskIndex(
@@ -437,7 +438,7 @@
 }
 
 // Tests that data gets saved when assigning a window to all desks.
-TEST_F(FullRestoreControllerTest, AssignToAllDesks) {
+TEST_F(WindowRestoreControllerTest, AssignToAllDesks) {
   auto* desks_controller = DesksController::Get();
   desks_controller->NewDesk(DesksCreationRemovalSource::kButton);
   ASSERT_EQ(0, desks_controller->GetDeskIndex(
@@ -459,7 +460,7 @@
 
 // Tests that data gets saved when moving a window to another display using the
 // accelerator.
-TEST_F(FullRestoreControllerTest, WindowMovedDisplay) {
+TEST_F(WindowRestoreControllerTest, WindowMovedDisplay) {
   UpdateDisplay("800x700,801+0-800x700");
 
   auto window = CreateAppWindow(gfx::Rect(50, 50, 100, 100), AppType::BROWSER);
@@ -474,7 +475,7 @@
 }
 
 // Tests that data gets saved when dragging a window.
-TEST_F(FullRestoreControllerTest, WindowDragged) {
+TEST_F(WindowRestoreControllerTest, WindowDragged) {
   auto window = CreateAppWindow(gfx::Rect(400, 400), AppType::BROWSER);
   ResetSaveWindowsCount();
 
@@ -490,7 +491,7 @@
   EXPECT_EQ(1, GetSaveWindowsCount(window.get()));
 }
 
-TEST_F(FullRestoreControllerTest, TabletModeChange) {
+TEST_F(WindowRestoreControllerTest, TabletModeChange) {
   // Tests that with no windows, nothing gets save when entering or exiting
   // tablet mode.
   TabletModeControllerTestApi().EnterTabletMode();
@@ -517,7 +518,7 @@
   EXPECT_GT(GetSaveWindowsCount(window2.get()), 1);
 }
 
-TEST_F(FullRestoreControllerTest, DisplayAddRemove) {
+TEST_F(WindowRestoreControllerTest, DisplayAddRemove) {
   UpdateDisplay("800x700,801+0-800x700");
 
   auto window = CreateAppWindow(gfx::Rect(800, 0, 400, 400), AppType::BROWSER);
@@ -544,7 +545,7 @@
   EXPECT_EQ(3, GetSaveWindowsCount(window.get()));
 }
 
-TEST_F(FullRestoreControllerTest, Activation) {
+TEST_F(WindowRestoreControllerTest, Activation) {
   auto window1 = CreateAppWindow(gfx::Rect(400, 400), AppType::BROWSER);
   auto window2 = CreateAppWindow(gfx::Rect(400, 400), AppType::BROWSER);
   auto window3 = CreateAppWindow(gfx::Rect(400, 400), AppType::BROWSER);
@@ -564,9 +565,9 @@
   EXPECT_EQ(0, GetActivationIndex(window3.get()));
 }
 
-// Tests that the mock widget created from full restore we will use in other
+// Tests that the mock widget created from window restore we will use in other
 // tests works as expected.
-TEST_F(FullRestoreControllerTest, TestFullRestoredWidget) {
+TEST_F(WindowRestoreControllerTest, TestFullRestoredWidget) {
   const int32_t kActivationIndex = 2;
   views::Widget* widget = CreateTestFullRestoredWidget(kActivationIndex);
   int32_t* activation_index =
@@ -586,7 +587,7 @@
 
 // Tests that widgets are restored to their proper stacking order, even if they
 // are restored out-of-order.
-TEST_F(FullRestoreControllerTest, Stacking) {
+TEST_F(WindowRestoreControllerTest, Stacking) {
   // Create a window that is a child of the active desk's container.
   auto* desk_container = desks_util::GetActiveDeskContainerForRoot(
       Shell::Get()->GetPrimaryRootWindow());
@@ -622,7 +623,7 @@
 
 // Tests that widgets are restored to their proper stacking order in a
 // multi-display scenario.
-TEST_F(FullRestoreControllerTest, StackingMultiDisplay) {
+TEST_F(WindowRestoreControllerTest, StackingMultiDisplay) {
   UpdateDisplay("800x700,801+0-800x700,1602+0-800x700");
 
   auto root_windows = Shell::GetAllRootWindows();
@@ -686,12 +687,12 @@
                       {window_3_3, window_3_2, window_3_1});
 }
 
-// Tests clamshell snapped window functionality when creating a window from full
-// restore.
-TEST_F(FullRestoreControllerTest, ClamshellSnapWindow) {
+// Tests clamshell snapped window functionality when creating a window from
+// window restore.
+TEST_F(WindowRestoreControllerTest, ClamshellSnapWindow) {
   UpdateDisplay("800x700");
 
-  // Add two entries to our fake full restore file, one snapped left and the
+  // Add two entries to our fake window restore file, one snapped left and the
   // other snapped right.
   const gfx::Rect restored_bounds(200, 200);
   AddEntryToFakeFile(/*restore_window_id=*/2, restored_bounds,
@@ -699,7 +700,7 @@
   AddEntryToFakeFile(/*restore_window_id=*/3, restored_bounds,
                      chromeos::WindowStateType::kSecondarySnapped);
 
-  // Create two full restore windows with the same restore window ids as the
+  // Create two window restore windows with the same restore window ids as the
   // entries we added. Test they are snapped and have snapped bounds.
   aura::Window* left_window =
       CreateTestFullRestoredWidgetFromRestoreId(/*restore_window_id=*/2)
@@ -728,9 +729,9 @@
   EXPECT_EQ(restored_bounds, right_window->GetBoundsInScreen());
 }
 
-// Tests full restore behavior when a display is disconnected before
+// Tests window restore behavior when a display is disconnected before
 // restoration.
-TEST_F(FullRestoreControllerTest, DisconnectedDisplay) {
+TEST_F(WindowRestoreControllerTest, DisconnectedDisplay) {
   UpdateDisplay("800x700");
   const gfx::Rect display_1_bounds(0, 0, 200, 200);
   const gfx::Rect display_2_bounds(801, 0, 200, 200);
@@ -800,7 +801,7 @@
 }
 
 // Tests that the splitview data in tablet is saved properly.
-TEST_F(FullRestoreControllerTest, TabletSplitviewWindow) {
+TEST_F(WindowRestoreControllerTest, TabletSplitviewWindow) {
   TabletModeControllerTestApi().EnterTabletMode();
 
   const gfx::Rect bounds(300, 300);
@@ -827,10 +828,10 @@
   EXPECT_EQ(bounds, *window2_info->current_bounds);
 }
 
-// Tests tablet snapped window functionality when creating a window from full
+// Tests tablet snapped window functionality when creating a window from window
 // restore.
-TEST_F(FullRestoreControllerTest, TabletSnapWindow) {
-  // Add two entries to our fake full restore file, one snapped left and the
+TEST_F(WindowRestoreControllerTest, TabletSnapWindow) {
+  // Add two entries to our fake window restore file, one snapped left and the
   // other snapped right.
   const gfx::Rect restored_bounds(200, 200);
   AddEntryToFakeFile(/*restore_window_id=*/2, restored_bounds,
@@ -840,7 +841,7 @@
 
   TabletModeControllerTestApi().EnterTabletMode();
 
-  // Create two full restore windows with the same restore window ids as the
+  // Create two window restore windows with the same restore window ids as the
   // entries we added. Test they are snapped and have snapped bounds.
   aura::Window* left_window =
       CreateTestFullRestoredWidgetFromRestoreId(/*restore_window_id=*/2)
@@ -873,8 +874,8 @@
   EXPECT_EQ(restored_bounds, right_window->GetBoundsInScreen());
 }
 
-// Tests full restore behavior when a display size changes.
-TEST_F(FullRestoreControllerTest, DisplaySizeChange) {
+// Tests window restore behavior when a display size changes.
+TEST_F(WindowRestoreControllerTest, DisplaySizeChange) {
   constexpr int kRestoreId = 1;
   UpdateDisplay("500x400");
 
@@ -895,9 +896,9 @@
   EXPECT_TRUE(WindowState::Get(restored_window)->IsNormalStateType());
 }
 
-// Tests full restore behavior for when a window saved in clamshell mode is
+// Tests window restore behavior for when a window saved in clamshell mode is
 // restored as expected in tablet mode.
-TEST_F(FullRestoreControllerTest, ClamshellToTablet) {
+TEST_F(WindowRestoreControllerTest, ClamshellToTablet) {
   constexpr int kRestoreId = 1;
 
   // Add a normal window to the fake file.
@@ -919,9 +920,9 @@
   EXPECT_EQ(clamshell_bounds, restored_window->GetBoundsInScreen());
 }
 
-// Tests full restore behavior for when a window saved in tablet mode is
+// Tests window restore behavior for when a window saved in tablet mode is
 // restored as expected in clamshell mode.
-TEST_F(FullRestoreControllerTest, TabletToClamshell) {
+TEST_F(WindowRestoreControllerTest, TabletToClamshell) {
   TabletModeControllerTestApi().EnterTabletMode();
 
   // The tablet mode window manager watches windows when they are added, then
@@ -958,7 +959,7 @@
 
   const int restore_id = window->GetProperty(app_restore::kRestoreWindowIdKey);
 
-  // Leave tablet mode, and then mock creating the window from full restore
+  // Leave tablet mode, and then mock creating the window from window restore
   // file. Test that the state and bounds are as expected in clamshell mode.
   TabletModeControllerTestApi().LeaveTabletMode();
   auto* restored_window =
@@ -969,7 +970,7 @@
 
 // Tests that when windows are restored in tablet mode the hotseat is hidden.
 // See crbug.com/1202923.
-TEST_F(FullRestoreControllerTest, HotseatIsHiddenOnRestoration) {
+TEST_F(WindowRestoreControllerTest, HotseatIsHiddenOnRestoration) {
   // Enter tablet mode and check that the hotseat is not hidden.
   TabletModeControllerTestApi().EnterTabletMode();
   HotseatWidget* hotseat_widget = GetPrimaryShelf()->hotseat_widget();
@@ -1004,7 +1005,7 @@
 
 // Tests that the app list isn't deactivated when all restored windows are
 // minimized.
-TEST_F(FullRestoreControllerTest,
+TEST_F(WindowRestoreControllerTest,
        AppListNotDeactivatedWhenAllWindowsMinimized) {
   // Enter tablet mode and ensure the app list is active.
   TabletModeControllerTestApi().EnterTabletMode();
@@ -1035,7 +1036,7 @@
 // Tests that the posted task for clearing a window's
 // `app_restore::kLaunchedFromFullRestoreKey` is cancelled when that window is
 // destroyed.
-TEST_F(FullRestoreControllerTest, RestorePropertyClearCallback) {
+TEST_F(WindowRestoreControllerTest, RestorePropertyClearCallback) {
   // Restore a window.
   AddEntryToFakeFile(/*restore_window_id=*/1, gfx::Rect(200, 200),
                      chromeos::WindowStateType::kNormal);
@@ -1051,9 +1052,9 @@
   EXPECT_EQ(0u, GetRestorePropertyClearCallbacks().size());
 }
 
-// Tests full restore behavior for when a ARC window is created without an
+// Tests window restore behavior for when a ARC window is created without an
 // associated task.
-TEST_F(FullRestoreControllerTest, ArcAppWindowCreatedWithoutTask) {
+TEST_F(WindowRestoreControllerTest, ArcAppWindowCreatedWithoutTask) {
   constexpr int kRestoreId = 1;
 
   // Create enough desks so that we can parent to the expected desk.
@@ -1079,7 +1080,7 @@
 
   // Simulate having the task ready. Our `restored_window` should now be
   // parented to the desk associated with desk 3, which is desk D.
-  FullRestoreController::Get()->OnARCTaskReadyForUnparentedWindow(
+  WindowRestoreController::Get()->OnARCTaskReadyForUnparentedWindow(
       restored_window);
   EXPECT_EQ(Shell::GetContainer(root_window, kShellWindowId_DeskContainerD),
             restored_window->parent());
@@ -1087,7 +1088,8 @@
 
 // Tests that parenting ARC windows to hidden container works in the multi
 // display scenario, including if a display gets disconnected partway through.
-TEST_F(FullRestoreControllerTest, ArcAppWindowCreatedWithoutTaskMultiDisplay) {
+TEST_F(WindowRestoreControllerTest,
+       ArcAppWindowCreatedWithoutTaskMultiDisplay) {
   UpdateDisplay("800x700,801+0-800x700");
 
   const int64_t primary_id = WindowTreeHostManager::GetPrimaryDisplayId();
@@ -1123,7 +1125,7 @@
   EXPECT_EQ(Shell::GetContainer(secondary_root_window,
                                 kShellWindowId_UnparentedContainer),
             restored_window1->parent());
-  FullRestoreController::Get()->OnARCTaskReadyForUnparentedWindow(
+  WindowRestoreController::Get()->OnARCTaskReadyForUnparentedWindow(
       restored_window1);
   EXPECT_EQ(
       Shell::GetContainer(secondary_root_window, kShellWindowId_DeskContainerD),
@@ -1145,7 +1147,7 @@
   display_info_list.push_back(primary_info);
   display_manager()->OnNativeDisplaysChanged(display_info_list);
 
-  FullRestoreController::Get()->OnARCTaskReadyForUnparentedWindow(
+  WindowRestoreController::Get()->OnARCTaskReadyForUnparentedWindow(
       restored_window2);
   EXPECT_EQ(
       Shell::GetContainer(primary_root_window, kShellWindowId_DeskContainerD),
@@ -1154,7 +1156,7 @@
 
 // Tests that windows that are out-of-bounds of the display they're being
 // restored to are properly restored.
-TEST_F(FullRestoreControllerTest, OutOfBoundsWindows) {
+TEST_F(WindowRestoreControllerTest, OutOfBoundsWindows) {
   UpdateDisplay("800x700");
   const gfx::Rect kScreenBounds(0, 0, 800, 800);
   const gfx::Rect kPartialBounds(-100, 100, 200, 200);
@@ -1202,7 +1204,7 @@
 
 // Tests that when the topmost window is a Full Restore'd window, it is
 // activatable. See crbug.com/1229928.
-TEST_F(FullRestoreControllerTest, TopmostWindowIsActivatable) {
+TEST_F(WindowRestoreControllerTest, TopmostWindowIsActivatable) {
   // Create a window that is not restored and activate it.
   auto* desk_container = desks_util::GetActiveDeskContainerForRoot(
       Shell::Get()->GetPrimaryRootWindow());
@@ -1246,7 +1248,7 @@
 
 // Tests that when the topmost window is minimized, the next highest unminimized
 // window is activated.
-TEST_F(FullRestoreControllerTest, NextTopmostWindowIsActivatable) {
+TEST_F(WindowRestoreControllerTest, NextTopmostWindowIsActivatable) {
   auto* desk_container = desks_util::GetActiveDeskContainerForRoot(
       Shell::Get()->GetPrimaryRootWindow());
 
@@ -1298,7 +1300,7 @@
 
 // Tests that when a window is restored to an inactive desk it is not
 // activatable. See crbug.com/1237158.
-TEST_F(FullRestoreControllerTest, WindowsOnInactiveDeskAreNotActivatable) {
+TEST_F(WindowRestoreControllerTest, WindowsOnInactiveDeskAreNotActivatable) {
   // Create two desks and switch to the first desk. There should now be three in
   // total.
   auto* desks_controller = DesksController::Get();
diff --git a/ash/wm/full_restore/full_restore_util.cc b/ash/wm/window_restore/window_restore_util.cc
similarity index 95%
rename from ash/wm/full_restore/full_restore_util.cc
rename to ash/wm/window_restore/window_restore_util.cc
index 3d46dc6..3dc289c 100644
--- a/ash/wm/full_restore/full_restore_util.cc
+++ b/ash/wm/window_restore/window_restore_util.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ash/wm/full_restore/full_restore_util.h"
+#include "ash/wm/window_restore/window_restore_util.h"
 
 #include "ash/public/cpp/app_types_util.h"
 #include "ash/public/cpp/window_properties.h"
@@ -55,7 +55,7 @@
     window_info->current_bounds = window_state->HasRestoreBounds()
                                       ? window_state->GetRestoreBoundsInScreen()
                                       : window->GetBoundsInScreen();
-    // Full restore does not support restoring fullscreen windows. If a window
+    // Window restore does not support restoring fullscreen windows. If a window
     // is fullscreen save the pre-fullscreen window state instead.
     window_info->window_state_type =
         window_state->IsFullscreen()
diff --git a/ash/wm/full_restore/full_restore_util.h b/ash/wm/window_restore/window_restore_util.h
similarity index 80%
rename from ash/wm/full_restore/full_restore_util.h
rename to ash/wm/window_restore/window_restore_util.h
index 7dda3ec..af39207 100644
--- a/ash/wm/full_restore/full_restore_util.h
+++ b/ash/wm/window_restore/window_restore_util.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef ASH_WM_FULL_RESTORE_FULL_RESTORE_UTIL_H_
-#define ASH_WM_FULL_RESTORE_FULL_RESTORE_UTIL_H_
+#ifndef ASH_WM_WINDOW_RESTORE_WINDOW_RESTORE_UTIL_H_
+#define ASH_WM_WINDOW_RESTORE_WINDOW_RESTORE_UTIL_H_
 
 #include "components/app_restore/window_info.h"
 
@@ -24,4 +24,4 @@
 
 }  // namespace ash
 
-#endif  // ASH_WM_FULL_RESTORE_FULL_RESTORE_UTIL_H_
+#endif  // ASH_WM_WINDOW_RESTORE_WINDOW_RESTORE_UTIL_H_
diff --git a/ash/wm/window_state.cc b/ash/wm/window_state.cc
index 4a30c99..4276247 100644
--- a/ash/wm/window_state.cc
+++ b/ash/wm/window_state.cc
@@ -20,12 +20,12 @@
 #include "ash/wm/collision_detection/collision_detection_utils.h"
 #include "ash/wm/default_state.h"
 #include "ash/wm/desks/persistent_desks_bar_controller.h"
-#include "ash/wm/full_restore/full_restore_controller.h"
 #include "ash/wm/pip/pip_positioner.h"
 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "ash/wm/window_animations.h"
 #include "ash/wm/window_positioning_utils.h"
 #include "ash/wm/window_properties.h"
+#include "ash/wm/window_restore/window_restore_controller.h"
 #include "ash/wm/window_state_delegate.h"
 #include "ash/wm/window_state_observer.h"
 #include "ash/wm/window_util.h"
@@ -199,12 +199,12 @@
                              base::TimeDelta::FromHours(10), 50);
 }
 
-// Notifies the full restore controller to write to file.
-void SaveWindowForFullRestore(WindowState* window_state) {
+// Notifies the window restore controller to write to file.
+void SaveWindowForWindowRestore(WindowState* window_state) {
   if (!full_restore::features::IsFullRestoreEnabled())
     return;
 
-  auto* controller = FullRestoreController::Get();
+  auto* controller = WindowRestoreController::Get();
   if (controller)
     controller->SaveWindow(window_state);
 }
@@ -605,7 +605,7 @@
   DCHECK(drag_details_);
   if (delegate_)
     delegate_->OnDragFinished(/*canceled=*/false, location);
-  SaveWindowForFullRestore(this);
+  SaveWindowForWindowRestore(this);
 }
 
 void WindowState::OnRevertDrag(const gfx::PointF& location) {
@@ -774,7 +774,7 @@
   for (auto& observer : observer_list_)
     observer.OnPostWindowStateTypeChange(this, old_window_state_type);
   OnPostPipStateChange(old_window_state_type);
-  SaveWindowForFullRestore(this);
+  SaveWindowForWindowRestore(this);
 }
 
 void WindowState::OnPostPipStateChange(WindowStateType old_window_state_type) {
@@ -964,8 +964,8 @@
   DCHECK(window->parent());
 
   // WindowState is only for windows in top level container, unless they are
-  // temporarily hidden when launched by full restore. The will be reparented to
-  // a top level container soon, and need a WindowState.
+  // temporarily hidden when launched by window restore. The will be reparented
+  // to a top level container soon, and need a WindowState.
   if (!IsToplevelContainer(window->parent()) &&
       !IsTemporarilyHiddenForFullrestore(window)) {
     return nullptr;
@@ -1023,13 +1023,13 @@
     return;
   }
   if (key == aura::client::kWindowWorkspaceKey) {
-    // Save the window for full restore purposes unless
+    // Save the window for window restore purposes unless
     // |ignore_property_change_| is true. Note that moving windows across
     // displays will also trigger a kWindowWorkspaceKey change, even if the
     // value stays the same, so we do not need to save the window when it
     // changes root windows (OnWindowAddedToRootWindow).
     if (!ignore_property_change_)
-      SaveWindowForFullRestore(this);
+      SaveWindowForWindowRestore(this);
     return;
   }
 
@@ -1087,7 +1087,7 @@
   }
 
   if (reason != ui::PropertyChangeReason::FROM_ANIMATION && !is_dragged())
-    SaveWindowForFullRestore(this);
+    SaveWindowForWindowRestore(this);
 }
 
 }  // namespace ash
diff --git a/ash/wm/workspace/multi_window_resize_controller.cc b/ash/wm/workspace/multi_window_resize_controller.cc
index 3f2b2b46..71f243bf 100644
--- a/ash/wm/workspace/multi_window_resize_controller.cc
+++ b/ash/wm/workspace/multi_window_resize_controller.cc
@@ -115,6 +115,9 @@
   ResizeView(MultiWindowResizeController* controller, Direction direction)
       : controller_(controller), direction_(direction) {}
 
+  ResizeView(const ResizeView&) = delete;
+  ResizeView& operator=(const ResizeView&) = delete;
+
   // views::View overrides:
   gfx::Size CalculatePreferredSize() const override {
     const bool vert = direction_ == Direction::kLeftRight;
@@ -185,8 +188,6 @@
 
   MultiWindowResizeController* controller_;
   const Direction direction_;
-
-  DISALLOW_COPY_AND_ASSIGN(ResizeView);
 };
 
 // MouseWatcherHost implementation for MultiWindowResizeController. Forwards
@@ -196,6 +197,9 @@
  public:
   ResizeMouseWatcherHost(MultiWindowResizeController* host) : host_(host) {}
 
+  ResizeMouseWatcherHost(const ResizeMouseWatcherHost&) = delete;
+  ResizeMouseWatcherHost& operator=(const ResizeMouseWatcherHost&) = delete;
+
   // MouseWatcherHost overrides:
   bool Contains(const gfx::Point& point_in_screen, EventType type) override {
     return (type == EventType::kPress)
@@ -205,8 +209,6 @@
 
  private:
   MultiWindowResizeController* host_;
-
-  DISALLOW_COPY_AND_ASSIGN(ResizeMouseWatcherHost);
 };
 
 MultiWindowResizeController::ResizeWindows::ResizeWindows()
diff --git a/ash/wm/workspace/workspace_layout_manager_unittest.cc b/ash/wm/workspace/workspace_layout_manager_unittest.cc
index 808beef..97a352c 100644
--- a/ash/wm/workspace/workspace_layout_manager_unittest.cc
+++ b/ash/wm/workspace/workspace_layout_manager_unittest.cc
@@ -360,6 +360,11 @@
  public:
   DontClobberRestoreBoundsWindowObserver() : window_(nullptr) {}
 
+  DontClobberRestoreBoundsWindowObserver(
+      const DontClobberRestoreBoundsWindowObserver&) = delete;
+  DontClobberRestoreBoundsWindowObserver& operator=(
+      const DontClobberRestoreBoundsWindowObserver&) = delete;
+
   void set_window(aura::Window* window) { window_ = window; }
 
   // aura::WindowObserver:
@@ -382,8 +387,6 @@
 
  private:
   aura::Window* window_;
-
-  DISALLOW_COPY_AND_ASSIGN(DontClobberRestoreBoundsWindowObserver);
 };
 
 // Creates a window, maximized the window and from within the maximized
diff --git a/ash/wm/workspace_controller_unittest.cc b/ash/wm/workspace_controller_unittest.cc
index a9d24fc..659a8b5 100644
--- a/ash/wm/workspace_controller_unittest.cc
+++ b/ash/wm/workspace_controller_unittest.cc
@@ -586,6 +586,11 @@
  public:
   DontCrashOnChangeAndActivateDelegate() : window_(NULL) {}
 
+  DontCrashOnChangeAndActivateDelegate(
+      const DontCrashOnChangeAndActivateDelegate&) = delete;
+  DontCrashOnChangeAndActivateDelegate& operator=(
+      const DontCrashOnChangeAndActivateDelegate&) = delete;
+
   void set_window(aura::Window* window) { window_ = window; }
 
   // WindowDelegate overrides:
@@ -599,8 +604,6 @@
 
  private:
   aura::Window* window_;
-
-  DISALLOW_COPY_AND_ASSIGN(DontCrashOnChangeAndActivateDelegate);
 };
 
 }  // namespace
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 6a8bd09..7dd2bbf 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -1605,6 +1605,8 @@
     }
     if (current_cpu == "arm") {
       sources += [
+        "profiler/chrome_unwind_info_android.cc",
+        "profiler/chrome_unwind_info_android.h",
         "profiler/chrome_unwind_table_android.cc",
         "profiler/chrome_unwind_table_android.h",
         "profiler/chrome_unwinder_android.cc",
@@ -1735,7 +1737,7 @@
       "//third_party/fuchsia-sdk/sdk/pkg/fidl_cpp",
       "//third_party/fuchsia-sdk/sdk/pkg/sync",
       "//third_party/fuchsia-sdk/sdk/pkg/sys_cpp",
-      "//third_party/fuchsia-sdk/sdk/pkg/syslog",
+      "//third_party/fuchsia-sdk/sdk/pkg/syslog_structured_backend",
       "//third_party/fuchsia-sdk/sdk/pkg/vfs_cpp",
       "//third_party/fuchsia-sdk/sdk/pkg/zx",
     ]
@@ -1748,7 +1750,6 @@
       "//third_party/fuchsia-sdk/sdk/pkg/async-loop-default",
       "//third_party/fuchsia-sdk/sdk/pkg/fidl",
       "//third_party/fuchsia-sdk/sdk/pkg/sys_inspect_cpp",
-      "//third_party/fuchsia-sdk/sdk/pkg/syslog",
       "//third_party/icu",
     ]
 
@@ -3414,6 +3415,7 @@
     }
     if (current_cpu == "arm") {
       sources += [
+        "profiler/chrome_unwind_info_android_unittest.cc",
         "profiler/chrome_unwind_table_android_unittest.cc",
         "profiler/chrome_unwinder_android_unittest.cc",
       ]
diff --git a/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java b/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
index ee15e553..b9175f8 100644
--- a/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
+++ b/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
@@ -71,10 +71,6 @@
     private static final String REACHED_CODE_SAMPLING_INTERVAL_KEY =
             "reached_code_sampling_interval";
 
-    // Compile time switch for sharing RELRO between the browser and the app zygote.
-    // TODO(crbug.com/1154224): remove when the issue is closed.
-    private static final boolean ALLOW_CHROMIUM_LINKER_IN_ZYGOTE = false;
-
     // Default sampling interval for reached code profiler in microseconds.
     private static final int DEFAULT_REACHED_CODE_SAMPLING_INTERVAL_US = 10000;
 
@@ -159,12 +155,6 @@
         int CHILD_WITHOUT_ZYGOTE = 2;
     }
 
-    // Returns true when sharing RELRO between the browser process and the app zygote should *not*
-    // be attempted.
-    public static boolean mainProcessIntendsToProvideRelroFd() {
-        return !ALLOW_CHROMIUM_LINKER_IN_ZYGOTE || Build.VERSION.SDK_INT <= Build.VERSION_CODES.R;
-    }
-
     /**
      * Inner class encapsulating points of communication between instances of LibraryLoader in
      * different processes.
diff --git a/base/fuchsia/scoped_fx_logger.cc b/base/fuchsia/scoped_fx_logger.cc
index 8ec60393..67ec812 100644
--- a/base/fuchsia/scoped_fx_logger.cc
+++ b/base/fuchsia/scoped_fx_logger.cc
@@ -4,39 +4,88 @@
 
 #include "base/fuchsia/scoped_fx_logger.h"
 
+#include <lib/fdio/directory.h>
+
 #include "base/fuchsia/fuchsia_logging.h"
+#include "base/process/process.h"
 #include "base/strings/string_piece.h"
+#include "base/threading/platform_thread.h"
 
 namespace base {
 
-ScopedFxLogger CreateFxLoggerFromLogSink(
-    fuchsia::logger::LogSinkHandle log_sink) {
-  return CreateFxLoggerFromLogSinkWithTag(std::move(log_sink), {});
-}
+ScopedFxLogger::ScopedFxLogger() = default;
+ScopedFxLogger::~ScopedFxLogger() = default;
 
-ScopedFxLogger CreateFxLoggerFromLogSinkWithTag(
-    fuchsia::logger::LogSinkHandle log_sink,
-    base::StringPiece tag) {
-  std::string tag_string(tag);
-  const char* tag_c_string = tag_string.c_str();
+// static
+ScopedFxLogger ScopedFxLogger::CreateForProcessWithTag(base::StringPiece tag) {
+  // CHECK()ing or LOG()ing inside this function is safe, since it is only
+  // called to initialize logging, not during individual logging operations.
 
-  fx_logger_config_t config = {
-      // Selecting based on log level is handled outside the fx_logger.
-      .min_severity = FX_LOG_ALL,
-      .console_fd = -1,
-      .log_sink_channel = log_sink.TakeChannel().release(),
-      .tags = tag.empty() ? nullptr : &tag_c_string,
-      .num_tags = tag.empty() ? 0u : 1u,
-  };
-
-  fx_logger_t* fx_logger = nullptr;
-  zx_status_t status = fx_logger_create(&config, &fx_logger);
+  fuchsia::logger::LogSinkHandle log_sink;
+  zx_status_t status =
+      fdio_service_connect("/svc/fuchsia.logger.LogSink",
+                           log_sink.NewRequest().TakeChannel().release());
   if (status != ZX_OK) {
-    ZX_LOG(ERROR, status) << "fx_logger_create";
-    return nullptr;
+    ZX_LOG(ERROR, status) << "connect(LogSink) failed";
+    return {};
   }
 
-  return ScopedFxLogger(fx_logger);
+  return CreateFromLogSinkWithTag(std::move(log_sink), tag);
 }
 
+// static
+ScopedFxLogger ScopedFxLogger::CreateFromLogSink(
+    fuchsia::logger::LogSinkHandle log_sink_handle) {
+  return CreateFromLogSinkWithTag(std::move(log_sink_handle), {});
+}
+
+// static
+ScopedFxLogger ScopedFxLogger::CreateFromLogSinkWithTag(
+    fuchsia::logger::LogSinkHandle log_sink_handle,
+    base::StringPiece tag) {
+  // CHECK()ing or LOG()ing inside this function is safe, since it is only
+  // called to initialize logging, not during individual logging operations.
+
+  // Attempts to create a kernel socket object should never fail.
+  zx::socket local, remote;
+  zx_status_t status = zx::socket::create(ZX_SOCKET_DATAGRAM, &local, &remote);
+  ZX_CHECK(status == ZX_OK, status) << "zx_socket_create() failed";
+
+  // ConnectStructured() may fail if e.g. the LogSink has disconnected already.
+  fuchsia::logger::LogSinkSyncPtr log_sink;
+  log_sink.Bind(std::move(log_sink_handle));
+  status = log_sink->ConnectStructured(std::move(remote));
+  if (status != ZX_OK) {
+    ZX_LOG(ERROR, status) << "ConnectStructured() failed";
+    return {};
+  }
+
+  return ScopedFxLogger(tag, std::move(local));
+}
+
+void ScopedFxLogger::LogMessage(base::StringPiece file,
+                                uint32_t line_number,
+                                base::StringPiece msg,
+                                FuchsiaLogSeverity severity) {
+  if (!socket_.is_valid())
+    return;
+
+  // It is not safe to use e.g. CHECK() or LOG() macros here, since those
+  // may result in reentrancy if this instance is used for routing process-
+  // global logs to the system logger.
+
+  fuchsia_syslog::LogBuffer buffer;
+  buffer.BeginRecord(
+      severity, cpp17::string_view(file.data(), file.size()), line_number,
+      cpp17::string_view(msg.data(), msg.size()), {}, false, socket_.borrow(),
+      0, base::Process::Current().Pid(), base::PlatformThread::CurrentId());
+  if (!tag_.empty()) {
+    buffer.WriteKeyValue("tag", tag_);
+  }
+  buffer.FlushRecord();
+}
+
+ScopedFxLogger::ScopedFxLogger(base::StringPiece tag, zx::socket socket)
+    : tag_(tag), socket_(std::move(socket)) {}
+
 }  // namespace base
diff --git a/base/fuchsia/scoped_fx_logger.h b/base/fuchsia/scoped_fx_logger.h
index 81cc631..bc42c26 100644
--- a/base/fuchsia/scoped_fx_logger.h
+++ b/base/fuchsia/scoped_fx_logger.h
@@ -6,37 +6,51 @@
 #define BASE_FUCHSIA_SCOPED_FX_LOGGER_H_
 
 #include <fuchsia/logger/cpp/fidl.h>
-#include <lib/syslog/logger.h>
+#include <lib/syslog/structured_backend/cpp/fuchsia_syslog.h>
+#include <lib/zx/socket.h>
 
-#include <memory>
+#include <stdint.h>
+#include <string>
 
 #include "base/base_export.h"
 #include "base/strings/string_piece_forward.h"
 
 namespace base {
 
-namespace internal {
+// Emits log lines to a logger created via the specified LogSink.
+// This class is thread-safe.
+class BASE_EXPORT ScopedFxLogger {
+ public:
+  ScopedFxLogger();
+  ~ScopedFxLogger();
 
-struct FxLoggerDeleter {
-  inline void operator()(fx_logger_t* ptr) const { fx_logger_destroy(ptr); }
+  ScopedFxLogger(ScopedFxLogger&& other) = default;
+  ScopedFxLogger& operator=(ScopedFxLogger&& other) = default;
+
+  static ScopedFxLogger CreateForProcessWithTag(base::StringPiece tag);
+
+  static ScopedFxLogger CreateFromLogSink(
+      fuchsia::logger::LogSinkHandle log_sink);
+
+  static ScopedFxLogger CreateFromLogSinkWithTag(fuchsia::logger::LogSinkHandle,
+                                                 base::StringPiece tag);
+
+  void LogMessage(base::StringPiece file,
+                  uint32_t line_number,
+                  base::StringPiece msg,
+                  FuchsiaLogSeverity severity);
+
+  bool is_valid() const { return socket_.is_valid(); }
+
+ private:
+  ScopedFxLogger(base::StringPiece tag, zx::socket socket);
+
+  // For thread-safety these members should be treated as read-only.
+  // They are non-const only to allow move-assignment of ScopedFxLogger.
+  std::string tag_;
+  zx::socket socket_;
 };
 
-}  // namespace internal
-
-using ScopedFxLogger = std::unique_ptr<fx_logger_t, internal::FxLoggerDeleter>;
-
-// Returns a new logger connected to the specified |log_sink| service.
-// The logger is initially configured to log all severities of message.
-// Returns null if creation of the new logger fails.
-BASE_EXPORT ScopedFxLogger
-CreateFxLoggerFromLogSink(::fuchsia::logger::LogSinkHandle log_sink);
-
-// Similar to CreateFxLoggerFromLogSink(), but returns a logger which annotates
-// messages with the specified |tag|, if non-empty.
-BASE_EXPORT ScopedFxLogger
-CreateFxLoggerFromLogSinkWithTag(::fuchsia::logger::LogSinkHandle log_sink,
-                                 base::StringPiece tag);
-
 }  // namespace base
 
 #endif  // BASE_FUCHSIA_SCOPED_FX_LOGGER_H_
diff --git a/base/logging.cc b/base/logging.cc
index 8ddd8ab..faeb60f 100644
--- a/base/logging.cc
+++ b/base/logging.cc
@@ -71,10 +71,7 @@
 #endif
 
 #if defined(OS_FUCHSIA)
-#include <lib/syslog/global.h>
-#include <lib/syslog/logger.h>
-#include <zircon/process.h>
-#include <zircon/syscalls.h>
+#include "base/fuchsia/scoped_fx_logger.h"
 #endif
 
 #if defined(OS_ANDROID)
@@ -165,6 +162,14 @@
 LogFormat g_log_format = LogFormat::LOG_FORMAT_SYSLOG;
 #endif
 
+#if defined(OS_FUCHSIA)
+// Retains system logging structures.
+base::ScopedFxLogger& GetScopedFxLogger() {
+  static base::NoDestructor<base::ScopedFxLogger> logger;
+  return *logger;
+}
+#endif
+
 // For LOGGING_ERROR and above, always print to stderr.
 const int kAlwaysPrintErrorLevel = LOGGING_ERROR;
 
@@ -348,27 +353,26 @@
 }
 
 #if defined(OS_FUCHSIA)
-
-inline fx_log_severity_t LogSeverityToFuchsiaLogSeverity(LogSeverity severity) {
+inline FuchsiaLogSeverity LogSeverityToFuchsiaLogSeverity(
+    LogSeverity severity) {
   switch (severity) {
     case LOGGING_INFO:
-      return FX_LOG_INFO;
+      return FUCHSIA_LOG_INFO;
     case LOGGING_WARNING:
-      return FX_LOG_WARNING;
+      return FUCHSIA_LOG_WARNING;
     case LOGGING_ERROR:
-      return FX_LOG_ERROR;
+      return FUCHSIA_LOG_ERROR;
     case LOGGING_FATAL:
       // Don't use FX_LOG_FATAL, otherwise fx_logger_log() will abort().
-      return FX_LOG_ERROR;
+      return FUCHSIA_LOG_ERROR;
   }
   if (severity > -3) {
     // LOGGING_VERBOSE levels 1 and 2.
-    return FX_LOG_DEBUG;
+    return FUCHSIA_LOG_DEBUG;
   }
   // LOGGING_VERBOSE levels 3 and higher, or incorrect levels.
-  return FX_LOG_TRACE;
+  return FUCHSIA_LOG_TRACE;
 }
-
 #endif  // defined (OS_FUCHSIA)
 
 }  // namespace
@@ -419,19 +423,7 @@
 
 #if defined(OS_FUCHSIA)
   if (g_logging_destination & LOG_TO_SYSTEM_DEBUG_LOG) {
-    std::string log_tag = base::CommandLine::ForCurrentProcess()
-                              ->GetProgram()
-                              .BaseName()
-                              .AsUTF8Unsafe();
-    const char* log_tag_data = log_tag.data();
-
-    fx_logger_config_t config = {
-        .min_severity = g_vlog_info ? FX_LOG_TRACE : FX_LOG_INFO,
-        .console_fd = -1,
-        .tags = &log_tag_data,
-        .num_tags = 1,
-    };
-    fx_log_reconfigure(&config);
+    GetScopedFxLogger() = base::ScopedFxLogger::CreateForProcessWithTag({});
   }
 #endif
 
@@ -806,16 +798,10 @@
     __android_log_write(priority, kAndroidLogTag, str_newline.c_str());
 #endif
 #elif defined(OS_FUCHSIA)
-    fx_logger_t* logger = fx_log_get_logger();
-    if (logger) {
-      // Temporarily remove the trailing newline from |str_newline|'s C-string
-      // representation, since fx_logger will add a newline of its own.
-      str_newline.pop_back();
-      fx_logger_log_with_source(
-          logger, LogSeverityToFuchsiaLogSeverity(severity_), nullptr, file_,
-          line_, str_newline.c_str() + message_start_);
-      str_newline.push_back('\n');
-    }
+    // LogMessage() will silently drop the message if the logger is not valid.
+    GetScopedFxLogger().LogMessage(
+        file_, line_, base::StringPiece(str_newline).substr(message_start_),
+        LogSeverityToFuchsiaLogSeverity(severity_));
 #endif  // OS_FUCHSIA
   }
 
diff --git a/base/logging_unittest.cc b/base/logging_unittest.cc
index 79df6c0a..b606ffd 100644
--- a/base/logging_unittest.cc
+++ b/base/logging_unittest.cc
@@ -745,10 +745,10 @@
   EXPECT_EQ(logged_message->severity,
             static_cast<int32_t>(fuchsia::logger::LogLevelFilter::ERROR));
   ASSERT_EQ(logged_message->tags.size(), 1u);
-  EXPECT_EQ(logged_message->tags[0], base::CommandLine::ForCurrentProcess()
-                                         ->GetProgram()
-                                         .BaseName()
-                                         .AsUTF8Unsafe());
+
+  // If no tags are explicitly set then the LogSink will add one based on the
+  // component name.
+  EXPECT_EQ(logged_message->tags[0], "base_unittests.cmx");
 }
 
 TEST_F(LoggingTest, FuchsiaLogging) {
diff --git a/base/profiler/chrome_unwind_info_android.cc b/base/profiler/chrome_unwind_info_android.cc
new file mode 100644
index 0000000..b5d5d20
--- /dev/null
+++ b/base/profiler/chrome_unwind_info_android.cc
@@ -0,0 +1,59 @@
+// 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 "base/profiler/chrome_unwind_info_android.h"
+
+#include "base/containers/buffer_iterator.h"
+
+namespace base {
+
+ChromeUnwindInfoAndroid::ChromeUnwindInfoAndroid(
+    span<const uint8_t> unwind_instruction_table,
+    span<const uint8_t> function_offset_table,
+    span<const FunctionTableEntry> function_table,
+    span<const uint32_t> page_table)
+    : unwind_instruction_table(unwind_instruction_table),
+      function_offset_table(function_offset_table),
+      function_table(function_table),
+      page_table(page_table) {}
+
+ChromeUnwindInfoAndroid::~ChromeUnwindInfoAndroid() = default;
+ChromeUnwindInfoAndroid::ChromeUnwindInfoAndroid(
+    ChromeUnwindInfoAndroid&& other) = default;
+ChromeUnwindInfoAndroid& ChromeUnwindInfoAndroid::operator=(
+    ChromeUnwindInfoAndroid&& other) = default;
+
+ChromeUnwindInfoAndroid CreateChromeUnwindInfoAndroid(
+    span<const uint8_t> data) {
+  BufferIterator<const uint8_t> data_iterator(data);
+
+  const auto* header = data_iterator.Object<ChromeUnwindInfoHeaderAndroid>();
+  DCHECK(header);
+
+  data_iterator.Seek(header->page_table_byte_offset);
+  const auto page_table =
+      data_iterator.Span<uint32_t>(header->page_table_entries);
+  DCHECK(!page_table.empty());
+
+  data_iterator.Seek(header->function_offset_table_byte_offset);
+  const auto function_offset_table =
+      data_iterator.Span<uint8_t>(header->function_offset_table_size_in_bytes);
+  DCHECK(!function_offset_table.empty());
+
+  data_iterator.Seek(header->function_table_byte_offset);
+  const auto function_table =
+      data_iterator.Span<FunctionTableEntry>(header->function_table_entries);
+  DCHECK(!function_table.empty());
+
+  data_iterator.Seek(header->unwind_instruction_table_byte_offset);
+  const auto unwind_instruction_table = data_iterator.Span<uint8_t>(
+      header->unwind_instruction_table_size_in_bytes);
+  DCHECK(!unwind_instruction_table.empty());
+
+  return ChromeUnwindInfoAndroid{unwind_instruction_table,
+                                 function_offset_table, function_table,
+                                 page_table};
+}
+
+}  // namespace base
\ No newline at end of file
diff --git a/base/profiler/chrome_unwind_info_android.h b/base/profiler/chrome_unwind_info_android.h
new file mode 100644
index 0000000..6586ef2
--- /dev/null
+++ b/base/profiler/chrome_unwind_info_android.h
@@ -0,0 +1,222 @@
+// 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.
+
+#ifndef BASE_PROFILER_CHROME_UNWIND_INFO_ANDROID_H_
+#define BASE_PROFILER_CHROME_UNWIND_INFO_ANDROID_H_
+
+#include <stdint.h>
+
+#include "base/base_export.h"
+#include "base/containers/span.h"
+
+namespace base {
+
+// Represents each entry in the function table (i.e. the second level of the
+// function address table).
+struct FunctionTableEntry {
+  // The offset into the 128kb page containing this function. Indexed by bits
+  // 1-16 of the pc offset from the start of the text section.
+  uint16_t function_start_address_page_instruction_offset;
+
+  // The byte index of the first offset for the function in the function
+  // offset table.
+  uint16_t function_offset_table_byte_index;
+};
+
+// The header at the start of the unwind info resource, with offsets/sizes for
+// the tables contained within the resource.
+//
+// The unwind info provides 4 tables which can translate an instruction address
+// to a set of unwind instructions to unwind the function frame the instruction
+// belongs to.
+//
+// `page_table` and `function_table` together locates which function the
+// instruction address belongs to given an instruction address.
+//
+// `function_offset_table` and `unwind_instruction_table` together locates
+// which sets of unwind instructions to execute given the function info
+// obtained from `page_table` and `function_table`, and the offset between the
+// instruction address and function start address.
+//
+// Design Doc:
+// https://docs.google.com/document/d/1IYTmGCJZoiQ242xPUZX1fATD6ivsjU1TAt_fPv74ocs/edit?usp=sharing
+struct BASE_EXPORT ChromeUnwindInfoHeaderAndroid {
+  // The offset in bytes from the start of the unwind info resource to the
+  // page table (i.e. the first level of the function address table). The page
+  // table represents discrete 128kb 'pages' of memory in the text section,
+  // each of which contains functions. The page table is indexed by bits 17
+  // and greater of the pc offset from the start of the text section.
+  // Indexing into page_table produces an index of function_table.
+  uint32_t page_table_byte_offset;
+  uint32_t page_table_entries;
+
+  // The offset in bytes from the start of the unwind info resource to the
+  // function table (i.e. the second level of the function address table). The
+  // function table represents the individual functions within a 128kb page.
+  // Each function is represented as a `FunctionTableEntry`. The relevant entry
+  // for a pc offset from the start of the text section is the one with the
+  // largest function_start_address_page_instruction_offset <= (pc_offset >> 1)
+  // & 0xffff.
+  uint32_t function_table_byte_offset;
+  uint32_t function_table_entries;
+
+  // The offset in bytes from the start of the unwind info resource to the
+  // function offset table. The function offset table represents the pc
+  // offsets from the start of each function along with indices into the
+  // unwind instructions for the offsets. The pc offsets and unwind indices
+  // are represented as (ULEB128, ULEB128) pairs in decreasing order of
+  // offset. Distinct sequences of (offset, index) pairs are concatenated in
+  // the table.
+  uint32_t function_offset_table_byte_offset;
+  uint32_t function_offset_table_size_in_bytes;
+
+  // The offset in bytes from the start of the unwind info resource to the
+  // unwind instruction table. The unwind instruction table represents
+  // distinct sequences of ARM compact unwind instructions[1] used across all
+  // functions in Chrome. The compact unwind instruction is a byte-oriented
+  // variable length encoding so is indexed by byte position.
+  // 1. See Exception handling ABI for the ARM architecture ABI, §9.3.
+  // https://developer.arm.com/documentation/ihi0038/b.
+  uint32_t unwind_instruction_table_byte_offset;
+  uint32_t unwind_instruction_table_size_in_bytes;
+};
+
+struct BASE_EXPORT ChromeUnwindInfoAndroid {
+  ChromeUnwindInfoAndroid(span<const uint8_t> unwind_instruction_table,
+                          span<const uint8_t> function_offset_table,
+                          span<const FunctionTableEntry> function_table,
+                          span<const uint32_t> page_table);
+  ~ChromeUnwindInfoAndroid();
+  ChromeUnwindInfoAndroid(ChromeUnwindInfoAndroid&& other);
+  ChromeUnwindInfoAndroid& operator=(ChromeUnwindInfoAndroid&& other);
+
+  // Unwind instruction table is expected to have following memory layout:
+  // +-----------------------------+
+  // | <--1 byte--->               |
+  // +-----------------------------+
+  // | pop {r4, r5, lr}            | <- FUNC1 offset 10
+  // +-----------------------------+
+  // | add sp, 16                  | <- FUNC1 offset 4
+  // +-----------------------------+
+  // | mov pc, lr                  | <- FUNC1 offset 0 (COMPLETE)
+  // +-----------------------------+
+  // | pop {r4, r11} [byte 1/2]    | <- FUNC2 offset 8
+  // +-----------------------------+
+  // | pop {r4, r11} [byte 2/2]    |
+  // +-----------------------------+
+  // | ...                         |
+  // +-----------------------------+
+  // Because we are unwinding the function, the next unwind instruction to
+  // execute always has smaller function offset.
+  // The function offsets are often discontinuous as not all instructions in
+  // the function have corresponding unwind instructions.
+  //
+  // See Exception handling ABI for the ARM architecture ABI, §9.3.
+  // https://developer.arm.com/documentation/ihi0038/b.
+  // for details in unwind instruction encoding.
+  // Only following instruction encodings are handled:
+  // - 00xxxxxx
+  // - 01xxxxxx
+  // - 1000iiii iiiiiiii
+  // - 1001nnnn
+  // - 10100nnn
+  // - 10101nnn
+  // - 10110000
+  // - 10110010 uleb128
+  span<const uint8_t> unwind_instruction_table;
+
+  // Function offset table is expected to have following memory layout:
+  // +---------------------+---------------------+
+  // | <-----ULEB128-----> | <-----ULEB128-----> |
+  // +---------------------+---------------------+
+  // | Offset              | Unwind Index        |
+  // +---------------------+---------------------+-----
+  // | 8                   | XXX                 |  |
+  // +---------------------+---------------------+  |
+  // | 3                   | YYY                 |Function 1
+  // +---------------------+---------------------+  |
+  // | 0                   | ZZZ                 |  |
+  // +---------------------+---------------------+-----
+  // | 5                   | AAA                 |  |
+  // +---------------------+---------------------+Function 2
+  // | 0                   | BBB                 |  |
+  // +---------------------+---------------------+-----
+  // | ...                 | ....                |
+  // +---------------------+---------------------+
+  // The function offset table contains [offset, unwind index] pairs, where
+  // - offset: offset from function start address of an instruction that affects
+  //           the unwind state, measured in two-byte instructions.
+  // - unwind index: unwind instruction location in unwind instruction table.
+  //
+  // Note:
+  // - Each function always ends at 0 offset, which corresponds to a terminal
+  //   instruction in unwind instruction table.
+  // - Within each function section, offset strictly decreases. By doing so,
+  //   each function's own terminal instruction will serve as termination
+  //   condition when searching in the table.
+  span<const uint8_t> function_offset_table;
+
+  // The function table represents the individual functions within a 128kb page.
+  // The relevant entry for an instruction offset from the start of the text
+  // section is the one with the largest function_start_address_page_offset <=
+  // instruction_offset_from_text_section_start.
+  //
+  // Function table is expected to have following memory layout:
+  // +--------------------+--------------------+
+  // | <-----2 byte-----> | <-----2 byte-----> |
+  // +--------------------+--------------------+
+  // | Page Offset        | Offset Table Index |
+  // +--------------------+--------------------+-----
+  // | 10                 | XXX                |  |
+  // +--------------------+--------------------+  |
+  // | ...                | ...                |Page 0x100
+  // +--------------------+--------------------+  |
+  // | 65500              | ZZZ                |  |
+  // +--------------------+--------------------+-----
+  // | 200                | AAA                |  |
+  // +--------------------+--------------------+  |
+  // | ...                | ...                |Page 0x101
+  // +--------------------+--------------------+  |
+  // | 65535              | BBB                |  |
+  // +--------------------+--------------------+-----
+  //
+  // Note:
+  // - Within each page, `Page Offset` strictly increases.
+  // - Each `FunctionTableEntry` represents a function where the start
+  // address falls into the page memory address range.
+  span<const FunctionTableEntry> function_table;
+
+  // The page table represents discrete 128kb 'pages' of memory in the text
+  // section, each of which contains functions. The page table is indexed by
+  // bits 17 and greater of the pc offset from the start of the text section.
+  // Indexing into page_table produces an index of function_table.
+  //
+  // The page table is expected to have following memory layout:
+  // +----------------+
+  // | <-- 4 byte --> |
+  // +----------------+
+  // | 0              |
+  // +----------------+
+  // | 18             |
+  // +----------------+
+  // | 18             |
+  // +----------------+
+  // | 80             |
+  // +----------------+
+  // | ...            |
+  // +----------------+
+  // Note:
+  // - The page start instructions in page table non-strictly increases, i.e
+  // empty page is allowed.
+  span<const uint32_t> page_table;
+};
+
+// Creates `ChromeUnwindInfoAndroid` struct based on binary `data` assuming
+// `data` starts with `ChromeUnwindInfoHeaderAndroid`.
+BASE_EXPORT ChromeUnwindInfoAndroid
+CreateChromeUnwindInfoAndroid(span<const uint8_t> data);
+
+}  // namespace base
+
+#endif  // BASE_PROFILER_CHROME_UNWIND_INFO_ANDROID_H_
\ No newline at end of file
diff --git a/base/profiler/chrome_unwind_info_android_unittest.cc b/base/profiler/chrome_unwind_info_android_unittest.cc
new file mode 100644
index 0000000..e33cf7c
--- /dev/null
+++ b/base/profiler/chrome_unwind_info_android_unittest.cc
@@ -0,0 +1,92 @@
+// Copyright 2019 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 "base/profiler/chrome_unwind_info_android.h"
+
+#include <tuple>
+
+#include "base/test/gtest_util.h"
+#include "build/build_config.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+
+bool operator==(const FunctionTableEntry& e1, const FunctionTableEntry& e2) {
+  return std::tie(e1.function_start_address_page_instruction_offset,
+                  e1.function_offset_table_byte_index) ==
+         std::tie(e2.function_start_address_page_instruction_offset,
+                  e2.function_offset_table_byte_index);
+}
+
+template <class T>
+void ExpectSpanSizeAndContentsEqual(span<T> actual, span<T> expected) {
+  EXPECT_EQ(actual.size(), expected.size());
+  if (actual.size() != expected.size()) {
+    return;
+  }
+
+  for (size_t i = 0; i < actual.size(); i++) {
+    EXPECT_EQ(actual[i], expected[i]);
+  }
+}
+
+TEST(ChromeUnwindInfoAndroidTest, CreateUnwindInfo) {
+  ChromeUnwindInfoHeaderAndroid header = {
+      /* page_table_byte_offset */ 64,
+      /* page_table_entries */ 1,
+
+      /* function_table_byte_offset */ 128,
+      /* function_table_entries */ 2,
+
+      /* function_offset_table_byte_offset */ 192,
+      /* function_offset_table_size_in_bytes */ 3,
+
+      /* unwind_instruction_table_byte_offset */ 256,
+      /* unwind_instruction_table_size_in_bytes */ 4,
+  };
+
+  uint8_t data[512] = {};
+  // Note: `CreateChromeUnwindInfoAndroid` is not expected to verify the content
+  // of each unwind table.
+  const uint32_t page_table[] = {1};
+  const FunctionTableEntry function_table[] = {{0, 2}, {0, 3}};
+  const uint8_t function_offset_table[] = {3, 3, 3};
+  const uint8_t unwind_instruction_table[] = {4, 4, 4, 4};
+
+  ASSERT_LT(sizeof(ChromeUnwindInfoHeaderAndroid), 64ul);
+  memcpy(&data[0], &header, sizeof(ChromeUnwindInfoHeaderAndroid));
+
+  memcpy(&data[header.page_table_byte_offset], page_table, sizeof(page_table));
+  memcpy(&data[header.function_table_byte_offset], function_table,
+         sizeof(function_table));
+  memcpy(&data[header.function_offset_table_byte_offset], function_offset_table,
+         sizeof(function_offset_table));
+  memcpy(&data[header.unwind_instruction_table_byte_offset],
+         unwind_instruction_table, sizeof(unwind_instruction_table));
+
+  ChromeUnwindInfoAndroid unwind_info = CreateChromeUnwindInfoAndroid(data);
+
+  ASSERT_EQ(&data[64],
+            reinterpret_cast<const uint8_t*>(&unwind_info.page_table[0]));
+  ASSERT_EQ(&data[128],
+            reinterpret_cast<const uint8_t*>(&unwind_info.function_table[0]));
+  ASSERT_EQ(&data[192], reinterpret_cast<const uint8_t*>(
+                            &unwind_info.function_offset_table[0]));
+  ASSERT_EQ(&data[256], reinterpret_cast<const uint8_t*>(
+                            &unwind_info.unwind_instruction_table[0]));
+
+  ExpectSpanSizeAndContentsEqual(unwind_info.page_table,
+                                 make_span(page_table, size(page_table)));
+  ExpectSpanSizeAndContentsEqual(
+      unwind_info.function_table,
+      make_span(function_table, size(function_table)));
+  ExpectSpanSizeAndContentsEqual(
+      unwind_info.function_offset_table,
+      make_span(function_offset_table, size(function_offset_table)));
+  ExpectSpanSizeAndContentsEqual(
+      unwind_info.unwind_instruction_table,
+      make_span(unwind_instruction_table, size(unwind_instruction_table)));
+}
+
+}  // namespace base
diff --git a/base/profiler/chrome_unwind_table_android.cc b/base/profiler/chrome_unwind_table_android.cc
index f2652e4f..20ea112 100644
--- a/base/profiler/chrome_unwind_table_android.cc
+++ b/base/profiler/chrome_unwind_table_android.cc
@@ -9,6 +9,7 @@
 #include "base/check_op.h"
 #include "base/notreached.h"
 #include "base/numerics/checked_math.h"
+#include "base/profiler/chrome_unwind_info_android.h"
 
 namespace base {
 namespace {
diff --git a/base/profiler/chrome_unwind_table_android.h b/base/profiler/chrome_unwind_table_android.h
index 7c01c07..41e7e132 100644
--- a/base/profiler/chrome_unwind_table_android.h
+++ b/base/profiler/chrome_unwind_table_android.h
@@ -14,47 +14,17 @@
 
 namespace base {
 
+struct FunctionTableEntry;
+
 enum class UnwindInstructionResult {
   kCompleted,           // Signals the end of unwind process.
   kInstructionPending,  // Continues to unwind next instruction.
   kAborted,             // Unable to unwind.
 };
 
-// Execute a single unwind instruction on the given thread_context,
-// and moves `instruction` to point to next instruction right after the executed
-// instruction if the executed result is `INSTRUCTION_PENDING`.
-//
-// See Exception handling ABI for the ARM architecture ABI, §9.3.
-// https://developer.arm.com/documentation/ihi0038/b.
-// for details in unwind instruction encoding.
-// Only following instruction encodings are handled:
-// - 00xxxxxx
-// - 01xxxxxx
-// - 1000iiii iiiiiiii
-// - 1001nnnn
-// - 10100nnn
-// - 10101nnn
-// - 10110000
-// - 10110010 uleb128
-//
-// Unwind instruction table is expected to have following memory layout:
-// +----------------+
-// | <--1 byte--->  |
-// +----------------+
-// | INST_PENDING   | <- FUNC1 offset 10
-// +----------------+
-// | INST_PENDING   | <- FUNC1 offset 4
-// +----------------+
-// | COMPLETE       | <- FUNC1 offset 0
-// +----------------+
-// | INST_PENDING   | <- FUNC2 offset 8
-// +----------------+
-// | ...            |
-// +----------------+
-// Because we are unwinding the function, the next unwind instruction to
-// execute always have smaller function offset.
-// The function offsets are often discontinuous as not all instructions in
-// the function have corresponding unwind instructions.
+// Execute a single unwind instruction on the given thread_context, and moves
+// `instruction` to point to next instruction right after the executed
+// instruction.
 //
 // Arguments:
 //   instruction: The pointer to the instruction to execute. This pointer will
@@ -69,18 +39,6 @@
                          bool& pc_was_updated,
                          RegisterContext* thread_context);
 
-// Represents each entry in the function table (i.e. the second level of the
-// function address table).
-struct FunctionTableEntry {
-  // The offset into the 128kb page containing this function. Indexed by bits
-  // 1-16 of the pc offset from the start of the text section.
-  uint16_t function_start_address_page_instruction_offset;
-
-  // The byte index of the first offset for the function in the function
-  // offset table.
-  uint16_t function_offset_table_byte_index;
-};
-
 // Represents an index that can locate a specific entry on function offset
 // table.
 struct FunctionOffsetTableIndex {
@@ -95,87 +53,28 @@
 // Given `FunctionOffsetTableIndex`, finds the instruction to execute on unwind
 // instruction table.
 //
-// Function offset table is expected to have following memory layout:
-// +---------------------+---------------------+
-// | <-----ULEB128-----> | <-----ULEB128-----> |
-// +---------------------+---------------------+
-// | Offset              | Unwind Index        |
-// +---------------------+---------------------+-----
-// | 8                   | XXX                 |  |
-// +---------------------+---------------------+  |
-// | 3                   | YYY                 |Function 1
-// +---------------------+---------------------+  |
-// | 0                   | ZZZ                 |  |
-// +---------------------+---------------------+-----
-// | 5                   | AAA                 |  |
-// +---------------------+---------------------+Function 2
-// | 0                   | BBB                 |  |
-// +---------------------+---------------------+-----
-// | ...                 | ....                |
-// +---------------------+---------------------+
-//
-// The function offset table contains [offset, unwind index] pairs, where
-// - offset: offset from function start address of an instruction that affects
-//           the unwind state, measured in two-byte instructions.
-// - unwind index: unwind instruction location on unwind instruction table.
-//
-// Note:
-// - Each function always ends at 0 offset, which correspond to a COMPLETE
-//   instruction on unwind instruction table.
-// - Within each function section, offset strictly decreases. By doing so,
-//   each function's own COMPLETE instruction will serve as termination
-//   condition when searching in the table.
-//
 // Arguments:
-//  unwind_instruction_table: The table that stores a list of unwind
-//                             instructions
-//  function_offset_table: Explained above.
-//  function_offset_table_byte_index: The byte index of the first offset for the
-//                                    function in the function offset table.
-//  instruction_offset_from_function_start: (pc - function_start_address) >> 1.
+//  unwind_instruction_table: See
+//    `ChromeUnwindInfoAndroid::unwind_instruction_table` for details.
+//  function_offset_table: See
+//    `ChromeUnwindInfoAndroid::function_offset_table` for details.
+//  index: The index used to locate an entry in `function_offset_table`.
 BASE_EXPORT const uint8_t*
 GetFirstUnwindInstructionFromFunctionOffsetTableIndex(
     const uint8_t* unwind_instruction_table,
     const uint8_t* function_offset_table,
     const FunctionOffsetTableIndex& index);
 
-// Given an instruction offset_from_text_section_start, finds the corresponding
+// Given an instruction_offset_from_text_section_start, finds the corresponding
 // `FunctionOffsetTableIndex`.
 //
-// The function table represents the individual functions within a 128kb page.
-// The relevant entry for an instruction offset from the start of the text
-// section is the one with the largest function_start_address_page_offset <=
-// instruction_offset_from_text_section_start
-//
-// Function table is expected to have following memory layout:
-// +--------------------+--------------------+
-// | <-----2 byte-----> | <-----2 byte-----> |
-// +--------------------+--------------------+
-// | Page Offset        | Offset Table Index |
-// +--------------------+--------------------+-----
-// | 10                 | XXX                |  |
-// +--------------------+--------------------+  |
-// | ...                | ...                |Page 0x100
-// +--------------------+--------------------+  |
-// | 65500              | ZZZ                |  |
-// +--------------------+--------------------+-----
-// | 200                | AAA                |  |
-// +--------------------+--------------------+  |
-// | ...                | ...                |Page 0x101
-// +--------------------+--------------------+  |
-// | 65535              | BBB                |  |
-// +--------------------+--------------------+-----
-//
-// Note:
-// - Within each page, `Page Offset` strictly increases.
-// - Each `FunctionTableEntry` represents a function where the start
-// address falls into the page memory address range.
-//
-// The page table represents discrete 128kb 'pages' of memory in the text
-// section, each of which contains `FunctionTableEntry`s.
-// Note:
-// - The page start instructions in page table non-strictly increases, i.e
-// empty page is allowed.
+// Arguments:
+//  page_start_instructions: A list of page_numbers. See
+//    `ChromeUnwindInfoAndroid::page_table` for details.
+//  function_offsets_table_indices: A list of `FunctionTableEntry`. See
+//    `ChromeUnwindInfoAndroid::function_table` for details.
+//  instruction_offset_from_text_section_start: The distance in bytes between
+//    the instruction of interest and text section start.
 BASE_EXPORT const absl::optional<FunctionOffsetTableIndex>
 GetFunctionTableIndexFromInstructionOffset(
     span<const uint32_t> page_start_instructions,
diff --git a/base/profiler/chrome_unwind_table_android_unittest.cc b/base/profiler/chrome_unwind_table_android_unittest.cc
index 51538e8..9b6f30c1 100644
--- a/base/profiler/chrome_unwind_table_android_unittest.cc
+++ b/base/profiler/chrome_unwind_table_android_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "base/profiler/chrome_unwind_table_android.h"
 
+#include "base/profiler/chrome_unwind_info_android.h"
 #include "base/test/gtest_util.h"
 #include "build/build_config.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/base/trace_event/memory_infra_background_allowlist.cc b/base/trace_event/memory_infra_background_allowlist.cc
index 64ceedd..d9462c2 100644
--- a/base/trace_event/memory_infra_background_allowlist.cc
+++ b/base/trace_event/memory_infra_background_allowlist.cc
@@ -115,6 +115,7 @@
     "extensions/value_store/Extensions.Database.Open.Settings/0x?",
     "extensions/value_store/Extensions.Database.Open.Rules/0x?",
     "extensions/value_store/Extensions.Database.Open.State/0x?",
+    "extensions/value_store/Extensions.Database.Open.Scripts/0x?",
     "extensions/value_store/Extensions.Database.Open/0x?",
     "extensions/value_store/Extensions.Database.Restore/0x?",
     "extensions/value_store/Extensions.Database.Value.Restore/0x?",
diff --git a/build/fuchsia/PRESUBMIT.py b/build/fuchsia/PRESUBMIT.py
index 4cdd4d02..d21d7b0 100644
--- a/build/fuchsia/PRESUBMIT.py
+++ b/build/fuchsia/PRESUBMIT.py
@@ -20,8 +20,7 @@
       input_api.canned_checks.GetUnitTests(
           input_api,
           output_api,
-          unit_tests=[J('boot_data_test.py'),
-                      J('fvdl_target_test.py')],
+          unit_tests=[J('fvdl_target_test.py')],
           run_on_python2=False,
           run_on_python3=True))
   return input_api.RunTests(tests)
diff --git a/build/fuchsia/boot_data.py b/build/fuchsia/boot_data.py
index f59d1974..e63c9e73 100644
--- a/build/fuchsia/boot_data.py
+++ b/build/fuchsia/boot_data.py
@@ -40,41 +40,23 @@
 _SSH_CONFIG_DIR = os.path.expanduser('~/.fuchsia')
 
 
-def _GetPubKeyPath():
-  """Returns a path to the generated SSH public key."""
+def _GetAuthorizedKeysPath():
+  """Returns a path to the authorized keys which get copied to your Fuchsia
+  device during paving"""
 
-  return os.path.join(_SSH_DIR, 'fuchsia_ed25519.pub')
+  return os.path.join(_SSH_DIR, 'fuchsia_authorized_keys')
 
 
 def ProvisionSSH():
-  """Generates a key pair and config file for SSH."""
+  """Generates a key pair and config file for SSH using the GN SDK."""
 
-  fuchsia_authorized_keys_path = os.path.join(_SSH_DIR,
-                                              'fuchsia_authorized_keys')
-  id_key_path = os.path.join(_SSH_DIR, 'fuchsia_ed25519')
-  _GetPubKeyPath()
-
-  logging.debug('Generating SSH credentials.')
-
-  if not os.path.isfile(id_key_path):
-    subprocess.check_output([
-        'ssh-keygen', '-P', '', '-t', 'ed25519', '-f', id_key_path, '-C',
-        'generated by FEMU Start testing step'
-    ])
-
-  if not os.path.isfile(fuchsia_authorized_keys_path):
-    result = subprocess.check_output(['ssh-keygen', '-y', '-f', id_key_path])
-    with open(fuchsia_authorized_keys_path, 'w') as out:
-      out.write(result.decode('utf-8'))
-
-  if not os.path.exists(_SSH_CONFIG_DIR):
-    os.mkdir(_SSH_CONFIG_DIR)
-  elif not os.path.isdir(_SSH_CONFIG_DIR):
-    raise Exception(_SSH_CONFIG_DIR + ' is not a directory.')
-  ssh_config_path = os.path.join(_SSH_CONFIG_DIR, 'ssh_config')
-  with open(ssh_config_path, "w") as ssh_config:
-    ssh_config.write(
-        _SSH_CONFIG_TEMPLATE.format(identity=id_key_path))
+  returncode, out, err = common.RunGnSdkFunction('fuchsia-common.sh',
+                                                 'check-fuchsia-ssh-config')
+  if returncode != 0:
+    logging.error('Command exited with error code %d' % (returncode))
+    logging.error('Stdout: %s' % out)
+    logging.error('Stderr: %s' % err)
+    raise Exception('Failed to provision ssh keys')
 
 
 def GetTargetFile(filename, target_arch, target_type):
@@ -87,20 +69,22 @@
 
 
 def GetSSHConfigPath():
-  return os.path.join(_SSH_CONFIG_DIR, 'ssh_config')
+  return os.path.join(_SSH_CONFIG_DIR, 'sshconfig')
 
 
 def GetBootImage(output_dir, target_arch, target_type):
   """"Gets a path to the Zircon boot image, with the SSH client public key
   added."""
   ProvisionSSH()
-  pubkey_path = _GetPubKeyPath()
+  authkeys_path = _GetAuthorizedKeysPath()
   zbi_tool = common.GetHostToolPathFromPlatform('zbi')
   image_source_path = GetTargetFile('zircon-a.zbi', target_arch, target_type)
   image_dest_path = os.path.join(output_dir, 'gen', 'fuchsia-with-keys.zbi')
 
-  cmd = [ zbi_tool, '-o', image_dest_path, image_source_path,
-          '-e', 'data/ssh/authorized_keys=' + pubkey_path ]
+  cmd = [
+      zbi_tool, '-o', image_dest_path, image_source_path, '-e',
+      'data/ssh/authorized_keys=' + authkeys_path
+  ]
   subprocess.check_call(cmd)
 
   return image_dest_path
diff --git a/build/fuchsia/boot_data_test.py b/build/fuchsia/boot_data_test.py
index aa652eb..ffa88cc 100755
--- a/build/fuchsia/boot_data_test.py
+++ b/build/fuchsia/boot_data_test.py
@@ -6,21 +6,21 @@
 import boot_data
 import os
 import unittest
-from boot_data import _SSH_CONFIG_DIR, _SSH_DIR
+from boot_data import _SSH_CONFIG_DIR, _SSH_DIR, _GetAuthorizedKeysPath, \
+                      GetSSHConfigPath
 
 
 class TestBootData(unittest.TestCase):
   def testProvisionSSHGeneratesFiles(self):
-    fuchsia_authorized_keys_path = os.path.join(_SSH_DIR,
-                                                'fuchsia_authorized_keys')
+    fuchsia_authorized_keys_path = _GetAuthorizedKeysPath()
     fuchsia_id_key_path = os.path.join(_SSH_DIR, 'fuchsia_ed25519')
-    pub_keys_path = os.path.join(_SSH_DIR, 'fuchsia_ed25519.pub')
-    ssh_config_path = os.path.join(_SSH_CONFIG_DIR, 'ssh_config')
+    fuchsia_pub_key_path = os.path.join(_SSH_DIR, 'fuchsia_ed25519.pub')
+    ssh_config_path = GetSSHConfigPath()
     # Check if the keys exists before generating. If they do, delete them
     # afterwards before asserting if ProvisionSSH works.
     authorized_key_before = os.path.exists(fuchsia_authorized_keys_path)
     id_keys_before = os.path.exists(fuchsia_id_key_path)
-    pub_keys_before = os.path.exists(pub_keys_path)
+    pub_keys_before = os.path.exists(fuchsia_pub_key_path)
     ssh_config_before = os.path.exists(ssh_config_path)
     ssh_dir_before = os.path.exists(_SSH_CONFIG_DIR)
     boot_data.ProvisionSSH()
@@ -32,7 +32,7 @@
     if not id_keys_before:
       os.remove(fuchsia_id_key_path)
     if not pub_keys_before:
-      os.remove(pub_keys_path)
+      os.remove(fuchsia_pub_key_path)
     if not ssh_config_before:
       os.remove(ssh_config_path)
     if not ssh_dir_before:
diff --git a/build/fuchsia/common.py b/build/fuchsia/common.py
index 99ced81..9f780915 100644
--- a/build/fuchsia/common.py
+++ b/build/fuchsia/common.py
@@ -97,6 +97,12 @@
   return port
 
 
+def RunGnSdkFunction(script, function):
+  script_path = os.path.join(SDK_ROOT, 'bin', script)
+  function_cmd = ['bash', '-c', '. %s; %s' % (script_path, function)]
+  return SubprocessCallWithTimeout(function_cmd)
+
+
 def SubprocessCallWithTimeout(command, silent=False, timeout_secs=None):
   """Helper function for running a command.
 
diff --git a/build/linux/sysroot_scripts/generated_package_lists/sid.amd64 b/build/linux/sysroot_scripts/generated_package_lists/sid.amd64
index 29ea13c4..037d392 100644
--- a/build/linux/sysroot_scripts/generated_package_lists/sid.amd64
+++ b/build/linux/sysroot_scripts/generated_package_lists/sid.amd64
@@ -345,6 +345,7 @@
 https://snapshot.debian.org/archive/debian/20210309T203820Z/pool/main/u/util-linux/libmount-dev_2.36.1-7_amd64.deb
 https://snapshot.debian.org/archive/debian/20210309T203820Z/pool/main/u/util-linux/libuuid1_2.36.1-7_amd64.deb
 https://snapshot.debian.org/archive/debian/20210309T203820Z/pool/main/u/util-linux/uuid-dev_2.36.1-7_amd64.deb
+https://snapshot.debian.org/archive/debian/20210309T203820Z/pool/main/v/valgrind/valgrind_3.16.1-1_amd64.deb
 https://snapshot.debian.org/archive/debian/20210309T203820Z/pool/main/v/vulkan-loader/libvulkan1_1.2.162.0-1_amd64.deb
 https://snapshot.debian.org/archive/debian/20210309T203820Z/pool/main/v/vulkan-loader/libvulkan-dev_1.2.162.0-1_amd64.deb
 https://snapshot.debian.org/archive/debian/20210309T203820Z/pool/main/w/wayland/libwayland-client0_1.19.0-2_amd64.deb
diff --git a/build/linux/sysroot_scripts/generated_package_lists/sid.arm b/build/linux/sysroot_scripts/generated_package_lists/sid.arm
index b91ebc4..dbb3133 100644
--- a/build/linux/sysroot_scripts/generated_package_lists/sid.arm
+++ b/build/linux/sysroot_scripts/generated_package_lists/sid.arm
@@ -341,6 +341,7 @@
 https://snapshot.debian.org/archive/debian/20210309T203820Z/pool/main/u/util-linux/libmount-dev_2.36.1-7_armhf.deb
 https://snapshot.debian.org/archive/debian/20210309T203820Z/pool/main/u/util-linux/libuuid1_2.36.1-7_armhf.deb
 https://snapshot.debian.org/archive/debian/20210309T203820Z/pool/main/u/util-linux/uuid-dev_2.36.1-7_armhf.deb
+https://snapshot.debian.org/archive/debian/20210309T203820Z/pool/main/v/valgrind/valgrind_3.16.1-1_armhf.deb
 https://snapshot.debian.org/archive/debian/20210309T203820Z/pool/main/v/vulkan-loader/libvulkan1_1.2.162.0-1_armhf.deb
 https://snapshot.debian.org/archive/debian/20210309T203820Z/pool/main/v/vulkan-loader/libvulkan-dev_1.2.162.0-1_armhf.deb
 https://snapshot.debian.org/archive/debian/20210309T203820Z/pool/main/w/wayland/libwayland-client0_1.19.0-2_armhf.deb
diff --git a/build/linux/sysroot_scripts/generated_package_lists/sid.arm64 b/build/linux/sysroot_scripts/generated_package_lists/sid.arm64
index 4db2b8a..45d05e8 100644
--- a/build/linux/sysroot_scripts/generated_package_lists/sid.arm64
+++ b/build/linux/sysroot_scripts/generated_package_lists/sid.arm64
@@ -344,6 +344,7 @@
 https://snapshot.debian.org/archive/debian/20210309T203820Z/pool/main/u/util-linux/libmount-dev_2.36.1-7_arm64.deb
 https://snapshot.debian.org/archive/debian/20210309T203820Z/pool/main/u/util-linux/libuuid1_2.36.1-7_arm64.deb
 https://snapshot.debian.org/archive/debian/20210309T203820Z/pool/main/u/util-linux/uuid-dev_2.36.1-7_arm64.deb
+https://snapshot.debian.org/archive/debian/20210309T203820Z/pool/main/v/valgrind/valgrind_3.16.1-1_arm64.deb
 https://snapshot.debian.org/archive/debian/20210309T203820Z/pool/main/v/vulkan-loader/libvulkan1_1.2.162.0-1_arm64.deb
 https://snapshot.debian.org/archive/debian/20210309T203820Z/pool/main/v/vulkan-loader/libvulkan-dev_1.2.162.0-1_arm64.deb
 https://snapshot.debian.org/archive/debian/20210309T203820Z/pool/main/w/wayland/libwayland-client0_1.19.0-2_arm64.deb
diff --git a/build/linux/sysroot_scripts/generated_package_lists/sid.i386 b/build/linux/sysroot_scripts/generated_package_lists/sid.i386
index cdeaf9a2..f177c88 100644
--- a/build/linux/sysroot_scripts/generated_package_lists/sid.i386
+++ b/build/linux/sysroot_scripts/generated_package_lists/sid.i386
@@ -341,6 +341,7 @@
 https://snapshot.debian.org/archive/debian/20210309T203820Z/pool/main/u/util-linux/libmount-dev_2.36.1-7_i386.deb
 https://snapshot.debian.org/archive/debian/20210309T203820Z/pool/main/u/util-linux/libuuid1_2.36.1-7_i386.deb
 https://snapshot.debian.org/archive/debian/20210309T203820Z/pool/main/u/util-linux/uuid-dev_2.36.1-7_i386.deb
+https://snapshot.debian.org/archive/debian/20210309T203820Z/pool/main/v/valgrind/valgrind_3.16.1-1_i386.deb
 https://snapshot.debian.org/archive/debian/20210309T203820Z/pool/main/v/vulkan-loader/libvulkan1_1.2.162.0-1_i386.deb
 https://snapshot.debian.org/archive/debian/20210309T203820Z/pool/main/v/vulkan-loader/libvulkan-dev_1.2.162.0-1_i386.deb
 https://snapshot.debian.org/archive/debian/20210309T203820Z/pool/main/w/wayland/libwayland-client0_1.19.0-2_i386.deb
diff --git a/build/linux/sysroot_scripts/generated_package_lists/sid.mips64el b/build/linux/sysroot_scripts/generated_package_lists/sid.mips64el
index a3b6559..13e978b 100644
--- a/build/linux/sysroot_scripts/generated_package_lists/sid.mips64el
+++ b/build/linux/sysroot_scripts/generated_package_lists/sid.mips64el
@@ -332,6 +332,7 @@
 https://snapshot.debian.org/archive/debian/20210309T203820Z/pool/main/u/util-linux/libmount-dev_2.36.1-7_mips64el.deb
 https://snapshot.debian.org/archive/debian/20210309T203820Z/pool/main/u/util-linux/libuuid1_2.36.1-7_mips64el.deb
 https://snapshot.debian.org/archive/debian/20210309T203820Z/pool/main/u/util-linux/uuid-dev_2.36.1-7_mips64el.deb
+https://snapshot.debian.org/archive/debian/20210309T203820Z/pool/main/v/valgrind/valgrind_3.16.1-1_mips64el.deb
 https://snapshot.debian.org/archive/debian/20210309T203820Z/pool/main/v/vulkan-loader/libvulkan1_1.2.162.0-1_mips64el.deb
 https://snapshot.debian.org/archive/debian/20210309T203820Z/pool/main/v/vulkan-loader/libvulkan-dev_1.2.162.0-1_mips64el.deb
 https://snapshot.debian.org/archive/debian/20210309T203820Z/pool/main/w/wayland/libwayland-client0_1.19.0-2_mips64el.deb
diff --git a/build/linux/sysroot_scripts/sysroot-creator-sid.sh b/build/linux/sysroot_scripts/sysroot-creator-sid.sh
index 86c311cb..4695580b 100755
--- a/build/linux/sysroot_scripts/sysroot-creator-sid.sh
+++ b/build/linux/sysroot_scripts/sysroot-creator-sid.sh
@@ -417,6 +417,7 @@
   libmpx2
   libquadmath0
   libubsan1
+  valgrind
 "
 
 DEBIAN_PACKAGES_ARM="
@@ -429,6 +430,7 @@
   libgtk-4-1
   libgtk-4-dev
   libubsan1
+  valgrind
 "
 
 DEBIAN_PACKAGES_ARM64="
@@ -444,6 +446,7 @@
   libthai0
   libtsan0
   libubsan1
+  valgrind
 "
 
 DEBIAN_PACKAGES_ARMEL="
@@ -458,6 +461,7 @@
 "
 
 DEBIAN_PACKAGES_MIPS64EL="
+  valgrind
 "
 
 . "${SCRIPT_DIR}/sysroot-creator.sh"
diff --git a/build/linux/sysroot_scripts/sysroots.json b/build/linux/sysroot_scripts/sysroots.json
index 6248db7..63b6d98 100644
--- a/build/linux/sysroot_scripts/sysroots.json
+++ b/build/linux/sysroot_scripts/sysroots.json
@@ -1,16 +1,16 @@
 {
     "sid_amd64": {
-        "Sha1Sum": "43a87bbebccad99325fdcf34166295b121ee15c7",
+        "Sha1Sum": "95051d95804a77144986255f534acb920cee375b",
         "SysrootDir": "debian_sid_amd64-sysroot",
         "Tarball": "debian_sid_amd64_sysroot.tar.xz"
     },
     "sid_arm": {
-        "Sha1Sum": "11d6f690ca49e8ba01a1d8c5346cedad2cf308fd",
+        "Sha1Sum": "8cf8dfa68861f84ce79d038f08da6e685487def5",
         "SysrootDir": "debian_sid_arm-sysroot",
         "Tarball": "debian_sid_arm_sysroot.tar.xz"
     },
     "sid_arm64": {
-        "Sha1Sum": "2befe8ce3e88be6080e4fb7e6d412278ea6a7625",
+        "Sha1Sum": "9677df0c176ac33116618f109c4988b719ad78c6",
         "SysrootDir": "debian_sid_arm64-sysroot",
         "Tarball": "debian_sid_arm64_sysroot.tar.xz"
     },
@@ -20,17 +20,17 @@
         "Tarball": "debian_sid_armel_sysroot.tar.xz"
     },
     "sid_i386": {
-        "Sha1Sum": "d53a049af5961f2f121ee4e149918097c193f8ed",
+        "Sha1Sum": "4840dc83ec7c3816ae0262e9e93231736bf0a5b7",
         "SysrootDir": "debian_sid_i386-sysroot",
         "Tarball": "debian_sid_i386_sysroot.tar.xz"
     },
     "sid_mips": {
-        "Sha1Sum": "eb577cef43088b7e0540950c74f994267631d4cd",
+        "Sha1Sum": "779ca2ab213f78b0c7d94ff157ee444ae2d40043",
         "SysrootDir": "debian_sid_mips-sysroot",
         "Tarball": "debian_sid_mips_sysroot.tar.xz"
     },
     "sid_mips64el": {
-        "Sha1Sum": "6cb76f27035d1460fe164f7e6c5318c047aac153",
+        "Sha1Sum": "27d205329440aa96002da71968a0dbef09aa7d6a",
         "SysrootDir": "debian_sid_mips64el-sysroot",
         "Tarball": "debian_sid_mips64el_sysroot.tar.xz"
     }
diff --git a/build/rust/tests/test_cpp_including_rust/BUILD.gn b/build/rust/tests/test_cpp_including_rust/BUILD.gn
index ee34675..76e8446b 100644
--- a/build/rust/tests/test_cpp_including_rust/BUILD.gn
+++ b/build/rust/tests/test_cpp_including_rust/BUILD.gn
@@ -13,7 +13,8 @@
 test("test_cpp_including_rust_unittests") {
   sources = [ "unittests.cc" ]
   deps = [
-    "//base/allocator",
+    "//base",
+    "//base/allocator:buildflags",
     "//base/test:run_all_unittests",
     "//build/rust/tests/test_rust_source_set:test_rust_source_set_lib",
     "//testing/gmock",
diff --git a/build/skia_gold_common/output_managerless_skia_gold_session.py b/build/skia_gold_common/output_managerless_skia_gold_session.py
index b22487f..a74b68f 100644
--- a/build/skia_gold_common/output_managerless_skia_gold_session.py
+++ b/build/skia_gold_common/output_managerless_skia_gold_session.py
@@ -10,6 +10,8 @@
 import subprocess
 import time
 
+import six
+
 from skia_gold_common import skia_gold_session
 
 
@@ -62,7 +64,11 @@
   @staticmethod
   def _RunCmdForRcAndOutput(cmd):
     try:
-      output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
+      output = subprocess.check_output(cmd,
+                                       stderr=subprocess.STDOUT).decode('utf-8')
       return 0, output
     except subprocess.CalledProcessError as e:
-      return e.returncode, e.output
+      output = e.output
+      if not isinstance(output, six.string_types):
+        output = output.decode('utf-8')
+      return e.returncode, output
diff --git a/cc/metrics/total_frame_counter.cc b/cc/metrics/total_frame_counter.cc
index 4e18f6e7..1d07e35 100644
--- a/cc/metrics/total_frame_counter.cc
+++ b/cc/metrics/total_frame_counter.cc
@@ -66,7 +66,7 @@
 
   DCHECK_GE(until, last_shown_timestamp_);
   auto frames_since =
-      std::round((until - last_shown_timestamp_) / latest_interval_);
+      std::ceil((until - last_shown_timestamp_) / latest_interval_);
   return total_frames_ + frames_since;
 }
 
diff --git a/cc/metrics/total_frame_counter_unittest.cc b/cc/metrics/total_frame_counter_unittest.cc
index fce7a6d..2baee72 100644
--- a/cc/metrics/total_frame_counter_unittest.cc
+++ b/cc/metrics/total_frame_counter_unittest.cc
@@ -33,17 +33,18 @@
   TotalFrameCounter counter;
   uint64_t sequence_number = 1;
   auto frame_time = base::TimeTicks::Now();
-  auto interval = base::TimeDelta::FromMillisecondsD(16.67);
+  // Use intervals that divide evenly into one second to avoid rounding issues.
+  auto interval = base::TimeDelta::FromMilliseconds(20);
 
-  // Make the page visible at the default frame rate.
+  // Make the page visible at 50fps.
   auto args = viz::BeginFrameArgs::Create(
       BEGINFRAME_FROM_HERE, kSourceId, sequence_number++, frame_time,
       frame_time + interval, interval, viz::BeginFrameArgs::NORMAL);
   counter.OnShow(frame_time);
   counter.OnBeginFrame(args);
 
-  // After 10 seconds, change the frame rate to be 120fps.
-  interval = base::TimeDelta::FromMillisecondsD(8.33);
+  // After 10 seconds, change the frame rate to be 100fps.
+  interval = base::TimeDelta::FromMilliseconds(10);
   frame_time += base::TimeDelta::FromSeconds(10);
   args = viz::BeginFrameArgs::Create(
       BEGINFRAME_FROM_HERE, kSourceId, sequence_number++, frame_time,
@@ -54,7 +55,7 @@
   auto advance = base::TimeDelta::FromSeconds(10);
   frame_time += advance;
   counter.OnHide(frame_time);
-  EXPECT_EQ(counter.total_frames(), 1800u);
+  EXPECT_EQ(counter.total_frames(), 1500u);
 }
 
 TEST(TotalFrameCounterTest, VisibilityChange) {
diff --git a/cc/raster/single_thread_task_graph_runner.cc b/cc/raster/single_thread_task_graph_runner.cc
index c772814..0dab12c 100644
--- a/cc/raster/single_thread_task_graph_runner.cc
+++ b/cc/raster/single_thread_task_graph_runner.cc
@@ -11,7 +11,7 @@
 #include <utility>
 
 #include "base/threading/simple_thread.h"
-#include "base/trace_event/trace_event.h"
+#include "base/trace_event/base_tracing.h"
 
 namespace cc {
 
@@ -116,6 +116,11 @@
 
   while (true) {
     if (!RunTaskWithLockAcquired()) {
+      // Make sure the END of the last trace event emitted before going idle
+      // is flushed to perfetto.
+      // TODO(crbug.com/1021571): Remove this once fixed.
+      PERFETTO_INTERNAL_ADD_EMPTY_EVENT();
+
       // Exit when shutdown is set and no more tasks are pending.
       if (shutdown_)
         break;
diff --git a/chrome/VERSION b/chrome/VERSION
index 2fbe1f7..7ecd409 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=96
 MINOR=0
-BUILD=4652
+BUILD=4653
 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 092b64fc..4a078af 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -2456,7 +2456,6 @@
   sources = [
     "../browser/attribution_reporting/android/java/src/org/chromium/chrome/browser/attribution_reporting/AttributionReportingProvider.java",
     "java/src/com/google/ipc/invalidation/ticl/android2/channel/GcmRegistrationTaskService.java",
-    "java/src/org/chromium/chrome/app/TrichromeZygotePreload.java",
     "java/src/org/chromium/chrome/browser/ChromeBackgroundService.java",
     "java/src/org/chromium/chrome/browser/ChromeBackupAgent.java",
     "java/src/org/chromium/chrome/browser/DeferredStartupHandler.java",
diff --git a/chrome/android/chrome_java_resources.gni b/chrome/android/chrome_java_resources.gni
index bb453b6..2733d3e4 100644
--- a/chrome/android/chrome_java_resources.gni
+++ b/chrome/android/chrome_java_resources.gni
@@ -487,7 +487,6 @@
   "java/res/drawable/ic_checkmark_24dp.xml",
   "java/res/drawable/ic_cloud_offline_24dp.xml",
   "java/res/drawable/ic_credit_card_black.xml",
-  "java/res/drawable/ic_desktop_windows.xml",
   "java/res/drawable/ic_error.xml",
   "java/res/drawable/ic_file_download_scheduled_24dp.xml",
   "java/res/drawable/ic_find_in_page.xml",
diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni
index 5ed1e35..9c5ae20 100644
--- a/chrome/android/chrome_public_apk_tmpl.gni
+++ b/chrome/android/chrome_public_apk_tmpl.gni
@@ -22,7 +22,6 @@
   "channel=$android_channel",
   "enable_vr=$enable_vr",
   "include_arcore_manifest_flag=false",
-  "zygote_preload_class=org.chromium.content_public.app.ZygotePreload",
 ]
 
 # Enable stack unwinding only on official build with specific channels. It is
diff --git a/chrome/android/expectations/monochrome_public_bundle.AndroidManifest.expected b/chrome/android/expectations/monochrome_public_bundle.AndroidManifest.expected
index e03f4d8..fea5945 100644
--- a/chrome/android/expectations/monochrome_public_bundle.AndroidManifest.expected
+++ b/chrome/android/expectations/monochrome_public_bundle.AndroidManifest.expected
@@ -85,7 +85,7 @@
       android:roundIcon="@drawable/ic_launcher_round"
       android:supportsRtl="true"
       android:use32bitAbi="true"
-      android:zygotePreloadName="org.chromium.content_public.app.ZygotePreload">
+      android:zygotePreloadName="org.chromium.content.app.ZygotePreload">
     <activity  # DIFF-ANCHOR: ea1a94af
         android:name="com.google.android.gms.common.api.GoogleApiActivity"
         android:exported="false"
diff --git a/chrome/android/expectations/trichrome_chrome_bundle.AndroidManifest.expected b/chrome/android/expectations/trichrome_chrome_bundle.AndroidManifest.expected
index c472e557..1643eb9 100644
--- a/chrome/android/expectations/trichrome_chrome_bundle.AndroidManifest.expected
+++ b/chrome/android/expectations/trichrome_chrome_bundle.AndroidManifest.expected
@@ -85,7 +85,7 @@
       android:roundIcon="@drawable/ic_launcher_round"
       android:supportsRtl="true"
       android:use32bitAbi="true"
-      android:zygotePreloadName="org.chromium.chrome.app.TrichromeZygotePreload">
+      android:zygotePreloadName="org.chromium.content.app.ZygotePreload">
     <activity  # DIFF-ANCHOR: ea1a94af
         android:name="com.google.android.gms.common.api.GoogleApiActivity"
         android:exported="false"
diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml
index 260bb164..e1987b18 100644
--- a/chrome/android/java/AndroidManifest.xml
+++ b/chrome/android/java/AndroidManifest.xml
@@ -177,7 +177,7 @@
         android:largeHeap="false"
         android:manageSpaceActivity="@string/manage_space_activity"
         android:supportsRtl="true"
-        android:zygotePreloadName="{{ zygote_preload_class }}"
+        android:zygotePreloadName="org.chromium.content.app.ZygotePreload"
         {% if backup_key is defined %}
         android:allowBackup="true"
         android:backupAgent="org.chromium.chrome.browser.ChromeBackupAgent"
diff --git a/chrome/android/java/res/layout/contextual_search_promo_view_revised.xml b/chrome/android/java/res/layout/contextual_search_promo_view_revised.xml
index 7651aaf..9045d769 100644
--- a/chrome/android/java/res/layout/contextual_search_promo_view_revised.xml
+++ b/chrome/android/java/res/layout/contextual_search_promo_view_revised.xml
@@ -66,7 +66,7 @@
                 android:layout_marginTop="16dp"
                 android:layout_marginBottom="16dp"
                 android:layout_marginEnd="16dp"
-                android:text="@string/contextual_search_turn_on_button"
+                android:text="@string/contextual_search_include_button"
                 style="@style/FilledButton.Flat" />
 
             <org.chromium.ui.widget.ButtonCompat
diff --git a/chrome/android/java/src/org/chromium/chrome/app/TrichromeZygotePreload.java b/chrome/android/java/src/org/chromium/chrome/app/TrichromeZygotePreload.java
deleted file mode 100644
index 4745eb4..0000000
--- a/chrome/android/java/src/org/chromium/chrome/app/TrichromeZygotePreload.java
+++ /dev/null
@@ -1,24 +0,0 @@
-// 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.
-
-package org.chromium.chrome.app;
-
-import android.content.pm.ApplicationInfo;
-
-import org.chromium.base.library_loader.LibraryLoader;
-import org.chromium.chrome.browser.ProductConfig;
-import org.chromium.content_public.app.ZygotePreload;
-
-/**
- * The {@link ZygotePreload} allowing to use the ModernLinker when running Trichrome.
- */
-public class TrichromeZygotePreload extends ZygotePreload {
-    @Override
-    public void doPreload(ApplicationInfo appInfo) {
-        // The ModernLinker is only needed when the App Zygote intends to create the RELRO region.
-        boolean useModernLinker = ProductConfig.USE_MODERN_LINKER
-                && !LibraryLoader.mainProcessIntendsToProvideRelroFd();
-        doPreloadCommon(appInfo, useModernLinker);
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/site_settings/ChromeSiteSettingsDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/site_settings/ChromeSiteSettingsDelegate.java
index e46cb4b6..9fb9dc5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/site_settings/ChromeSiteSettingsDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/site_settings/ChromeSiteSettingsDelegate.java
@@ -159,6 +159,8 @@
             case SiteSettingsCategory.Type.BLUETOOTH_SCANNING:
                 return CommandLine.getInstance().hasSwitch(
                         ContentSwitches.ENABLE_EXPERIMENTAL_WEB_PLATFORM_FEATURES);
+            case SiteSettingsCategory.Type.REQUEST_DESKTOP_SITE:
+                return ContentFeatureList.isEnabled(ContentFeatureList.REQUEST_DESKTOP_SITE_GLOBAL);
             case SiteSettingsCategory.Type.NFC:
                 return ContentFeatureList.isEnabled(ContentFeatureList.WEB_NFC);
             default:
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java
index 553416d..2cb2319 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java
@@ -58,6 +58,7 @@
 import org.chromium.components.security_state.SecurityStateModel;
 import org.chromium.components.url_formatter.UrlFormatter;
 import org.chromium.content_public.browser.ChildProcessImportance;
+import org.chromium.content_public.browser.ContentFeatureList;
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.content_public.browser.WebContentsAccessibility;
@@ -1637,17 +1638,18 @@
                 : getWebContents().getNavigationController().getUseDesktopUserAgent();
 
         // We only calculate the user agent when users did not manually choose one.
+        // TODO(crbug.com/1251794): Desktop site setting in app menu does not persist after restart.
         if (!mUserForcedUserAgent
-                && ChromeFeatureList.isEnabled(ChromeFeatureList.REQUEST_DESKTOP_SITE_FOR_TABLETS)
-                && ChromeFeatureList.getFieldTrialParamByFeatureAsBoolean(
-                        ChromeFeatureList.REQUEST_DESKTOP_SITE_FOR_TABLETS,
-                        REQUEST_DESKTOP_ENABLED_PARAM, false)) {
+                && ContentFeatureList.isEnabled(ContentFeatureList.REQUEST_DESKTOP_SITE_GLOBAL)) {
             // We only do the following logic to choose the desktop/mobile user agent if
             // 1. User never manually made a choice in app menu for requesting desktop site.
-            // 2. The browser is running in tablets.
-            boolean shouldRequestDesktopSite = TabUtils.isTabLargeEnoughForDesktopSite(this);
+            // 2. User enabled request desktop site in site settings.
+            Profile profile =
+                    IncognitoUtils.getProfileFromWindowAndroid(mWindowAndroid, isIncognito());
+            boolean shouldRequestDesktopSite = TabUtils.isDesktopSiteGlobalEnabled(profile);
 
             if (shouldRequestDesktopSite != currentRequestDesktopSite) {
+                // TODO(crbug.com/1243758): Confirm if a new histogram should be used.
                 RecordHistogram.recordBooleanHistogram(
                         "Android.RequestDesktopSite.UseDesktopUserAgent", shouldRequestDesktopSite);
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabUtils.java
index d0b0f32..3174c5c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabUtils.java
@@ -16,6 +16,9 @@
 import org.chromium.base.ApplicationStatus;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
+import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.components.browser_ui.site_settings.WebsitePreferenceBridge;
+import org.chromium.components.content_settings.ContentSettingsType;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.ui.base.DeviceFormFactor;
 import org.chromium.ui.base.WindowAndroid;
@@ -115,4 +118,16 @@
 
         return minWidthForDesktopSite <= windowWidth;
     }
+
+    /**
+     * Check if request desktop site global setting is enabled.
+     * @param profile The profile of the tab.
+     *        Content settings have separate storage for incognito profiles.
+     *        For site-specific exceptions the actual profile is needed.
+     * @return Whether the desktop site should be requested.
+     */
+    public static boolean isDesktopSiteGlobalEnabled(Profile profile) {
+        return WebsitePreferenceBridge.isCategoryEnabled(
+                profile, ContentSettingsType.REQUEST_DESKTOP_SITE);
+    }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SiteSettingsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SiteSettingsTest.java
index a170e39..8ecacbf 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SiteSettingsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SiteSettingsTest.java
@@ -1169,6 +1169,24 @@
     @Test
     @SmallTest
     @Feature({"Preferences"})
+    public void testAllowRequestDesktopSite() {
+        doTestSiteSettingPermissions("RequestDesktopSite",
+                SiteSettingsCategory.Type.REQUEST_DESKTOP_SITE,
+                ContentSettingsType.REQUEST_DESKTOP_SITE, true);
+    }
+
+    @Test
+    @SmallTest
+    @Feature({"Preferences"})
+    public void testBlockRequestDesktopSite() {
+        doTestSiteSettingPermissions("RequestDesktopSite",
+                SiteSettingsCategory.Type.REQUEST_DESKTOP_SITE,
+                ContentSettingsType.REQUEST_DESKTOP_SITE, false);
+    }
+
+    @Test
+    @SmallTest
+    @Feature({"Preferences"})
     @DisableIf.
     Build(message = "Flaky, see crbug.com/1170671", sdk_is_less_than = Build.VERSION_CODES.Q)
     public void testEmbargoedNotificationSiteSettings() throws Exception {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/WebsitePermissionsFetcherTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/WebsitePermissionsFetcherTest.java
index 1bd8974..3abc16eb 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/WebsitePermissionsFetcherTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/WebsitePermissionsFetcherTest.java
@@ -493,7 +493,7 @@
         // If the ContentSettingsType.NUM_TYPES value changes *and* a new value has been exposed on
         // Android, then please update this code block to include a test for your new type.
         // Otherwise, just update count in the assert.
-        Assert.assertEquals(75, ContentSettingsType.NUM_TYPES);
+        Assert.assertEquals(76, ContentSettingsType.NUM_TYPES);
         websitePreferenceBridge.addContentSettingException(
                 new ContentSettingException(ContentSettingsType.COOKIES, googleOrigin,
                         ContentSettingValues.DEFAULT, preferenceSource));
@@ -524,6 +524,9 @@
         websitePreferenceBridge.addContentSettingException(
                 new ContentSettingException(ContentSettingsType.AUTO_DARK_WEB_CONTENT, googleOrigin,
                         ContentSettingValues.DEFAULT, preferenceSource));
+        websitePreferenceBridge.addContentSettingException(
+                new ContentSettingException(ContentSettingsType.REQUEST_DESKTOP_SITE, googleOrigin,
+                        ContentSettingValues.DEFAULT, preferenceSource));
 
         // Add storage info.
         int storageSize = 256;
@@ -587,6 +590,9 @@
             Assert.assertEquals(Integer.valueOf(ContentSettingValues.DEFAULT),
                     site.getContentSetting(UNUSED_BROWSER_CONTEXT_HANDLE,
                             ContentSettingsType.AUTO_DARK_WEB_CONTENT));
+            Assert.assertEquals(Integer.valueOf(ContentSettingValues.DEFAULT),
+                    site.getContentSetting(UNUSED_BROWSER_CONTEXT_HANDLE,
+                            ContentSettingsType.REQUEST_DESKTOP_SITE));
 
             // Check storage info.
             ArrayList<StorageInfo> storageInfos = new ArrayList<>(site.getStorageInfo());
diff --git a/chrome/android/trichrome.gni b/chrome/android/trichrome.gni
index 5a97c2f5..d0de691 100644
--- a/chrome/android/trichrome.gni
+++ b/chrome/android/trichrome.gni
@@ -35,7 +35,6 @@
   "trichrome_library=$trichrome_library_package",
   "trichrome_certdigest=$trichrome_certdigest",
   "use32bitAbi=android:use32bitAbi=\"true\"",
-  "zygote_preload_class=org.chromium.chrome.app.TrichromeZygotePreload",
 ]
 
 trichrome_synchronized_proguard =
diff --git a/chrome/app/os_settings_strings.grdp b/chrome/app/os_settings_strings.grdp
index ff21446..5dff4b3 100644
--- a/chrome/app/os_settings_strings.grdp
+++ b/chrome/app/os_settings_strings.grdp
@@ -1223,7 +1223,7 @@
     Switch Access settings
   </message>
   <message name="IDS_SETTINGS_SWITCH_ACCESS_SETUP_GUIDE_LABEL" desc="Label for the button that opens the setup guide dialog for Switch Access.">
-    Rerun setup guide
+    Setup guide
   </message>
   <message name="IDS_SETTINGS_SWITCH_ASSIGNMENT_HEADING" desc="Heading for the settings section for Switch Access to assign switches to actions">
     Switch action assignment
@@ -1280,18 +1280,18 @@
     <ph name="DURATION">$1<ex>1.5</ex></ph>s
   </message>
   <message name="IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_DIALOG_TITLE" desc="A title for a dialog to assign a switch key to an action. Switch Access is an alternative input method designed for users with limited mobility, where the user has as little as one switch (for example, a button) to control the computer.">
-    Assign switch: <ph name="action">$1<ex>Select</ex></ph>
+    Assign switch for “<ph name="action">$1<ex>Select</ex></ph>”
   </message>
   <message name="IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_WAIT_FOR_KEY_PROMPT_NO_SWITCHES" desc="A message shown to ask a user to press a new key to be assigned to an action. No switches are currently assigned to this action. The user can assign multiple switches to this action. Switch Access is an alternative input method designed for users with limited mobility, where the user has as little as one switch (for example, a button) to control the computer.">
-    Press a switch to assign “<ph name="action">$1<ex>Select</ex></ph>”
-You can assign multiple switches to this action
+    Press a switch or keyboard key to assign it to “<ph name="action">$1<ex>Select</ex></ph>.”
+You can assign multiple switches to this action.
   </message>
   <message name="IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_WAIT_FOR_KEY_PROMPT_NO_SWITCHES_SETUP_GUIDE" desc="A message shown in the setup flow to ask a user to press a new key or external switch to be assigned to an action. No switches are currently assigned to this action. The user can assign multiple switches to this action. Switch Access is an alternative input method designed for users with limited mobility, where the user has as little as one switch (for example, a button) to control the computer.">
-    Press a switch or key to assign "<ph name="action">$1<ex>Select</ex></ph>"
+    Press a switch or keyboard key to assign it to “<ph name="action">$1<ex>Select</ex></ph>”
   </message>
   <message name="IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_WAIT_FOR_KEY_PROMPT_AT_LEAST_ONE_SWITCH" desc="A message shown to ask a user to press a key to be assigned to an action, or press an assigned switch to remove assignment. One or more switches are currently assigned to this action. Switch Access is an alternative input method designed for users with limited mobility, where the user has as little as one switch (for example, a button) to control the computer.">
-    Press a new switch to start assignment
-Press an assigned switch to remove assignment
+    Press a new switch or keyboard key to start assignment.
+Press an assigned switch or key to remove assignment.
   </message>
   <message name="IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_WAIT_FOR_CONFIRMATION_PROMPT" desc="A message shown to ask a user to confirm by pressing a switch key to be assigned to an action. Switch Access is an alternative input method designed for users with limited mobility, where the user has as little as one switch (for example, a button) to control the computer.">
       Press “<ph name="currentKey">$1<ex>backspace</ex></ph>” again to confirm assignment and <ph name="response">$2<ex>exit</ex></ph>
@@ -1309,10 +1309,10 @@
       Press “<ph name="currentKey">$1<ex>backspace</ex></ph>” again to remove assignment and <ph name="response">$2<ex>exit</ex></ph>
   </message>
   <message name="IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_WARN_NOT_CONFIRMED_PROMPT" desc="A message warning the user that the switch key pressed during confirmation did not match the initial switch key pressed. Switch Access is an alternative input method designed for users with limited mobility, where the user has as little as one switch (for example, a button) to control the computer.">
-      Keys do not match. Press any key to <ph name="response">$1<ex>exit</ex></ph>.
+      Keys don’t match. Press any key to <ph name="response">$1<ex>exit</ex></ph>.
   </message>
   <message name="IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_WARN_CANNOT_REMOVE_LAST_SELECT_SWITCH" desc="A message warning the user that they cannot remove the last switch for the Select action. The text for the 'Select' action should be the same as the text from IDS_SETTINGS_ASSIGN_SELECT_SWITCH_LABEL. Switch Access is an alternative input method designed for users with limited mobility, where the user has as little as one switch (for example, a button) to control the computer.">
-      Can’t remove the only switch assigned to Select. Press any key to <ph name="response">$1<ex>exit</ex></ph>.
+      Can’t remove the only switch assigned to “Select.” Press any key to <ph name="response">$1<ex>exit</ex></ph>.
   </message>
   <message name="IDS_SETTINGS_SWITCH_AND_DEVICE_TYPE" desc="Label describing a switch key and the type of device where the switch key exists. Switch Access is an alternative input method designed for users with limited mobility, where the user has as little as one switch (for example, a button) to control the computer.">
     <ph name="SWITCH">$1<ex>backspace</ex></ph> (<ph name="DEVICE_TYPE">$2<ex>USB</ex></ph>)
@@ -1345,16 +1345,16 @@
     No switch has been assigned yet
   </message>
   <message name="IDS_SETTINGS_NO_SWITCHES_ASSIGNED_SETUP_GUIDE" desc="A label indicating no switches are assigned to an action, from within the setup guide. Switch Access is an alternative input method designed for users with limited mobility, where the user has as little as one switch (for example, a button) to control the computer.">
-    No switch or key has been assigned yet
+    Switch hasn’t been assigned yet
   </message>
   <message name="IDS_SETTINGS_SWITCH_ACCESS_DIALOG_EXIT" desc="The label of the button to exit one of the switch access dialogs without making any changes. Switch Access is an alternative input method designed for users with limited mobility, where the user has as little as one switch (for example, a button) to control the computer.">
     Exit
   </message>
   <message name="IDS_SETTINGS_SWITCH_ACCESS_SETUP_GUIDE_WARNING_DIALOG_TITLE" desc="The title for the dialog explaining that re-running the setup guide will clear all switch assignments. Switch Access is an alternative input method designed for users with limited mobility, where the user has as little as one switch (for example, a button) to control the computer.">
-    Clear all switch assignments
+    Start Switch Access setup?
   </message>
   <message name="IDS_SETTINGS_SWITCH_ACCESS_SETUP_GUIDE_WARNING_DIALOG_MESSAGE" desc="The message explaining that re-running the setup guide will clear all switch assignments. Switch Access is an alternative input method designed for users with limited mobility, where the user has as little as one switch (for example, a button) to control the computer.">
-    Re-running the setup guide will clear your assigned switches. Do you want to continue?
+    Your currently assigned switches will be cleared
   </message>
   <message name="IDS_SETTINGS_SWITCH_ACCESS_SETUP_INTRO_TITLE" desc="The title for the first page of the Switch Access setup guide. Switch Access is an alternative input method designed for users with limited mobility, where the user has as little as one switch (for example, a button) to control the computer.">
     Switch Access setup guide
@@ -1363,34 +1363,34 @@
     To get started, please make sure your USB or Bluetooth switch is connected to your Chromebook. You can also use keyboard keys.
   </message>
   <message name="IDS_SETTINGS_SWITCH_ACCESS_SETUP_ASSIGN_SELECT_TITLE" desc="The title for the page of the Switch Access setup guide where the user assigns a switch to perform the action select, which selects the element onscreen currently surrounded by the focus ring. Switch Access is an alternative input method designed for users with limited mobility, where the user has as little as one switch (for example, a button) to control the computer.">
-    Assign switch: Select
+    Assign switch for “Select”
   </message>
   <message name="IDS_SETTINGS_SWITCH_ACCESS_SETUP_AUTO_SCAN_ENABLED_TITLE" desc="The title for the page of the Switch Access setup guide that informs the user that auto-scan has been enabled, meaning that the focused item will change periodically with no additional input. Switch Access is an alternative input method designed for users with limited mobility, where the user has as little as one switch (for example, a button) to control the computer.">
-    Auto-scan enabled
+    Move between items automatically
   </message>
   <message name="IDS_SETTINGS_SWITCH_ACCESS_SETUP_AUTO_SCAN_ENABLED_EXPLANATION" desc="The message displayed in the Switch Access setup guide explaining how the auto-scan behavior works. Switch Access is an alternative input method designed for users with limited mobility, where the user has as little as one switch (for example, a button) to control the computer.">
-    Auto-scan will automatically cycle through and focus on items on the screen. When an item is focused, press the "Select" key you just assigned to activate it.
+    Auto-scan lets you move through items on the screen automatically. When an item is highlighted, press “Select” to activate it.
   </message>
   <message name="IDS_SETTINGS_SWITCH_ACCESS_SETUP_AUTO_SCAN_ENABLED_DIRECTIONS" desc="The message displayed in the Switch Access setup guide after auto-scan has been enabled, informing them how to proceed. Switch Access is an alternative input method designed for users with limited mobility, where the user has as little as one switch (for example, a button) to control the computer.">
-    Activate the Next button to continue the setup or the Previous button to change the "Select" switch assignment.
+    You can go back to change the assignment for “Select.” You can always turn off auto-scan in Settings.
   </message>
   <message name="IDS_SETTINGS_SWITCH_ACCESS_SETUP_CHOOSE_SWITCH_COUNT_TITLE" desc="The title for the page of the Switch Access setup guide where the user selects the number of switches they are going to use. Switch Access is an alternative input method designed for users with limited mobility, where the user has as little as one switch (for example, a button) to control the computer.">
-    Do you want to assign additional switches?
+    Assign additional switches?
   </message>
   <message name="IDS_SETTINGS_SWITCH_ACCESS_SETUP_CHOOSE_1_SWITCH" desc="The label for the option to use only one switch (already assigned), within the Switch Access setup guide. Switch Access is an alternative input method designed for users with limited mobility, where the user has as little as one switch (for example, a button) to control the computer.">
-    I only use one switch
+    No, stay with 1 switch
   </message>
   <message name="IDS_SETTINGS_SWITCH_ACCESS_SETUP_CHOOSE_2_SWITCHES" desc="The label for the option to use two switches (with one already assigned), within the Switch Access setup guide. Switch Access is an alternative input method designed for users with limited mobility, where the user has as little as one switch (for example, a button) to control the computer.">
-    Assign one more switch
+    Assign 1 more switch
   </message>
   <message name="IDS_SETTINGS_SWITCH_ACCESS_SETUP_CHOOSE_2_SWITCHES_DESCRIPTION" desc="The description for the option to use two switches (with one already assigned), within the Switch Access setup guide. It details that the second switch will be 'next' and move focus to the next item onscreen. Switch Access is an alternative input method designed for users with limited mobility, where the user has as little as one switch (for example, a button) to control the computer.">
-    Assign this switch to "Next" to move to the next item on the page
+    Use “Next” to move forward on the screen
   </message>
   <message name="IDS_SETTINGS_SWITCH_ACCESS_SETUP_CHOOSE_3_SWITCHES" desc="The label for the option to use three switches (with one already assigned), within the Switch Access setup guide. Switch Access is an alternative input method designed for users with limited mobility, where the user has as little as one switch (for example, a button) to control the computer.">
-    Assign two more switches
+    Assign 2 more switches
   </message>
   <message name="IDS_SETTINGS_SWITCH_ACCESS_SETUP_CHOOSE_3_SWITCHES_DESCRIPTION" desc="The description for the option to use three switches (with one already assigned), within the Switch Access setup guide. It details that the switches will be 'next' and 'previous', and used for navigating the items onscreen. Switch Access is an alternative input method designed for users with limited mobility, where the user has as little as one switch (for example, a button) to control the computer.">
-    Assign them to "Next" and "Previous" to move between items on the page
+    Use “Next” and “Previous” to move between items on the screen
   </message>
   <message name="IDS_SETTINGS_SWITCH_ACCESS_SETUP_AUTO_SCAN_SPEED_TITLE" desc="The title for the page of the Switch Access setup guide where the user sets the speed of auto-scan, which automatically advances the focus between elements at a fixed interval. Switch Access is an alternative input method designed for users with limited mobility, where the user has as little as one switch (for example, a button) to control the computer.">
     Auto-scan speed
@@ -1399,22 +1399,22 @@
     Choose how long the highlight should stay on each item
   </message>
   <message name="IDS_SETTINGS_SWITCH_ACCESS_SETUP_ASSIGN_NEXT_TITLE" desc="The title for the page of the Switch Access setup guide where the user assigns a switch to perform the action next, which advances the focus ring to the next element onscreen. Switch Access is an alternative input method designed for users with limited mobility, where the user has as little as one switch (for example, a button) to control the computer.">
-    Assign switch: Next
+    Assign switch for “Next”
   </message>
   <message name="IDS_SETTINGS_SWITCH_ACCESS_SETUP_ASSIGN_PREVIOUS_TITLE" desc="The title for the page of the Switch Access setup guide where the user assigns a switch to perform the action previous, which moves the focus ring to the previous element onscreen. Switch Access is an alternative input method designed for users with limited mobility, where the user has as little as one switch (for example, a button) to control the computer.">
-    Assign switch: Previous
+    Assign switch for “Previous”
   </message>
   <message name="IDS_SETTINGS_SWITCH_ACCESS_SETUP_CLOSING_TITLE" desc="The title for the final page of the Switch Access setup guide, which informs the user that setup is complete and provides some final information. Switch Access is an alternative input method designed for users with limited mobility, where the user has as little as one switch (for example, a button) to control the computer.">
-    You're all set!
+    You’re all set!
   </message>
   <message name="IDS_SETTINGS_SWITCH_ACCESS_SETUP_CLOSING_AUTO_SCAN_INSTRUCTIONS" desc="Instructions for how to close the Switch Access setup guide using Switch Access with auto-scan enabled. Switch Access is an alternative input method designed for users with limited mobility where the user has as little as one switch (for example, a button) to control the computer. Auto-scan is a feature of Switch Access where focus moves from one element to the next at a set interval automatically, so the user only has to select the element when it is highlighted.">
     Press your switch when the focus is on the Done button to close the guide.
   </message>
   <message name="IDS_SETTINGS_SWITCH_ACCESS_SETUP_CLOSING_MANUAL_SCAN_INSTRUCTIONS" desc="Instructions for how to close the Switch Access setup guide using Switch Access with at least one switch assigned to navigation. Switch Access is an alternative input method designed for users with limited mobility where the user has as little as one switch (for example, a button) to control the computer. Auto-scan is a feature of Switch Access where focus moves from one element to the next at a set interval automatically, so the user only has to select the element when it is highlighted.">
-    Now that you have more switches to navigate, auto-scan has been turned off. Navigate to the Done button and press the Select switch to close the guide.
+    Since you set up multiple switches, auto-scan has been turned off.
   </message>
   <message name="IDS_SETTINGS_SWITCH_ACCESS_SETUP_CLOSING_INFO" desc="Final advice on changing the settings for Switch Access after the Switch Access setup guide has been closed. Switch Access is an alternative input method designed for users with limited mobility where the user has as little as one switch (for example, a button) to control the computer.">
-    You can always change additional settings or open the setup guide again from Switch Access settings.
+    You can always change your settings or open the setup guide again from Switch Access settings.
   </message>
   <message name="IDS_SETTINGS_SWITCH_ACCESS_SETUP_AUTO_SCAN_SLOWER" desc="The label on the button which slows the speed of Switch Access' auto-scan, which automatically advances the focus between elements at a fixed interval. Switch Access is an alternative input method designed for users with limited mobility, where the user has as little as one switch (for example, a button) to control the computer.">
     Slower
@@ -1432,7 +1432,7 @@
     Previous
   </message>
   <message name="IDS_SETTINGS_SWITCH_ACCESS_SETUP_START_OVER" desc="A button in the Switch Access setup guide to restart from the beginning, and reconfigure any/all of the settings. Switch Access is an alternative input method designed for users with limited mobility, where the user has as little as one switch (for example, a button) to control the computer.">
-    Start over setup
+    Redo setup
   </message>
   <message name="IDS_SETTINGS_SWITCH_ACCESS_SETUP_DONE" desc="A button in the Switch Access setup guide to confirm that the user has finished configuring their settings and would like to close the dialog. Switch Access is an alternative input method designed for users with limited mobility, where the user has as little as one switch (for example, a button) to control the computer.">
     Done
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_NO_SWITCHES_ASSIGNED_SETUP_GUIDE.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_NO_SWITCHES_ASSIGNED_SETUP_GUIDE.png.sha1
index 2235e07..44caa04 100644
--- a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_NO_SWITCHES_ASSIGNED_SETUP_GUIDE.png.sha1
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_NO_SWITCHES_ASSIGNED_SETUP_GUIDE.png.sha1
@@ -1 +1 @@
-e017a296c8e2e5a577514802dff88cf9f895e8ce
\ No newline at end of file
+b8c83189c7182b46c1cc6e09b750d5f426528902
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_DIALOG_TITLE.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_DIALOG_TITLE.png.sha1
index 8cabbacb..ea419b8 100644
--- a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_DIALOG_TITLE.png.sha1
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_DIALOG_TITLE.png.sha1
@@ -1 +1 @@
-b14090832131315ecb83e68967b8c2a3f1daac9a
\ No newline at end of file
+3436150acf556251294401811f0aa99d19de135c
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_WAIT_FOR_CONFIRMATION_PROMPT.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_WAIT_FOR_CONFIRMATION_PROMPT.png.sha1
index 786d9232..4202d96 100644
--- a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_WAIT_FOR_CONFIRMATION_PROMPT.png.sha1
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_WAIT_FOR_CONFIRMATION_PROMPT.png.sha1
@@ -1 +1 @@
-8ec28705408deeb425ea2bcfce11174cb31f4122
\ No newline at end of file
+b64c7303529045423dcc89381ef7d5ca98cfb91e
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_WAIT_FOR_KEY_PROMPT_AT_LEAST_ONE_SWITCH.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_WAIT_FOR_KEY_PROMPT_AT_LEAST_ONE_SWITCH.png.sha1
index b44f93e..65e7a951 100644
--- a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_WAIT_FOR_KEY_PROMPT_AT_LEAST_ONE_SWITCH.png.sha1
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_WAIT_FOR_KEY_PROMPT_AT_LEAST_ONE_SWITCH.png.sha1
@@ -1 +1 @@
-d59a6c671a5441bfb2264307054a4af5da217eb0
\ No newline at end of file
+b788eab086eb1af7f3cf5b40f8ed453572052e81
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_WAIT_FOR_KEY_PROMPT_NO_SWITCHES.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_WAIT_FOR_KEY_PROMPT_NO_SWITCHES.png.sha1
index c5405d346..f6368b1 100644
--- a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_WAIT_FOR_KEY_PROMPT_NO_SWITCHES.png.sha1
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_WAIT_FOR_KEY_PROMPT_NO_SWITCHES.png.sha1
@@ -1 +1 @@
-15ee6bb5dc6f28957f3927ca92d46d8dab694a8c
\ No newline at end of file
+5090abc445e337f385b3c15f7c7f8c8fb63ee424
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_WAIT_FOR_KEY_PROMPT_NO_SWITCHES_SETUP_GUIDE.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_WAIT_FOR_KEY_PROMPT_NO_SWITCHES_SETUP_GUIDE.png.sha1
index 2235e07..c718b1b 100644
--- a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_WAIT_FOR_KEY_PROMPT_NO_SWITCHES_SETUP_GUIDE.png.sha1
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_WAIT_FOR_KEY_PROMPT_NO_SWITCHES_SETUP_GUIDE.png.sha1
@@ -1 +1 @@
-e017a296c8e2e5a577514802dff88cf9f895e8ce
\ No newline at end of file
+e49883bdd23e145c409bed81835fb885a97ff814
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_WARN_CANNOT_REMOVE_LAST_SELECT_SWITCH.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_WARN_CANNOT_REMOVE_LAST_SELECT_SWITCH.png.sha1
index 783c81fa..6f89201b 100644
--- a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_WARN_CANNOT_REMOVE_LAST_SELECT_SWITCH.png.sha1
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_WARN_CANNOT_REMOVE_LAST_SELECT_SWITCH.png.sha1
@@ -1 +1 @@
-bdf360c94294cf0f89939e3aed405ae28aec1bcb
\ No newline at end of file
+6907bd0df3f24ae73bf08e5ca372e80936d7940e
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_WARN_NOT_CONFIRMED_PROMPT.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_WARN_NOT_CONFIRMED_PROMPT.png.sha1
index e24897e..2b3439a 100644
--- a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_WARN_NOT_CONFIRMED_PROMPT.png.sha1
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_WARN_NOT_CONFIRMED_PROMPT.png.sha1
@@ -1 +1 @@
-9fc79913e1446ecd43c53cb00fec04c981ae5235
\ No newline at end of file
+6e6c9c4cc37c00096bac1af23220ddbedde0e7d0
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_ASSIGN_NEXT_TITLE.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_ASSIGN_NEXT_TITLE.png.sha1
index df5b9cc..cd498bb 100644
--- a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_ASSIGN_NEXT_TITLE.png.sha1
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_ASSIGN_NEXT_TITLE.png.sha1
@@ -1 +1 @@
-40fd647de97b53066fe66380b2a018a60a9c5303
\ No newline at end of file
+54b6a768c4bf582363ab3ebc8a6795dba35343bb
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_ASSIGN_PREVIOUS_TITLE.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_ASSIGN_PREVIOUS_TITLE.png.sha1
index 1294c56..54589c3 100644
--- a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_ASSIGN_PREVIOUS_TITLE.png.sha1
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_ASSIGN_PREVIOUS_TITLE.png.sha1
@@ -1 +1 @@
-348e56133d39e3353c1274da49a675f84880fcc2
\ No newline at end of file
+26a4ee016c5d58f11a256e4c0b57f1f1db29dd7b
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_ASSIGN_SELECT_TITLE.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_ASSIGN_SELECT_TITLE.png.sha1
index 9d95e9f1..3ad74585 100644
--- a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_ASSIGN_SELECT_TITLE.png.sha1
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_ASSIGN_SELECT_TITLE.png.sha1
@@ -1 +1 @@
-6ee5a605e083d66a43fef865a5ed5b9647abac1e
\ No newline at end of file
+4daa170ebcabaf1a48beaaa6f495f8cbc60f49ec
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_AUTO_SCAN_ENABLED_DIRECTIONS.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_AUTO_SCAN_ENABLED_DIRECTIONS.png.sha1
index e0468ff..857a544 100644
--- a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_AUTO_SCAN_ENABLED_DIRECTIONS.png.sha1
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_AUTO_SCAN_ENABLED_DIRECTIONS.png.sha1
@@ -1 +1 @@
-ecf9276430b5eb12e2c6a391e68a7b5a87fe4326
\ No newline at end of file
+cdd25e5fd14897632302226582d378a0847337f6
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_AUTO_SCAN_ENABLED_EXPLANATION.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_AUTO_SCAN_ENABLED_EXPLANATION.png.sha1
index e0468ff..029f6edc 100644
--- a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_AUTO_SCAN_ENABLED_EXPLANATION.png.sha1
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_AUTO_SCAN_ENABLED_EXPLANATION.png.sha1
@@ -1 +1 @@
-ecf9276430b5eb12e2c6a391e68a7b5a87fe4326
\ No newline at end of file
+efdb0b57cc499d6d05c80ae91403282a0e28f9d1
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_AUTO_SCAN_ENABLED_TITLE.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_AUTO_SCAN_ENABLED_TITLE.png.sha1
index e0468ff..f2899a4 100644
--- a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_AUTO_SCAN_ENABLED_TITLE.png.sha1
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_AUTO_SCAN_ENABLED_TITLE.png.sha1
@@ -1 +1 @@
-ecf9276430b5eb12e2c6a391e68a7b5a87fe4326
\ No newline at end of file
+f3b7718dce2c92aa92343f00281052469c4ca6cb
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_CHOOSE_1_SWITCH.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_CHOOSE_1_SWITCH.png.sha1
index 03861548..0a51c23 100644
--- a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_CHOOSE_1_SWITCH.png.sha1
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_CHOOSE_1_SWITCH.png.sha1
@@ -1 +1 @@
-518a0a315e5f1625dd8175ff577c0a113fb2e019
\ No newline at end of file
+602f1400a5f6efd503724b40257c1412dc35074e
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_CHOOSE_2_SWITCHES.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_CHOOSE_2_SWITCHES.png.sha1
index 03861548..7431089 100644
--- a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_CHOOSE_2_SWITCHES.png.sha1
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_CHOOSE_2_SWITCHES.png.sha1
@@ -1 +1 @@
-518a0a315e5f1625dd8175ff577c0a113fb2e019
\ No newline at end of file
+dd93073c3f425e664f79da84d2bde8efe322d696
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_CHOOSE_2_SWITCHES_DESCRIPTION.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_CHOOSE_2_SWITCHES_DESCRIPTION.png.sha1
index 03861548..63c9867 100644
--- a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_CHOOSE_2_SWITCHES_DESCRIPTION.png.sha1
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_CHOOSE_2_SWITCHES_DESCRIPTION.png.sha1
@@ -1 +1 @@
-518a0a315e5f1625dd8175ff577c0a113fb2e019
\ No newline at end of file
+525d3016e4561003b44e60f3521d16326eb86db6
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_CHOOSE_3_SWITCHES.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_CHOOSE_3_SWITCHES.png.sha1
index 03861548..c48f8ae 100644
--- a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_CHOOSE_3_SWITCHES.png.sha1
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_CHOOSE_3_SWITCHES.png.sha1
@@ -1 +1 @@
-518a0a315e5f1625dd8175ff577c0a113fb2e019
\ No newline at end of file
+2a4d3241ab489d2f094a9c65c525c2f81eee103e
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_CHOOSE_3_SWITCHES_DESCRIPTION.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_CHOOSE_3_SWITCHES_DESCRIPTION.png.sha1
index 03861548..ea65969a 100644
--- a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_CHOOSE_3_SWITCHES_DESCRIPTION.png.sha1
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_CHOOSE_3_SWITCHES_DESCRIPTION.png.sha1
@@ -1 +1 @@
-518a0a315e5f1625dd8175ff577c0a113fb2e019
\ No newline at end of file
+3591ffb7958f0bf434dfa3df0afed9b53f46c7be
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_CHOOSE_SWITCH_COUNT_TITLE.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_CHOOSE_SWITCH_COUNT_TITLE.png.sha1
index 03861548..d4385bfb 100644
--- a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_CHOOSE_SWITCH_COUNT_TITLE.png.sha1
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_CHOOSE_SWITCH_COUNT_TITLE.png.sha1
@@ -1 +1 @@
-518a0a315e5f1625dd8175ff577c0a113fb2e019
\ No newline at end of file
+f8d5521b88234d0cfeadb96f20f83842411edd9f
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_CLOSING_INFO.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_CLOSING_INFO.png.sha1
index 7208493..d3edeb5 100644
--- a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_CLOSING_INFO.png.sha1
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_CLOSING_INFO.png.sha1
@@ -1 +1 @@
-a36cf042e637d759bb8c9e067aa43561c1ff0874
\ No newline at end of file
+22002ea6e4d96e54a8842db6de37222490a4253c
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_CLOSING_MANUAL_SCAN_INSTRUCTIONS.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_CLOSING_MANUAL_SCAN_INSTRUCTIONS.png.sha1
index 3e764b1..d3edeb5 100644
--- a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_CLOSING_MANUAL_SCAN_INSTRUCTIONS.png.sha1
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_CLOSING_MANUAL_SCAN_INSTRUCTIONS.png.sha1
@@ -1 +1 @@
-0d19c6bca00cf652d3e5f25e3a76cd1f71ad91ab
\ No newline at end of file
+22002ea6e4d96e54a8842db6de37222490a4253c
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_CLOSING_TITLE.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_CLOSING_TITLE.png.sha1
index 7208493..bcb215d 100644
--- a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_CLOSING_TITLE.png.sha1
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_CLOSING_TITLE.png.sha1
@@ -1 +1 @@
-a36cf042e637d759bb8c9e067aa43561c1ff0874
\ No newline at end of file
+148d7cfd6e81f40c820a8a945806d93a0ee81651
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_GUIDE_LABEL.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_GUIDE_LABEL.png.sha1
index 3b37878..1ebb3a4 100644
--- a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_GUIDE_LABEL.png.sha1
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_GUIDE_LABEL.png.sha1
@@ -1 +1 @@
-d8184769d6beacadd9ba37084523a4f518d54f4c
\ No newline at end of file
+21d02ab412938ffbb608190b1bb6a39559fb25b0
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_GUIDE_WARNING_DIALOG_MESSAGE.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_GUIDE_WARNING_DIALOG_MESSAGE.png.sha1
index a2f7ddb9..2dfa293f 100644
--- a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_GUIDE_WARNING_DIALOG_MESSAGE.png.sha1
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_GUIDE_WARNING_DIALOG_MESSAGE.png.sha1
@@ -1 +1 @@
-1513097c75f4f9def027f2e564fb690b30e99d75
\ No newline at end of file
+ea9dc1c3961c29d7e4729de5b53ceda1405fc7b1
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_GUIDE_WARNING_DIALOG_TITLE.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_GUIDE_WARNING_DIALOG_TITLE.png.sha1
index a2f7ddb9..543f014 100644
--- a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_GUIDE_WARNING_DIALOG_TITLE.png.sha1
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_GUIDE_WARNING_DIALOG_TITLE.png.sha1
@@ -1 +1 @@
-1513097c75f4f9def027f2e564fb690b30e99d75
\ No newline at end of file
+9c9f7d9acc7b037adf728411d08f185ada19996d
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_START_OVER.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_START_OVER.png.sha1
index 7208493..54141b26 100644
--- a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_START_OVER.png.sha1
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SWITCH_ACCESS_SETUP_START_OVER.png.sha1
@@ -1 +1 @@
-a36cf042e637d759bb8c9e067aa43561c1ff0874
\ No newline at end of file
+eb65f373d3405e9388b5a6647ec955c7876702cd
\ No newline at end of file
diff --git a/chrome/browser/apps/app_service/app_service_proxy_base.cc b/chrome/browser/apps/app_service/app_service_proxy_base.cc
index fe21ff7..c59eb7ff 100644
--- a/chrome/browser/apps/app_service/app_service_proxy_base.cc
+++ b/chrome/browser/apps/app_service/app_service_proxy_base.cc
@@ -468,6 +468,35 @@
   }
 }
 
+void AppServiceProxyBase::SetSupportedLinksPreference(
+    const std::string& app_id) {
+  DCHECK(!app_id.empty());
+  if (!app_service_.is_connected()) {
+    return;
+  }
+
+  std::vector<apps::mojom::IntentFilterPtr> filters;
+  AppRegistryCache().ForOneApp(app_id, [&filters](const AppUpdate& app) {
+    for (auto& filter : app.IntentFilters()) {
+      if (apps_util::IsSupportedLink(filter)) {
+        filters.push_back(std::move(filter));
+      }
+    }
+  });
+
+  app_service_->SetSupportedLinksPreference(
+      app_registry_cache_.GetAppType(app_id), app_id, std::move(filters));
+}
+
+void AppServiceProxyBase::RemoveSupportedLinksPreference(
+    const std::string& app_id) {
+  DCHECK(!app_id.empty());
+  if (app_service_.is_connected()) {
+    app_service_->RemoveSupportedLinksPreference(
+        app_registry_cache_.GetAppType(app_id), app_id);
+  }
+}
+
 void AppServiceProxyBase::SetWindowMode(const std::string& app_id,
                                         apps::mojom::WindowMode window_mode) {
   if (app_service_.is_connected()) {
diff --git a/chrome/browser/apps/app_service/app_service_proxy_base.h b/chrome/browser/apps/app_service/app_service_proxy_base.h
index ef044db..4dc2d50 100644
--- a/chrome/browser/apps/app_service/app_service_proxy_base.h
+++ b/chrome/browser/apps/app_service/app_service_proxy_base.h
@@ -216,6 +216,16 @@
   void AddPreferredApp(const std::string& app_id,
                        const apps::mojom::IntentPtr& intent);
 
+  // Sets |app_id| as the preferred app for all of its supported links ('view'
+  // intent filters with a scheme and host). Any existing preferred apps for
+  // those links will have all their supported links unset, as if
+  // RemoveSupportedLinksPreference was called for that app.
+  void SetSupportedLinksPreference(const std::string& app_id);
+
+  // Removes all supported link filters from the preferred app list for
+  // |app_id|.
+  void RemoveSupportedLinksPreference(const std::string& app_id);
+
   void SetWindowMode(const std::string& app_id,
                      apps::mojom::WindowMode window_mode);
 
@@ -362,8 +372,9 @@
   bool is_using_testing_profile_ = false;
   base::OnceClosure dialog_created_callback_;
 
-  FRIEND_TEST_ALL_PREFIXES(AppServiceProxyTest,
-                           PreferredAppsUpdatedOnUninstall);
+  FRIEND_TEST_ALL_PREFIXES(AppServiceProxyPreferredAppsTest,
+                           UpdatedOnUninstall);
+  FRIEND_TEST_ALL_PREFIXES(AppServiceProxyPreferredAppsTest, SetPreferredApp);
 };
 
 }  // namespace apps
diff --git a/chrome/browser/apps/app_service/app_service_proxy_lacros.cc b/chrome/browser/apps/app_service/app_service_proxy_lacros.cc
index 8b276b55..64f256a 100644
--- a/chrome/browser/apps/app_service/app_service_proxy_lacros.cc
+++ b/chrome/browser/apps/app_service/app_service_proxy_lacros.cc
@@ -11,6 +11,7 @@
 #include "base/containers/contains.h"
 #include "base/debug/dump_without_crashing.h"
 #include "base/location.h"
+#include "base/notreached.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/chromeos_buildflags.h"
 #include "chrome/browser/apps/app_service/app_icon_source.h"
@@ -435,6 +436,16 @@
   NOTIMPLEMENTED();
 }
 
+void AppServiceProxyLacros::SetSupportedLinksPreference(
+    const std::string& app_id) {
+  NOTIMPLEMENTED();
+}
+
+void AppServiceProxyLacros::RemoveSupportedLinksPreference(
+    const std::string& app_id) {
+  NOTIMPLEMENTED();
+}
+
 void AppServiceProxyLacros::SetWindowMode(const std::string& app_id,
                                           apps::mojom::WindowMode window_mode) {
   NOTIMPLEMENTED();
diff --git a/chrome/browser/apps/app_service/app_service_proxy_lacros.h b/chrome/browser/apps/app_service/app_service_proxy_lacros.h
index 9bd1026..81a7771 100644
--- a/chrome/browser/apps/app_service/app_service_proxy_lacros.h
+++ b/chrome/browser/apps/app_service/app_service_proxy_lacros.h
@@ -217,6 +217,16 @@
   void AddPreferredApp(const std::string& app_id,
                        const apps::mojom::IntentPtr& intent);
 
+  // Sets |app_id| as the preferred app for all of its supported links ('view'
+  // intent filters with a scheme and host). Any existing preferred apps for
+  // those links will have all their supported links unset, as if
+  // RemoveSupportedLinksPreference was called for that app.
+  void SetSupportedLinksPreference(const std::string& app_id);
+
+  // Removes all supported link filters from the preferred app list for
+  // |app_id|.
+  void RemoveSupportedLinksPreference(const std::string& app_id);
+
   void SetWindowMode(const std::string& app_id,
                      apps::mojom::WindowMode window_mode);
 
diff --git a/chrome/browser/apps/app_service/app_service_proxy_unittest.cc b/chrome/browser/apps/app_service/app_service_proxy_unittest.cc
index d05d7c9..144e56c 100644
--- a/chrome/browser/apps/app_service/app_service_proxy_unittest.cc
+++ b/chrome/browser/apps/app_service/app_service_proxy_unittest.cc
@@ -14,6 +14,7 @@
 #include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/services/app_service/public/cpp/intent_filter_util.h"
+#include "components/services/app_service/public/cpp/intent_test_util.h"
 #include "components/services/app_service/public/cpp/intent_util.h"
 #include "components/services/app_service/public/cpp/publisher_base.h"
 #include "components/services/app_service/public/mojom/types.mojom.h"
@@ -243,34 +244,44 @@
 }
 
 #if !BUILDFLAG(IS_CHROMEOS_LACROS)
-TEST_F(AppServiceProxyTest, PreferredAppsUpdatedOnUninstall) {
+class AppServiceProxyPreferredAppsTest : public AppServiceProxyTest {
+ public:
+  void SetUp() override {
+    proxy_ = AppServiceProxyFactory::GetForProfile(&profile_);
+
+    auto* const provider = web_app::FakeWebAppProvider::Get(&profile_);
+    provider->SkipAwaitingExtensionSystem();
+    web_app::test::AwaitStartWebAppProviderAndSubsystems(&profile_);
+  }
+
+  AppServiceProxy* proxy() { return proxy_; }
+
+ private:
+  TestingProfile profile_;
+  AppServiceProxy* proxy_;
+};
+
+TEST_F(AppServiceProxyPreferredAppsTest, UpdatedOnUninstall) {
   constexpr char kTestAppId[] = "foo";
   const GURL kTestUrl = GURL("https://www.example.com/");
 
-  TestingProfile profile;
-  auto* proxy = AppServiceProxyFactory::GetForProfile(&profile);
-
-  auto* const provider = web_app::FakeWebAppProvider::Get(&profile);
-  provider->SkipAwaitingExtensionSystem();
-  web_app::test::AwaitStartWebAppProviderAndSubsystems(&profile);
-
   // Install an app and set it as preferred for a URL.
   {
     std::vector<mojom::AppPtr> apps;
     mojom::AppPtr app = PublisherBase::MakeApp(
-        mojom::AppType::kBuiltIn, kTestAppId, mojom::Readiness::kReady,
-        "Test App", mojom::InstallSource::kUser);
+        mojom::AppType::kWeb, kTestAppId, mojom::Readiness::kReady, "Test App",
+        mojom::InstallSource::kUser);
     app->intent_filters.push_back(
         apps_util::CreateIntentFilterForUrlScope(kTestUrl));
     apps.push_back(std::move(app));
 
-    proxy->OnApps(std::move(apps), mojom::AppType::kBuiltIn,
-                  /*should_notify_initialized=*/false);
-    proxy->AddPreferredApp(kTestAppId, kTestUrl);
-    proxy->FlushMojoCallsForTesting();
+    proxy()->OnApps(std::move(apps), mojom::AppType::kWeb,
+                    /*should_notify_initialized=*/false);
+    proxy()->AddPreferredApp(kTestAppId, kTestUrl);
+    proxy()->FlushMojoCallsForTesting();
 
     absl::optional<std::string> preferred_app =
-        proxy->PreferredApps().FindPreferredAppForUrl(kTestUrl);
+        proxy()->PreferredApps().FindPreferredAppForUrl(kTestUrl);
     ASSERT_EQ(preferred_app, kTestAppId);
   }
 
@@ -278,17 +289,17 @@
   {
     std::vector<mojom::AppPtr> apps;
     mojom::AppPtr app = mojom::App::New();
-    app->app_type = mojom::AppType::kBuiltIn;
+    app->app_type = mojom::AppType::kWeb;
     app->app_id = kTestAppId;
     app->last_launch_time = base::Time();
     apps.push_back(std::move(app));
 
-    proxy->OnApps(std::move(apps), mojom::AppType::kBuiltIn,
-                  /*should_notify_initialized=*/false);
-    proxy->FlushMojoCallsForTesting();
+    proxy()->OnApps(std::move(apps), mojom::AppType::kWeb,
+                    /*should_notify_initialized=*/false);
+    proxy()->FlushMojoCallsForTesting();
 
     absl::optional<std::string> preferred_app =
-        proxy->PreferredApps().FindPreferredAppForUrl(kTestUrl);
+        proxy()->PreferredApps().FindPreferredAppForUrl(kTestUrl);
     ASSERT_EQ(preferred_app, kTestAppId);
   }
 
@@ -296,19 +307,84 @@
   {
     std::vector<mojom::AppPtr> apps;
     mojom::AppPtr app = mojom::App::New();
-    app->app_type = mojom::AppType::kBuiltIn;
+    app->app_type = mojom::AppType::kWeb;
     app->app_id = kTestAppId;
     app->readiness = mojom::Readiness::kUninstalledByUser;
     apps.push_back(std::move(app));
 
-    proxy->OnApps(std::move(apps), mojom::AppType::kBuiltIn,
-                  /*should_notify_initialized=*/false);
-    proxy->FlushMojoCallsForTesting();
+    proxy()->OnApps(std::move(apps), mojom::AppType::kWeb,
+                    /*should_notify_initialized=*/false);
+    proxy()->FlushMojoCallsForTesting();
 
     // TODO(crbug.com/1247944): Once removals are synced back to
     // AppServiceProxy, check that the app is no longer preferred.
   }
 }
+
+TEST_F(AppServiceProxyPreferredAppsTest, SetPreferredApp) {
+  constexpr char kTestAppId1[] = "abc";
+  constexpr char kTestAppId2[] = "def";
+  const GURL kTestUrl1 = GURL("https://www.foo.com/");
+  const GURL kTestUrl2 = GURL("https://www.bar.com/");
+
+  auto url_filter_1 = apps_util::CreateIntentFilterForUrlScope(kTestUrl1);
+  auto url_filter_2 = apps_util::CreateIntentFilterForUrlScope(kTestUrl2);
+  auto send_filter = apps_util::CreateIntentFilterForSend("image/png");
+
+  std::vector<mojom::AppPtr> apps;
+  mojom::AppPtr app1 = PublisherBase::MakeApp(
+      mojom::AppType::kWeb, kTestAppId1, mojom::Readiness::kReady, "Test App",
+      mojom::InstallSource::kUser);
+  app1->intent_filters.push_back(url_filter_1.Clone());
+  app1->intent_filters.push_back(url_filter_2.Clone());
+  app1->intent_filters.push_back(send_filter.Clone());
+  apps.push_back(std::move(app1));
+
+  mojom::AppPtr app2 = PublisherBase::MakeApp(
+      mojom::AppType::kWeb, kTestAppId2, mojom::Readiness::kReady, "Test App",
+      mojom::InstallSource::kUser);
+  app2->intent_filters.push_back(url_filter_1.Clone());
+  apps.push_back(std::move(app2));
+
+  proxy()->OnApps(std::move(apps), mojom::AppType::kWeb,
+                  /*should_notify_initialized=*/false);
+
+  // Set app 1 as preferred. Both links should be set as preferred, but the
+  // non-link filter is ignored.
+
+  proxy()->SetSupportedLinksPreference(kTestAppId1);
+  proxy()->FlushMojoCallsForTesting();
+
+  ASSERT_EQ(kTestAppId1,
+            proxy()->PreferredApps().FindPreferredAppForUrl(kTestUrl1));
+  ASSERT_EQ(kTestAppId1,
+            proxy()->PreferredApps().FindPreferredAppForUrl(kTestUrl2));
+  apps::mojom::IntentPtr mime_intent = apps::mojom::Intent::New();
+  mime_intent->mime_type = "image/png";
+  mime_intent->action = apps_util::kIntentActionSend;
+  ASSERT_EQ(absl::nullopt,
+            proxy()->PreferredApps().FindPreferredAppForIntent(mime_intent));
+
+  // Set app 2 as preferred. Both of the previous preferences for app 1 should
+  // be removed.
+
+  proxy()->SetSupportedLinksPreference(kTestAppId2);
+  proxy()->FlushMojoCallsForTesting();
+
+  ASSERT_EQ(kTestAppId2,
+            proxy()->PreferredApps().FindPreferredAppForUrl(kTestUrl1));
+  ASSERT_EQ(absl::nullopt,
+            proxy()->PreferredApps().FindPreferredAppForUrl(kTestUrl2));
+
+  // Remove all supported link preferences for app 2.
+
+  proxy()->RemoveSupportedLinksPreference(kTestAppId2);
+  proxy()->FlushMojoCallsForTesting();
+
+  ASSERT_EQ(absl::nullopt,
+            proxy()->PreferredApps().FindPreferredAppForUrl(kTestUrl1));
+}
+
 #endif  // !BUILDFLAG(OS_CHROMEOS_LACROS)
 
 }  // namespace apps
diff --git a/chrome/browser/apps/platform_apps/app_load_service.cc b/chrome/browser/apps/platform_apps/app_load_service.cc
index b0871b0..b4259d9 100644
--- a/chrome/browser/apps/platform_apps/app_load_service.cc
+++ b/chrome/browser/apps/platform_apps/app_load_service.cc
@@ -11,15 +11,11 @@
 #include "chrome/browser/extensions/unpacked_installer.h"
 #include "components/services/app_service/public/mojom/types.mojom-shared.h"
 #include "content/public/browser/browser_context.h"
-#include "content/public/browser/notification_details.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_types.h"
 #include "extensions/browser/app_window/app_window_registry.h"
 #include "extensions/browser/extension_host.h"
 #include "extensions/browser/extension_prefs.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_system.h"
-#include "extensions/browser/notification_types.h"
 #include "extensions/common/extension.h"
 
 using extensions::Extension;
@@ -34,10 +30,10 @@
 
 AppLoadService::AppLoadService(content::BrowserContext* context)
     : context_(context) {
-  registrar_.Add(this,
-                 extensions::NOTIFICATION_EXTENSION_HOST_DID_STOP_FIRST_LOAD,
-                 content::NotificationService::AllSources());
   extensions::ExtensionRegistry::Get(context_)->AddObserver(this);
+
+  host_registry_observation_.Observe(
+      extensions::ExtensionHostRegistry::Get(context_));
 }
 
 AppLoadService::~AppLoadService() = default;
@@ -94,12 +90,9 @@
   return apps::AppLoadServiceFactory::GetForBrowserContext(context);
 }
 
-void AppLoadService::Observe(int type,
-                             const content::NotificationSource& source,
-                             const content::NotificationDetails& details) {
-  DCHECK_EQ(type, extensions::NOTIFICATION_EXTENSION_HOST_DID_STOP_FIRST_LOAD);
-  extensions::ExtensionHost* host =
-      content::Details<extensions::ExtensionHost>(details).ptr();
+void AppLoadService::OnExtensionHostCompletedFirstLoad(
+    content::BrowserContext* browser_context,
+    extensions::ExtensionHost* host) {
   const Extension* extension = host->extension();
   // It is possible for an extension to be unloaded before it stops loading.
   if (!extension)
diff --git a/chrome/browser/apps/platform_apps/app_load_service.h b/chrome/browser/apps/platform_apps/app_load_service.h
index 65068ae..11add8a 100644
--- a/chrome/browser/apps/platform_apps/app_load_service.h
+++ b/chrome/browser/apps/platform_apps/app_load_service.h
@@ -10,9 +10,9 @@
 
 #include "base/command_line.h"
 #include "base/files/file_path.h"
+#include "base/scoped_observation.h"
 #include "components/keyed_service/core/keyed_service.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
+#include "extensions/browser/extension_host_registry.h"
 #include "extensions/browser/extension_registry_observer.h"
 #include "extensions/common/extension_id.h"
 
@@ -25,8 +25,8 @@
 // Monitors apps being reloaded and performs app specific actions (like launch
 // or restart) on them. Also provides an interface to schedule these actions.
 class AppLoadService : public KeyedService,
-                       public content::NotificationObserver,
-                       public extensions::ExtensionRegistryObserver {
+                       public extensions::ExtensionRegistryObserver,
+                       public extensions::ExtensionHostRegistry::Observer {
  public:
   enum PostReloadActionType {
     LAUNCH_FOR_RELOAD,
@@ -72,10 +72,10 @@
   static AppLoadService* Get(content::BrowserContext* context);
 
  private:
-  // content::NotificationObserver.
-  void Observe(int type,
-               const content::NotificationSource& source,
-               const content::NotificationDetails& details) override;
+  // extensions::ExtensionHostRegistry::Observer:
+  void OnExtensionHostCompletedFirstLoad(
+      content::BrowserContext* browser_context,
+      extensions::ExtensionHost* host) override;
 
   // extensions::ExtensionRegistryObserver.
   void OnExtensionUnloaded(content::BrowserContext* browser_context,
@@ -89,8 +89,11 @@
   // Map of extension id to reload action. Absence from the map implies
   // no action.
   std::map<std::string, PostReloadAction> post_reload_actions_;
-  content::NotificationRegistrar registrar_;
   content::BrowserContext* context_;
+
+  base::ScopedObservation<extensions::ExtensionHostRegistry,
+                          extensions::ExtensionHostRegistry::Observer>
+      host_registry_observation_{this};
 };
 
 }  // namespace apps
diff --git a/chrome/browser/apps/platform_apps/app_load_service_factory.cc b/chrome/browser/apps/platform_apps/app_load_service_factory.cc
index bbff2f7..b95974d 100644
--- a/chrome/browser/apps/platform_apps/app_load_service_factory.cc
+++ b/chrome/browser/apps/platform_apps/app_load_service_factory.cc
@@ -8,6 +8,7 @@
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "content/public/browser/browser_context.h"
 #include "extensions/browser/app_window/app_window_registry.h"
+#include "extensions/browser/extension_host_registry.h"
 #include "extensions/browser/extension_prefs_factory.h"
 #include "extensions/browser/extension_registry_factory.h"
 #include "extensions/browser/extension_system_provider.h"
@@ -33,6 +34,7 @@
   DependsOn(extensions::AppWindowRegistry::Factory::GetInstance());
   DependsOn(extensions::ExtensionPrefsFactory::GetInstance());
   DependsOn(extensions::ExtensionRegistryFactory::GetInstance());
+  DependsOn(extensions::ExtensionHostRegistry::GetFactory());
   DependsOn(
       extensions::ExtensionsBrowserClient::Get()->GetExtensionSystemFactory());
 }
diff --git a/chrome/browser/ash/accessibility/accessibility_manager_browsertest.cc b/chrome/browser/ash/accessibility/accessibility_manager_browsertest.cc
index ec82937..d054bcf 100644
--- a/chrome/browser/ash/accessibility/accessibility_manager_browsertest.cc
+++ b/chrome/browser/ash/accessibility/accessibility_manager_browsertest.cc
@@ -254,10 +254,10 @@
                                    enabled);
 }
 
-bool IsBrailleImeActive() {
+bool IsBrailleImeEnabled() {
   InputMethodManager* imm = InputMethodManager::Get();
   std::unique_ptr<InputMethodDescriptors> descriptors =
-      imm->GetActiveIMEState()->GetActiveInputMethods();
+      imm->GetActiveIMEState()->GetEnabledInputMethods();
   for (const auto& descriptor : *descriptors) {
     if (descriptor.id() == extension_ime_util::kBrailleImeEngineId)
       return true;
@@ -1423,7 +1423,7 @@
           GetActiveUserProfile()));
 
   // Make sure we start in the expected state.
-  EXPECT_FALSE(IsBrailleImeActive());
+  EXPECT_FALSE(IsBrailleImeEnabled());
   EXPECT_FALSE(IsSpokenFeedbackEnabled());
 
   // Signal the accessibility manager that a braille display was connected.
@@ -1431,10 +1431,10 @@
 
   // Now, both spoken feedback and the Braille IME should be enabled.
   EXPECT_TRUE(IsSpokenFeedbackEnabled());
-  EXPECT_TRUE(IsBrailleImeActive());
+  EXPECT_TRUE(IsBrailleImeEnabled());
 
   // Send a braille dots key event and make sure that the braille IME is
-  // enabled.
+  // activated.
   KeyEvent event;
   event.command = extensions::api::braille_display_private::KEY_COMMAND_DOTS;
   event.braille_dots = std::make_unique<int>(0);
@@ -1442,17 +1442,17 @@
   EXPECT_TRUE(IsBrailleImeCurrent());
 
   // Unplug the display.  Spoken feedback remains on, but the Braille IME
-  // should get deactivated.
+  // should get disabled and deactivated.
   SetBrailleDisplayAvailability(false);
   EXPECT_TRUE(IsSpokenFeedbackEnabled());
-  EXPECT_FALSE(IsBrailleImeActive());
+  EXPECT_FALSE(IsBrailleImeEnabled());
   EXPECT_FALSE(IsBrailleImeCurrent());
 
-  // Plugging in a display while spoken feedback is enabled should activate
+  // Plugging in a display while spoken feedback is enabled should enable
   // the Braille IME.
   SetBrailleDisplayAvailability(true);
   EXPECT_TRUE(IsSpokenFeedbackEnabled());
-  EXPECT_TRUE(IsBrailleImeActive());
+  EXPECT_TRUE(IsBrailleImeEnabled());
 }
 
 }  // namespace ash
diff --git a/chrome/browser/ash/app_restore/app_launch_handler.h b/chrome/browser/ash/app_restore/app_launch_handler.h
index 2dfa5d4..145ead9 100644
--- a/chrome/browser/ash/app_restore/app_launch_handler.h
+++ b/chrome/browser/ash/app_restore/app_launch_handler.h
@@ -31,6 +31,10 @@
   // Returns true if there are some restore data. Otherwise, returns false.
   bool HasRestoreData();
 
+  // Called when an app has launched. Overriders can use this to record
+  // histograms based on `app_type_name`.
+  virtual void RecordRestoredAppLaunch(apps::AppTypeName app_type_name) = 0;
+
   // apps::AppRegistryCache::Observer:
   void OnAppUpdate(const apps::AppUpdate& update) override;
   void OnAppTypeInitialized(apps::mojom::AppType app_type) override;
@@ -40,6 +44,8 @@
   Profile* profile() { return profile_; }
   const Profile* profile() const { return profile_; }
 
+  ::app_restore::RestoreData* restore_data() { return restore_data_.get(); }
+
  protected:
   // Note: LaunchApps does not launch browser windows, this is handled
   // separately.
@@ -57,10 +63,9 @@
   virtual base::WeakPtr<AppLaunchHandler> GetWeakPtrAppLaunchHandler() = 0;
 
   void set_restore_data(
-      std::unique_ptr<app_restore::RestoreData> restore_data) {
+      std::unique_ptr<::app_restore::RestoreData> restore_data) {
     restore_data_ = std::move(restore_data);
   }
-  app_restore::RestoreData* restore_data() { return restore_data_.get(); }
 
  private:
   void LaunchApp(apps::mojom::AppType app_type, const std::string& app_id);
@@ -68,12 +73,10 @@
   virtual void LaunchSystemWebAppOrChromeApp(
       apps::mojom::AppType app_type,
       const std::string& app_id,
-      const app_restore::RestoreData::LaunchList& launch_list);
-
-  virtual void RecordRestoredAppLaunch(apps::AppTypeName app_type_name) = 0;
+      const ::app_restore::RestoreData::LaunchList& launch_list);
 
   Profile* const profile_;
-  std::unique_ptr<app_restore::RestoreData> restore_data_;
+  std::unique_ptr<::app_restore::RestoreData> restore_data_;
 };
 
 }  // namespace ash
diff --git a/chrome/browser/ash/app_restore/full_restore_arc_task_handler.cc b/chrome/browser/ash/app_restore/app_restore_arc_task_handler.cc
similarity index 62%
rename from chrome/browser/ash/app_restore/full_restore_arc_task_handler.cc
rename to chrome/browser/ash/app_restore/app_restore_arc_task_handler.cc
index 1ec6967a..27ac65d2 100644
--- a/chrome/browser/ash/app_restore/full_restore_arc_task_handler.cc
+++ b/chrome/browser/ash/app_restore/app_restore_arc_task_handler.cc
@@ -2,26 +2,26 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ash/app_restore/full_restore_arc_task_handler.h"
+#include "chrome/browser/ash/app_restore/app_restore_arc_task_handler.h"
 
+#include "chrome/browser/ash/app_restore/app_restore_arc_task_handler_factory.h"
 #include "chrome/browser/ash/app_restore/arc_app_launch_handler.h"
 #include "chrome/browser/ash/app_restore/arc_window_handler.h"
 #include "chrome/browser/ash/app_restore/arc_window_utils.h"
-#include "chrome/browser/ash/app_restore/full_restore_arc_task_handler_factory.h"
 #include "chrome/browser/ash/arc/session/arc_session_manager.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/app_restore/full_restore_utils.h"
 
 namespace ash {
-namespace full_restore {
+namespace app_restore {
 
 // static
-FullRestoreArcTaskHandler* FullRestoreArcTaskHandler::GetForProfile(
+AppRestoreArcTaskHandler* AppRestoreArcTaskHandler::GetForProfile(
     Profile* profile) {
-  return FullRestoreArcTaskHandlerFactory::GetForProfile(profile);
+  return AppRestoreArcTaskHandlerFactory::GetForProfile(profile);
 }
 
-FullRestoreArcTaskHandler::FullRestoreArcTaskHandler(Profile* profile) {
+AppRestoreArcTaskHandler::AppRestoreArcTaskHandler(Profile* profile) {
   ArcAppListPrefs* prefs = ArcAppListPrefs::Get(profile);
   if (!prefs)
     return;
@@ -29,8 +29,8 @@
   arc_prefs_observer_.Observe(prefs);
 
 #if BUILDFLAG(ENABLE_WAYLAND_SERVER)
-  if (IsArcGhostWindowEnabled())
-    window_handler_ = std::make_unique<ArcWindowHandler>();
+  if (full_restore::IsArcGhostWindowEnabled())
+    window_handler_ = std::make_unique<full_restore::ArcWindowHandler>();
 #endif
 
   arc_app_launch_handler_ = std::make_unique<ArcAppLaunchHandler>();
@@ -41,27 +41,27 @@
     arc_session_manager->AddObserver(this);
 }
 
-FullRestoreArcTaskHandler::~FullRestoreArcTaskHandler() {
+AppRestoreArcTaskHandler::~AppRestoreArcTaskHandler() {
   arc::ArcSessionManager* arc_session_manager = arc::ArcSessionManager::Get();
   // arc::ArcSessionManager may be released first.
   if (arc_session_manager)
     arc_session_manager->RemoveObserver(this);
 }
 
-void FullRestoreArcTaskHandler::OnTaskCreated(int32_t task_id,
-                                              const std::string& package_name,
-                                              const std::string& activity,
-                                              const std::string& intent,
-                                              int32_t session_id) {
+void AppRestoreArcTaskHandler::OnTaskCreated(int32_t task_id,
+                                             const std::string& package_name,
+                                             const std::string& activity,
+                                             const std::string& intent,
+                                             int32_t session_id) {
   const std::string app_id = ArcAppListPrefs::GetAppId(package_name, activity);
   ::full_restore::OnTaskCreated(app_id, task_id, session_id);
 }
 
-void FullRestoreArcTaskHandler::OnTaskDestroyed(int32_t task_id) {
+void AppRestoreArcTaskHandler::OnTaskDestroyed(int32_t task_id) {
   ::full_restore::OnTaskDestroyed(task_id);
 }
 
-void FullRestoreArcTaskHandler::OnTaskDescriptionChanged(
+void AppRestoreArcTaskHandler::OnTaskDescriptionChanged(
     int32_t task_id,
     const std::string& label,
     const arc::mojom::RawIconPngData& icon,
@@ -71,7 +71,7 @@
                                           status_bar_color);
 }
 
-void FullRestoreArcTaskHandler::OnAppConnectionReady() {
+void AppRestoreArcTaskHandler::OnAppConnectionReady() {
 #if BUILDFLAG(ENABLE_WAYLAND_SERVER)
   if (window_handler_)
     window_handler_->OnAppInstanceConnected();
@@ -83,28 +83,28 @@
   ::full_restore::SetArcConnection(/*is_connection_ready=*/true);
 }
 
-void FullRestoreArcTaskHandler::OnAppConnectionClosed() {
+void AppRestoreArcTaskHandler::OnAppConnectionClosed() {
   ::full_restore::SetArcConnection(/*is_connection_ready=*/false);
 }
 
-void FullRestoreArcTaskHandler::OnArcAppListPrefsDestroyed() {
+void AppRestoreArcTaskHandler::OnArcAppListPrefsDestroyed() {
   arc_prefs_observer_.Reset();
 }
 
-void FullRestoreArcTaskHandler::OnArcPlayStoreEnabledChanged(bool enabled) {
+void AppRestoreArcTaskHandler::OnArcPlayStoreEnabledChanged(bool enabled) {
   if (arc_app_launch_handler_)
     arc_app_launch_handler_->OnArcPlayStoreEnabledChanged(enabled);
 }
 
-void FullRestoreArcTaskHandler::OnShelfReady() {
+void AppRestoreArcTaskHandler::OnShelfReady() {
   if (arc_app_launch_handler_)
     arc_app_launch_handler_->OnShelfReady();
 }
 
-void FullRestoreArcTaskHandler::Shutdown() {
+void AppRestoreArcTaskHandler::Shutdown() {
   arc_app_launch_handler_.reset();
   window_handler_.reset();
 }
 
-}  // namespace full_restore
+}  // namespace app_restore
 }  // namespace ash
diff --git a/chrome/browser/ash/app_restore/full_restore_arc_task_handler.h b/chrome/browser/ash/app_restore/app_restore_arc_task_handler.h
similarity index 66%
rename from chrome/browser/ash/app_restore/full_restore_arc_task_handler.h
rename to chrome/browser/ash/app_restore/app_restore_arc_task_handler.h
index c2f266eb..1731f61 100644
--- a/chrome/browser/ash/app_restore/full_restore_arc_task_handler.h
+++ b/chrome/browser/ash/app_restore/app_restore_arc_task_handler.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_ASH_APP_RESTORE_FULL_RESTORE_ARC_TASK_HANDLER_H_
-#define CHROME_BROWSER_ASH_APP_RESTORE_FULL_RESTORE_ARC_TASK_HANDLER_H_
+#ifndef CHROME_BROWSER_ASH_APP_RESTORE_APP_RESTORE_ARC_TASK_HANDLER_H_
+#define CHROME_BROWSER_ASH_APP_RESTORE_APP_RESTORE_ARC_TASK_HANDLER_H_
 
 #include <utility>
 
@@ -17,31 +17,35 @@
 
 namespace ash {
 namespace full_restore {
+class ArcWindowHandler;
+}  // namespace full_restore
+
+namespace app_restore {
 
 class ArcAppLaunchHandler;
-class ArcWindowHandler;
 
-// The FullRestoreArcTaskHandler class observes ArcAppListPrefs, and calls
+// The AppRestoreArcTaskHandler class observes ArcAppListPrefs, and calls
 // FullRestoreSaveHandler to update the ARC app launch info when a task is
 // created or destroyed.
 //
-// FullRestoreArcTaskHandler is an independent KeyedService so that it could be
+// AppRestoreArcTaskHandler is an independent KeyedService so that it could be
 // created along with ARC system rather than with FullRestoreService.
-class FullRestoreArcTaskHandler : public KeyedService,
-                                  public ArcAppListPrefs::Observer,
-                                  public arc::ArcSessionManagerObserver {
+class AppRestoreArcTaskHandler : public KeyedService,
+                                 public ArcAppListPrefs::Observer,
+                                 public arc::ArcSessionManagerObserver {
  public:
-  static FullRestoreArcTaskHandler* GetForProfile(Profile* profile);
+  static AppRestoreArcTaskHandler* GetForProfile(Profile* profile);
 
-  explicit FullRestoreArcTaskHandler(Profile* profile);
-  FullRestoreArcTaskHandler(const FullRestoreArcTaskHandler&) = delete;
-  FullRestoreArcTaskHandler& operator=(const FullRestoreArcTaskHandler&) =
-      delete;
+  explicit AppRestoreArcTaskHandler(Profile* profile);
+  AppRestoreArcTaskHandler(const AppRestoreArcTaskHandler&) = delete;
+  AppRestoreArcTaskHandler& operator=(const AppRestoreArcTaskHandler&) = delete;
 
-  ~FullRestoreArcTaskHandler() override;
+  ~AppRestoreArcTaskHandler() override;
 
 #if BUILDFLAG(ENABLE_WAYLAND_SERVER)
-  ArcWindowHandler* window_handler() { return window_handler_.get(); }
+  full_restore::ArcWindowHandler* window_handler() {
+    return window_handler_.get();
+  }
 #endif
 
   ArcAppLaunchHandler* arc_app_launch_handler() {
@@ -78,13 +82,13 @@
       arc_prefs_observer_{this};
 
 #if BUILDFLAG(ENABLE_WAYLAND_SERVER)
-  std::unique_ptr<ArcWindowHandler> window_handler_;
+  std::unique_ptr<full_restore::ArcWindowHandler> window_handler_;
 #endif
 
   std::unique_ptr<ArcAppLaunchHandler> arc_app_launch_handler_;
 };
 
-}  // namespace full_restore
+}  // namespace app_restore
 }  // namespace ash
 
-#endif  // CHROME_BROWSER_ASH_APP_RESTORE_FULL_RESTORE_ARC_TASK_HANDLER_H_
+#endif  // CHROME_BROWSER_ASH_APP_RESTORE_APP_RESTORE_ARC_TASK_HANDLER_H_
diff --git a/chrome/browser/ash/app_restore/app_restore_arc_task_handler_factory.cc b/chrome/browser/ash/app_restore/app_restore_arc_task_handler_factory.cc
new file mode 100644
index 0000000..0039999
--- /dev/null
+++ b/chrome/browser/ash/app_restore/app_restore_arc_task_handler_factory.cc
@@ -0,0 +1,54 @@
+// 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 "chrome/browser/ash/app_restore/app_restore_arc_task_handler_factory.h"
+
+#include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
+#include "chrome/browser/ash/app_restore/app_restore_arc_task_handler.h"
+#include "chrome/browser/ash/arc/arc_util.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.h"
+#include "components/app_restore/features.h"
+#include "components/keyed_service/content/browser_context_dependency_manager.h"
+
+namespace ash {
+namespace app_restore {
+
+// static
+AppRestoreArcTaskHandler* AppRestoreArcTaskHandlerFactory::GetForProfile(
+    Profile* profile) {
+  return static_cast<AppRestoreArcTaskHandler*>(
+      AppRestoreArcTaskHandlerFactory::GetInstance()
+          ->GetServiceForBrowserContext(profile, /*create=*/true));
+}
+
+// static
+AppRestoreArcTaskHandlerFactory*
+AppRestoreArcTaskHandlerFactory::GetInstance() {
+  return base::Singleton<AppRestoreArcTaskHandlerFactory>::get();
+}
+
+AppRestoreArcTaskHandlerFactory::AppRestoreArcTaskHandlerFactory()
+    : BrowserContextKeyedServiceFactory(
+          "AppRestoreArcTaskHandler",
+          BrowserContextDependencyManager::GetInstance()) {
+  DependsOn(ArcAppListPrefsFactory::GetInstance());
+  DependsOn(apps::AppServiceProxyFactory::GetInstance());
+}
+
+AppRestoreArcTaskHandlerFactory::~AppRestoreArcTaskHandlerFactory() = default;
+
+KeyedService* AppRestoreArcTaskHandlerFactory::BuildServiceInstanceFor(
+    content::BrowserContext* context) const {
+  if (!::full_restore::features::IsFullRestoreEnabled())
+    return nullptr;
+
+  if (!arc::IsArcAllowedForProfile(Profile::FromBrowserContext(context)))
+    return nullptr;
+
+  return new AppRestoreArcTaskHandler(Profile::FromBrowserContext(context));
+}
+
+}  // namespace app_restore
+}  // namespace ash
diff --git a/chrome/browser/ash/app_restore/app_restore_arc_task_handler_factory.h b/chrome/browser/ash/app_restore/app_restore_arc_task_handler_factory.h
new file mode 100644
index 0000000..daa3940
--- /dev/null
+++ b/chrome/browser/ash/app_restore/app_restore_arc_task_handler_factory.h
@@ -0,0 +1,43 @@
+// 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.
+
+#ifndef CHROME_BROWSER_ASH_APP_RESTORE_APP_RESTORE_ARC_TASK_HANDLER_FACTORY_H_
+#define CHROME_BROWSER_ASH_APP_RESTORE_APP_RESTORE_ARC_TASK_HANDLER_FACTORY_H_
+
+#include "base/memory/singleton.h"
+#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+
+class Profile;
+
+namespace ash {
+namespace app_restore {
+
+class AppRestoreArcTaskHandler;
+
+class AppRestoreArcTaskHandlerFactory
+    : public BrowserContextKeyedServiceFactory {
+ public:
+  static AppRestoreArcTaskHandler* GetForProfile(Profile* profile);
+
+  static AppRestoreArcTaskHandlerFactory* GetInstance();
+
+ private:
+  friend struct base::DefaultSingletonTraits<AppRestoreArcTaskHandlerFactory>;
+
+  AppRestoreArcTaskHandlerFactory();
+  AppRestoreArcTaskHandlerFactory(const AppRestoreArcTaskHandlerFactory&) =
+      delete;
+  AppRestoreArcTaskHandlerFactory& operator=(
+      const AppRestoreArcTaskHandlerFactory&) = delete;
+  ~AppRestoreArcTaskHandlerFactory() override;
+
+  // BrowserContextKeyedServiceFactory.
+  KeyedService* BuildServiceInstanceFor(
+      content::BrowserContext* context) const override;
+};
+
+}  // namespace app_restore
+}  // namespace ash
+
+#endif  // CHROME_BROWSER_ASH_APP_RESTORE_APP_RESTORE_ARC_TASK_HANDLER_FACTORY_H_
diff --git a/chrome/browser/ash/app_restore/arc_app_launch_handler.cc b/chrome/browser/ash/app_restore/arc_app_launch_handler.cc
index 3ebf6521..0a688943 100644
--- a/chrome/browser/ash/app_restore/arc_app_launch_handler.cc
+++ b/chrome/browser/ash/app_restore/arc_app_launch_handler.cc
@@ -18,10 +18,10 @@
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
 #include "chrome/browser/apps/app_service/launch_utils.h"
+#include "chrome/browser/ash/app_restore/app_restore_arc_task_handler.h"
 #include "chrome/browser/ash/app_restore/arc_window_handler.h"
 #include "chrome/browser/ash/app_restore/arc_window_utils.h"
 #include "chrome/browser/ash/app_restore/full_restore_app_launch_handler.h"
-#include "chrome/browser/ash/app_restore/full_restore_arc_task_handler.h"
 #include "chrome/browser/ash/arc/arc_util.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_process_platform_part.h"
@@ -79,7 +79,7 @@
 
 constexpr char kArcGhostWindowLaunchHistogram[] = "Apps.ArcGhostWindowLaunch";
 
-constexpr char kRestoreArcAppStates[] = "Apps.RestoreArcAppStates";
+constexpr char kRestoreArcAppStatesHistogram[] = "Apps.RestoreArcAppStates";
 
 constexpr char kGhostWindowPopToArcHistogram[] = "Arc.LaunchedWithGhostWindow";
 
@@ -89,7 +89,7 @@
 }  // namespace
 
 namespace ash {
-namespace full_restore {
+namespace app_restore {
 
 ArcAppLaunchHandler::ArcAppLaunchHandler() {
   if (aura::Env::HasInstance())
@@ -132,8 +132,7 @@
     manager->RemoveObserver(this);
 }
 
-void ArcAppLaunchHandler::RestoreArcApps(
-    FullRestoreAppLaunchHandler* app_launch_handler) {
+void ArcAppLaunchHandler::RestoreArcApps(AppLaunchHandler* app_launch_handler) {
   DCHECK(app_launch_handler);
   handler_ = app_launch_handler;
 
@@ -149,9 +148,8 @@
     return;
   }
 
-  window_handler_ =
-      FullRestoreArcTaskHandler::GetForProfile(handler_->profile())
-          ->window_handler();
+  window_handler_ = AppRestoreArcTaskHandler::GetForProfile(handler_->profile())
+                        ->window_handler();
 
   apps::AppRegistryCache& cache =
       apps::AppServiceProxyFactory::GetForProfile(handler_->profile())
@@ -290,7 +288,7 @@
     return;
 
   const std::string* arc_app_id =
-      new_active->GetProperty(app_restore::kAppIdKey);
+      new_active->GetProperty(::app_restore::kAppIdKey);
   if (!arc_app_id || arc_app_id->empty() || !IsAppReady(*arc_app_id))
     return;
 
@@ -333,7 +331,7 @@
   auto window_id = it->second;
   session_id_to_window_id_.erase(session_id.value());
 
-  const std::string* arc_app_id = window->GetProperty(app_restore::kAppIdKey);
+  const std::string* arc_app_id = window->GetProperty(::app_restore::kAppIdKey);
   if (!arc_app_id || arc_app_id->empty())
     return;
 
@@ -450,12 +448,12 @@
     if (data_it.second->intent.has_value()) {
       DCHECK(data_it.second->intent.value());
       ::full_restore::SaveAppLaunchInfo(
-          file_path, std::make_unique<app_restore::AppLaunchInfo>(
+          file_path, std::make_unique<::app_restore::AppLaunchInfo>(
                          app_id, event_flags, data_it.second->intent->Clone(),
                          arc_session_id, display_id));
     } else {
       ::full_restore::SaveAppLaunchInfo(
-          file_path, std::make_unique<app_restore::AppLaunchInfo>(
+          file_path, std::make_unique<::app_restore::AppLaunchInfo>(
                          app_id, event_flags, arc_session_id, display_id));
     }
 
@@ -619,7 +617,7 @@
   DCHECK(data_it->second->event_flag.has_value());
 
   apps::mojom::WindowInfoPtr window_info =
-      HandleArcWindowInfo(data_it->second->GetAppWindowInfo());
+      full_restore::HandleArcWindowInfo(data_it->second->GetAppWindowInfo());
   const auto window_it = window_id_to_session_id_.find(window_id);
   if (window_it != window_id_to_session_id_.end()) {
     window_info->window_id = window_it->second;
@@ -879,7 +877,7 @@
     // For other cases, mark the failed state as "unknown".
   }
 
-  base::UmaHistogramEnumeration(kRestoreArcAppStates, restore_state);
+  base::UmaHistogramEnumeration(kRestoreArcAppStatesHistogram, restore_state);
 
 #if BUILDFLAG(ENABLE_WAYLAND_SERVER)
   if (window_handler_) {
@@ -896,5 +894,5 @@
   return g_browser_process->platform_part()->scheduler_configuration_manager();
 }
 
-}  // namespace full_restore
+}  // namespace app_restore
 }  // namespace ash
diff --git a/chrome/browser/ash/app_restore/arc_app_launch_handler.h b/chrome/browser/ash/app_restore/arc_app_launch_handler.h
index 788afed..bb6657e 100644
--- a/chrome/browser/ash/app_restore/arc_app_launch_handler.h
+++ b/chrome/browser/ash/app_restore/arc_app_launch_handler.h
@@ -29,12 +29,16 @@
 }  // namespace apps
 
 namespace ash {
-namespace full_restore {
 
+class AppLaunchHandler;
+
+namespace full_restore {
 class ArcAppLaunchHandlerArcAppBrowserTest;
 class ArcWindowHandler;
-class FullRestoreAppLaunchHandler;
 class FullRestoreAppLaunchHandlerArcAppBrowserTest;
+}  // namespace full_restore
+
+namespace app_restore {
 
 struct CpuTick {
   uint64_t idle_time = 0;
@@ -118,7 +122,7 @@
 
   // Invoked when the restoration process can start. Reads the restore data, and
   // add the ARC apps windows to `windows_` and `no_stack_windows_`.
-  void RestoreArcApps(FullRestoreAppLaunchHandler* app_launch_handler);
+  void RestoreArcApps(AppLaunchHandler* app_launch_handler);
 
   void OnAppConnectionReady();
 
@@ -149,8 +153,8 @@
   void OnConfigurationSet(bool success, size_t num_cores_disabled) override;
 
  private:
-  friend ArcAppLaunchHandlerArcAppBrowserTest;
-  friend FullRestoreAppLaunchHandlerArcAppBrowserTest;
+  friend class full_restore::ArcAppLaunchHandlerArcAppBrowserTest;
+  friend class full_restore::FullRestoreAppLaunchHandlerArcAppBrowserTest;
 
   // Reads the restore data, and add the ARC app windows to `windows_`,
   // `no_stack_windows_` and `app_ids_`.
@@ -220,7 +224,7 @@
 
   chromeos::SchedulerConfigurationManager* GetSchedulerConfigurationManager();
 
-  FullRestoreAppLaunchHandler* handler_ = nullptr;
+  AppLaunchHandler* handler_ = nullptr;
 
   // The app id list from the restore data. If the app has been added the
   // AppRegistryCache, the app will be removed from `app_ids_` to
@@ -243,7 +247,7 @@
   std::map<int32_t, int32_t> window_id_to_session_id_;
   std::map<int32_t, int32_t> session_id_to_window_id_;
 
-  ArcWindowHandler* window_handler_ = nullptr;
+  full_restore::ArcWindowHandler* window_handler_ = nullptr;
 
   // If the system is under memory pressuure or high CPU usage rate, only launch
   // 1 window following the window stack priority. `first_run_` is used to check
@@ -304,7 +308,7 @@
   base::WeakPtrFactory<ArcAppLaunchHandler> weak_ptr_factory_{this};
 };
 
-}  // namespace full_restore
+}  // namespace app_restore
 }  // namespace ash
 
 #endif  // CHROME_BROWSER_ASH_APP_RESTORE_ARC_APP_LAUNCH_HANDLER_H_
diff --git a/chrome/browser/ash/app_restore/arc_window_handler.h b/chrome/browser/ash/app_restore/arc_window_handler.h
index 3cfaf7c..4e0daf3e 100644
--- a/chrome/browser/ash/app_restore/arc_window_handler.h
+++ b/chrome/browser/ash/app_restore/arc_window_handler.h
@@ -66,7 +66,7 @@
 
   void LaunchArcGhostWindow(const std::string& app_id,
                             int32_t session_id,
-                            app_restore::AppRestoreData* restore_data);
+                            ::app_restore::AppRestoreData* restore_data);
 
   void CloseWindow(int session_id);
 
@@ -83,7 +83,7 @@
 
   int ghost_window_pop_count() { return ghost_window_pop_count_; }
 
-  // Override exo::WMHelper::LifetimeManager::Observer.
+  // exo::WMHelper::LifetimeManager::Observer:
   void OnDestroyed() override;
 
  private:
diff --git a/chrome/browser/ash/app_restore/full_restore_app_launch_handler.cc b/chrome/browser/ash/app_restore/full_restore_app_launch_handler.cc
index 6374ff8..1e3e5e6 100644
--- a/chrome/browser/ash/app_restore/full_restore_app_launch_handler.cc
+++ b/chrome/browser/ash/app_restore/full_restore_app_launch_handler.cc
@@ -15,8 +15,8 @@
 #include "chrome/browser/apps/app_service/app_platform_metrics.h"
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
+#include "chrome/browser/ash/app_restore/app_restore_arc_task_handler.h"
 #include "chrome/browser/ash/app_restore/arc_app_launch_handler.h"
-#include "chrome/browser/ash/app_restore/full_restore_arc_task_handler.h"
 #include "chrome/browser/ash/app_restore/full_restore_service.h"
 #include "chrome/browser/ash/login/session/user_session_manager.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
@@ -179,7 +179,7 @@
 }
 
 void FullRestoreAppLaunchHandler::OnGetRestoreData(
-    std::unique_ptr<app_restore::RestoreData> restore_data) {
+    std::unique_ptr<::app_restore::RestoreData> restore_data) {
   set_restore_data(std::move(restore_data));
   LogRestoreData();
 
@@ -214,10 +214,9 @@
   }
 
   VLOG(1) << "Restore apps in " << profile()->GetPath();
-  if (FullRestoreArcTaskHandler::GetForProfile(profile())) {
-    FullRestoreArcTaskHandler::GetForProfile(profile())
-        ->arc_app_launch_handler()
-        ->RestoreArcApps(this);
+  if (auto* arc_task_handler =
+          app_restore::AppRestoreArcTaskHandler::GetForProfile(profile())) {
+    arc_task_handler->arc_app_launch_handler()->RestoreArcApps(this);
   }
 
   LaunchApps();
diff --git a/chrome/browser/ash/app_restore/full_restore_app_launch_handler_browsertest.cc b/chrome/browser/ash/app_restore/full_restore_app_launch_handler_browsertest.cc
index 13ba896..21d2c96 100644
--- a/chrome/browser/ash/app_restore/full_restore_app_launch_handler_browsertest.cc
+++ b/chrome/browser/ash/app_restore/full_restore_app_launch_handler_browsertest.cc
@@ -23,8 +23,8 @@
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
 #include "chrome/browser/apps/app_service/launch_utils.h"
 #include "chrome/browser/apps/platform_apps/app_browsertest_util.h"
+#include "chrome/browser/ash/app_restore/app_restore_arc_task_handler.h"
 #include "chrome/browser/ash/app_restore/arc_app_launch_handler.h"
-#include "chrome/browser/ash/app_restore/full_restore_arc_task_handler.h"
 #include "chrome/browser/ash/app_restore/full_restore_prefs.h"
 #include "chrome/browser/ash/app_restore/full_restore_service.h"
 #include "chrome/browser/ash/arc/arc_util.h"
@@ -164,9 +164,9 @@
   // SaveWindowInfo to work.
   auto window = std::make_unique<aura::Window>(nullptr);
   window->Init(ui::LAYER_NOT_DRAWN);
-  window->SetProperty(app_restore::kWindowIdKey, window_id);
+  window->SetProperty(::app_restore::kWindowIdKey, window_id);
 
-  app_restore::WindowInfo window_info;
+  ::app_restore::WindowInfo window_info;
   window_info.window = window.get();
   window_info.desk_id = desk_id;
   window_info.current_bounds = current_bounds;
@@ -188,7 +188,7 @@
 }
 
 void SaveWindowInfo(aura::Window* window) {
-  app_restore::WindowInfo window_info;
+  ::app_restore::WindowInfo window_info;
   window_info.window = window;
   window_info.activation_index = kActivationIndex;
   window_info.desk_id = kDeskId;
@@ -201,7 +201,7 @@
     aura::Window* window,
     uint32_t activation_index,
     chromeos::WindowStateType window_state_type = kWindowStateType) {
-  app_restore::WindowInfo window_info;
+  ::app_restore::WindowInfo window_info;
   window_info.window = window;
   window_info.activation_index = activation_index;
   window_info.desk_id = kDeskId;
@@ -256,9 +256,10 @@
   ExoAppTypeResolver().PopulateProperties(resolver_params,
                                           params.init_properties_container);
 
-  if (!app_id.empty())
-    params.init_properties_container.SetProperty(app_restore::kAppIdKey,
+  if (!app_id.empty()) {
+    params.init_properties_container.SetProperty(::app_restore::kAppIdKey,
                                                  app_id);
+  }
 
   views::Widget* widget = new views::Widget();
   widget->Init(std::move(params));
@@ -285,7 +286,7 @@
 Browser* GetBrowserForWindowId(int32_t window_id) {
   for (Browser* browser : *BrowserList::GetInstance()) {
     if (browser->window()->GetNativeWindow()->GetProperty(
-            app_restore::kRestoreWindowIdKey) == window_id) {
+            ::app_restore::kRestoreWindowIdKey) == window_id) {
       return browser;
     }
   }
@@ -333,7 +334,8 @@
   aura::Window* FindWebAppWindow() {
     for (auto* browser : *BrowserList::GetInstance()) {
       aura::Window* window = browser->window()->GetNativeWindow();
-      if (window->GetProperty(app_restore::kRestoreWindowIdKey) == kWindowId2) {
+      if (window->GetProperty(::app_restore::kRestoreWindowIdKey) ==
+          kWindowId2) {
         return window;
       }
     }
@@ -359,13 +361,13 @@
   void SaveChromeAppLaunchInfo(const std::string& app_id) {
     ::full_restore::SaveAppLaunchInfo(
         profile()->GetPath(),
-        std::make_unique<app_restore::AppLaunchInfo>(
+        std::make_unique<::app_restore::AppLaunchInfo>(
             app_id, apps::mojom::LaunchContainer::kLaunchContainerWindow,
             WindowOpenDisposition::NEW_WINDOW, display::kDefaultDisplayId,
             std::vector<base::FilePath>{}, nullptr));
   }
 
-  std::unique_ptr<app_restore::WindowInfo> GetWindowInfo(
+  std::unique_ptr<::app_restore::WindowInfo> GetWindowInfo(
       int32_t restore_window_id) {
     return ::full_restore::FullRestoreReadHandler::GetInstance()->GetWindowInfo(
         restore_window_id);
@@ -405,7 +407,7 @@
                        NotLaunchBrowser) {
   // Add app launch info.
   ::full_restore::SaveAppLaunchInfo(
-      profile()->GetPath(), std::make_unique<app_restore::AppLaunchInfo>(
+      profile()->GetPath(), std::make_unique<::app_restore::AppLaunchInfo>(
                                 extension_misc::kChromeAppId, kWindowId1));
 
   WaitForAppLaunchInfoSaved();
@@ -426,7 +428,7 @@
   // Add app launch info.
   ::full_restore::SaveAppLaunchInfo(
       profile()->GetPath(),
-      std::make_unique<app_restore::AppLaunchInfo>(
+      std::make_unique<::app_restore::AppLaunchInfo>(
           kAppId, kWindowId2,
           apps::mojom::LaunchContainer::kLaunchContainerWindow,
           WindowOpenDisposition::NEW_WINDOW, display::kDefaultDisplayId,
@@ -445,7 +447,7 @@
 
   aura::Window* web_app_window = FindWebAppWindow();
   ASSERT_TRUE(web_app_window);
-  EXPECT_TRUE(web_app_window->GetProperty(app_restore::kWindowInfoKey));
+  EXPECT_TRUE(web_app_window->GetProperty(::app_restore::kWindowInfoKey));
 }
 
 // Tests that restoring windows that are minimized will restore their
@@ -455,7 +457,7 @@
   // Add app launch info.
   ::full_restore::SaveAppLaunchInfo(
       profile()->GetPath(),
-      std::make_unique<app_restore::AppLaunchInfo>(
+      std::make_unique<::app_restore::AppLaunchInfo>(
           kAppId, kWindowId2,
           apps::mojom::LaunchContainer::kLaunchContainerWindow,
           WindowOpenDisposition::NEW_WINDOW, display::kDefaultDisplayId,
@@ -493,7 +495,7 @@
   // Add app launch info.
   ::full_restore::SaveAppLaunchInfo(
       profile()->GetPath(),
-      std::make_unique<app_restore::AppLaunchInfo>(
+      std::make_unique<::app_restore::AppLaunchInfo>(
           kAppId, kWindowId2,
           apps::mojom::LaunchContainer::kLaunchContainerWindow,
           WindowOpenDisposition::NEW_WINDOW, display::kDefaultDisplayId,
@@ -516,7 +518,7 @@
                        FirstRunFullRestore) {
   // Add app launch infos.
   ::full_restore::SaveAppLaunchInfo(
-      profile()->GetPath(), std::make_unique<app_restore::AppLaunchInfo>(
+      profile()->GetPath(), std::make_unique<::app_restore::AppLaunchInfo>(
                                 extension_misc::kChromeAppId, kWindowId1));
 
   WaitForAppLaunchInfoSaved();
@@ -537,11 +539,11 @@
 IN_PROC_BROWSER_TEST_F(FullRestoreAppLaunchHandlerBrowserTest, NotRestore) {
   // Add app launch infos.
   ::full_restore::SaveAppLaunchInfo(
-      profile()->GetPath(), std::make_unique<app_restore::AppLaunchInfo>(
+      profile()->GetPath(), std::make_unique<::app_restore::AppLaunchInfo>(
                                 extension_misc::kChromeAppId, kWindowId1));
   ::full_restore::SaveAppLaunchInfo(
       profile()->GetPath(),
-      std::make_unique<app_restore::AppLaunchInfo>(
+      std::make_unique<::app_restore::AppLaunchInfo>(
           kAppId, kWindowId2,
           apps::mojom::LaunchContainer::kLaunchContainerWindow,
           WindowOpenDisposition::NEW_WINDOW, display::kDefaultDisplayId,
@@ -571,10 +573,10 @@
 
   // Add the chrome browser launch info.
   ::full_restore::SaveAppLaunchInfo(
-      profile()->GetPath(), std::make_unique<app_restore::AppLaunchInfo>(
+      profile()->GetPath(), std::make_unique<::app_restore::AppLaunchInfo>(
                                 extension_misc::kChromeAppId, kWindowId1));
 
-  auto app_launch_info = std::make_unique<app_restore::AppLaunchInfo>(
+  auto app_launch_info = std::make_unique<::app_restore::AppLaunchInfo>(
       extension_misc::kChromeAppId, kWindowId2);
   app_launch_info->app_type_browser = true;
   ::full_restore::SaveAppLaunchInfo(profile()->GetPath(),
@@ -602,10 +604,10 @@
 
   // Add the chrome browser launch info.
   ::full_restore::SaveAppLaunchInfo(
-      profile()->GetPath(), std::make_unique<app_restore::AppLaunchInfo>(
+      profile()->GetPath(), std::make_unique<::app_restore::AppLaunchInfo>(
                                 extension_misc::kChromeAppId, kWindowId1));
 
-  auto app_launch_info = std::make_unique<app_restore::AppLaunchInfo>(
+  auto app_launch_info = std::make_unique<::app_restore::AppLaunchInfo>(
       extension_misc::kChromeAppId, kWindowId2);
   app_launch_info->app_type_browser = true;
   ::full_restore::SaveAppLaunchInfo(profile()->GetPath(),
@@ -655,10 +657,10 @@
 
   // Add the chrome browser launch info.
   ::full_restore::SaveAppLaunchInfo(
-      profile()->GetPath(), std::make_unique<app_restore::AppLaunchInfo>(
+      profile()->GetPath(), std::make_unique<::app_restore::AppLaunchInfo>(
                                 extension_misc::kChromeAppId, kWindowId1));
 
-  auto app_launch_info = std::make_unique<app_restore::AppLaunchInfo>(
+  auto app_launch_info = std::make_unique<::app_restore::AppLaunchInfo>(
       extension_misc::kChromeAppId, kWindowId2);
   app_launch_info->app_type_browser = true;
   ::full_restore::SaveAppLaunchInfo(profile()->GetPath(),
@@ -715,7 +717,7 @@
   // Add app launch info, but no browser launch info.
   ::full_restore::SaveAppLaunchInfo(
       profile()->GetPath(),
-      std::make_unique<app_restore::AppLaunchInfo>(
+      std::make_unique<::app_restore::AppLaunchInfo>(
           kAppId, kWindowId2,
           apps::mojom::LaunchContainer::kLaunchContainerWindow,
           WindowOpenDisposition::NEW_WINDOW, display::kDefaultDisplayId,
@@ -745,10 +747,10 @@
 
   // Add the chrome browser launch info.
   ::full_restore::SaveAppLaunchInfo(
-      profile()->GetPath(), std::make_unique<app_restore::AppLaunchInfo>(
+      profile()->GetPath(), std::make_unique<::app_restore::AppLaunchInfo>(
                                 extension_misc::kChromeAppId, kWindowId1));
 
-  auto app_launch_info = std::make_unique<app_restore::AppLaunchInfo>(
+  auto app_launch_info = std::make_unique<::app_restore::AppLaunchInfo>(
       extension_misc::kChromeAppId, kWindowId2);
   app_launch_info->app_type_browser = true;
   ::full_restore::SaveAppLaunchInfo(profile()->GetPath(),
@@ -780,11 +782,11 @@
 
   // Add app launch infos.
   ::full_restore::SaveAppLaunchInfo(
-      profile()->GetPath(), std::make_unique<app_restore::AppLaunchInfo>(
+      profile()->GetPath(), std::make_unique<::app_restore::AppLaunchInfo>(
                                 extension_misc::kChromeAppId, kWindowId1));
   ::full_restore::SaveAppLaunchInfo(
       profile()->GetPath(),
-      std::make_unique<app_restore::AppLaunchInfo>(
+      std::make_unique<::app_restore::AppLaunchInfo>(
           kAppId, kWindowId2,
           apps::mojom::LaunchContainer::kLaunchContainerWindow,
           WindowOpenDisposition::NEW_WINDOW, display::kDefaultDisplayId,
@@ -813,11 +815,11 @@
 
   // Add app launch infos.
   ::full_restore::SaveAppLaunchInfo(
-      profile()->GetPath(), std::make_unique<app_restore::AppLaunchInfo>(
+      profile()->GetPath(), std::make_unique<::app_restore::AppLaunchInfo>(
                                 extension_misc::kChromeAppId, kWindowId1));
   ::full_restore::SaveAppLaunchInfo(
       profile()->GetPath(),
-      std::make_unique<app_restore::AppLaunchInfo>(
+      std::make_unique<::app_restore::AppLaunchInfo>(
           kAppId, kWindowId2,
           apps::mojom::LaunchContainer::kLaunchContainerWindow,
           WindowOpenDisposition::NEW_WINDOW, display::kDefaultDisplayId,
@@ -847,7 +849,7 @@
   size_t count = BrowserList::GetInstance()->size();
 
   ::full_restore::SaveAppLaunchInfo(
-      profile()->GetPath(), std::make_unique<app_restore::AppLaunchInfo>(
+      profile()->GetPath(), std::make_unique<::app_restore::AppLaunchInfo>(
                                 extension_misc::kChromeAppId, kWindowId1));
 
   CreateAndSaveWindowInfo(kDeskId, kCurrentBounds, kWindowStateType);
@@ -864,7 +866,7 @@
   // TODO(sammiequon): Check the values from the actual browser window.
   auto window = std::make_unique<aura::Window>(nullptr);
   window->Init(ui::LAYER_NOT_DRAWN);
-  window->SetProperty(app_restore::kRestoreWindowIdKey, kWindowId1);
+  window->SetProperty(::app_restore::kRestoreWindowIdKey, kWindowId1);
   auto stored_window_info = ::full_restore::GetWindowInfo(window.get());
   EXPECT_EQ(kDeskId, *stored_window_info->desk_id);
   EXPECT_EQ(kCurrentBounds, *stored_window_info->current_bounds);
@@ -905,7 +907,7 @@
   // Create Full Restore launch data before launching any browser, simulating
   // Full Restore data being saved prior to restart.
   ::full_restore::SaveAppLaunchInfo(
-      profile()->GetPath(), std::make_unique<app_restore::AppLaunchInfo>(
+      profile()->GetPath(), std::make_unique<::app_restore::AppLaunchInfo>(
                                 extension_misc::kChromeAppId, kRestoreId));
   CreateAndSaveWindowInfo(kDeskId, kCurrentBounds,
                           chromeos::WindowStateType::kNormal,
@@ -989,13 +991,14 @@
 
   window = app_window->GetNativeWindow();
   ASSERT_TRUE(window);
-  int restore_window_id = window->GetProperty(app_restore::kRestoreWindowIdKey);
+  int restore_window_id =
+      window->GetProperty(::app_restore::kRestoreWindowIdKey);
   EXPECT_NE(0, restore_window_id);
 
-  auto* window_info = window->GetProperty(app_restore::kWindowInfoKey);
+  auto* window_info = window->GetProperty(::app_restore::kWindowInfoKey);
   ASSERT_TRUE(window_info);
   EXPECT_TRUE(window_info->activation_index.has_value());
-  int32_t* index = window->GetProperty(app_restore::kActivationIndexKey);
+  int32_t* index = window->GetProperty(::app_restore::kActivationIndexKey);
   ASSERT_TRUE(index);
   EXPECT_EQ(kActivationIndex, *index);
   EXPECT_EQ(kDeskId, window->GetProperty(aura::client::kWindowWorkspaceKey));
@@ -1092,7 +1095,7 @@
   ASSERT_TRUE(app_window1);
   window1 = app_window1->GetNativeWindow();
   ASSERT_TRUE(window1);
-  EXPECT_NE(0, window1->GetProperty(app_restore::kRestoreWindowIdKey));
+  EXPECT_NE(0, window1->GetProperty(::app_restore::kRestoreWindowIdKey));
 
   auto window_info = ::full_restore::GetWindowInfo(window1);
   ASSERT_TRUE(window_info);
@@ -1103,7 +1106,7 @@
   ASSERT_TRUE(app_window2);
   window2 = app_window2->GetNativeWindow();
   ASSERT_TRUE(window2);
-  EXPECT_NE(0, window2->GetProperty(app_restore::kRestoreWindowIdKey));
+  EXPECT_NE(0, window2->GetProperty(::app_restore::kRestoreWindowIdKey));
 
   window_info = ::full_restore::GetWindowInfo(window2);
   ASSERT_TRUE(window_info);
@@ -1115,7 +1118,7 @@
   ASSERT_TRUE(app_window);
   auto* window = app_window->GetNativeWindow();
   ASSERT_TRUE(window);
-  EXPECT_EQ(0, window->GetProperty(app_restore::kRestoreWindowIdKey));
+  EXPECT_EQ(0, window->GetProperty(::app_restore::kRestoreWindowIdKey));
 
   // Close the window.
   CloseAppWindow(app_window1);
@@ -1139,7 +1142,7 @@
   ASSERT_TRUE(app_window);
 
   // Toggle immersive fullscreen by simulating what happens when F4 is pressed.
-  // FullRestoreController will save to file when the state changes.
+  // WindowRestoreController will save to file when the state changes.
   const ash::WMEvent event(ash::WM_EVENT_TOGGLE_FULLSCREEN);
   ash::WindowState::Get(app_window->GetNativeWindow())->OnWMEvent(&event);
 
@@ -1248,7 +1251,7 @@
 
   void SaveAppLaunchInfo(const std::string& app_id, int32_t session_id) {
     ::full_restore::SaveAppLaunchInfo(
-        profile()->GetPath(), std::make_unique<app_restore::AppLaunchInfo>(
+        profile()->GetPath(), std::make_unique<::app_restore::AppLaunchInfo>(
                                   app_id, ui::EventFlags::EF_NONE, session_id,
                                   display::kDefaultDisplayId));
   }
@@ -1257,7 +1260,7 @@
     test_full_restore_info_observer_.Reset();
 
     arc_app_launch_handler_ =
-        FullRestoreArcTaskHandler::GetForProfile(profile())
+        app_restore::AppRestoreArcTaskHandler::GetForProfile(profile())
             ->arc_app_launch_handler();
     arc_app_launch_handler_->is_app_connection_ready_ = false;
 
@@ -1294,11 +1297,11 @@
                             int32_t restore_window_id,
                             bool hidden) {
     ASSERT_TRUE(window);
-    EXPECT_EQ(window_id, window->GetProperty(app_restore::kWindowIdKey));
+    EXPECT_EQ(window_id, window->GetProperty(::app_restore::kWindowIdKey));
     EXPECT_EQ(restore_window_id,
-              window->GetProperty(app_restore::kRestoreWindowIdKey));
+              window->GetProperty(::app_restore::kRestoreWindowIdKey));
     EXPECT_EQ(hidden,
-              window->GetProperty(app_restore::kParentToHiddenContainerKey));
+              window->GetProperty(::app_restore::kParentToHiddenContainerKey));
   }
 
   void VerifyWindowInfo(aura::Window* window,
@@ -1402,7 +1405,7 @@
   }
 
  protected:
-  ArcAppLaunchHandler* arc_app_launch_handler_ = nullptr;
+  app_restore::ArcAppLaunchHandler* arc_app_launch_handler_ = nullptr;
 
  private:
   arc::ArcSessionManager* arc_session_manager() {
@@ -1670,7 +1673,7 @@
 
   // Simulate creating the task for the restored window.
   int32_t kTaskId2 = 200;
-  window->SetProperty(app_restore::kWindowIdKey, kTaskId2);
+  window->SetProperty(::app_restore::kWindowIdKey, kTaskId2);
   CreateTask(app_id, kTaskId2, session_id2);
 
   VerifyWindowProperty(window, kTaskId2, kTaskId1, /*hidden=*/false);
@@ -1777,7 +1780,7 @@
   // Simulate creating the task for the restored window.
   int32_t kTaskId2 = 200;
   CreateTask(app_id, kTaskId2, session_id3);
-  window->SetProperty(app_restore::kWindowIdKey, kTaskId2);
+  window->SetProperty(::app_restore::kWindowIdKey, kTaskId2);
 
   VerifyWindowProperty(window, kTaskId2, session_id2, /*hidden=*/false);
   VerifyWindowInfo(window, kActivationIndex);
@@ -2022,7 +2025,7 @@
   void OnAppConnectionReady() {
     if (!arc_app_launch_handler_) {
       arc_app_launch_handler_ =
-          FullRestoreArcTaskHandler::GetForProfile(profile())
+          app_restore::AppRestoreArcTaskHandler::GetForProfile(profile())
               ->arc_app_launch_handler();
     }
     arc_app_launch_handler_->OnAppConnectionReady();
@@ -2110,8 +2113,8 @@
   VerifyNoRestoreData(app_id2);
 
   OnAppConnectionReady();
-  EXPECT_EQ(
-      1, histogram_tester.GetBucketCount(kRestoredAppWindowCountHistogram, 1));
+  EXPECT_EQ(1, histogram_tester.GetBucketCount(
+                   app_restore::kRestoredAppWindowCountHistogram, 1));
 
   // Remove app_id1, and verify windows and restore data for `app_id1` have been
   // removed.
@@ -2203,8 +2206,8 @@
   VerifyRestoreData(app_id2, kTaskId2);
 
   OnAppConnectionReady();
-  EXPECT_EQ(
-      1, histogram_tester.GetBucketCount(kRestoredAppWindowCountHistogram, 2));
+  EXPECT_EQ(1, histogram_tester.GetBucketCount(
+                   app_restore::kRestoredAppWindowCountHistogram, 2));
 
   StopInstance();
 }
@@ -2254,8 +2257,8 @@
   VerifyNoRestoreData(app_id2);
 
   OnAppConnectionReady();
-  EXPECT_EQ(
-      1, histogram_tester.GetBucketCount(kRestoredAppWindowCountHistogram, 1));
+  EXPECT_EQ(1, histogram_tester.GetBucketCount(
+                   app_restore::kRestoredAppWindowCountHistogram, 1));
 
   StopInstance();
 }
@@ -2314,8 +2317,8 @@
   VerifyWindows(activation_index1, app_id1, kTaskId1);
 
   OnAppConnectionReady();
-  EXPECT_EQ(
-      1, histogram_tester.GetBucketCount(kRestoredAppWindowCountHistogram, 1));
+  EXPECT_EQ(1, histogram_tester.GetBucketCount(
+                   app_restore::kRestoredAppWindowCountHistogram, 1));
 
   // Modify `app_id2` status to be ready to prepare launching `app_id2`.
   UpdateApp(app_id2, apps::mojom::Readiness::kReady);
@@ -2386,8 +2389,8 @@
   VerifyWindows(activation_index1, app_id1, kTaskId1);
   VerifyNoStackWindows(app_id2, kTaskId2);
 
-  EXPECT_EQ(
-      1, histogram_tester.GetBucketCount(kRestoredAppWindowCountHistogram, 2));
+  EXPECT_EQ(1, histogram_tester.GetBucketCount(
+                   app_restore::kRestoredAppWindowCountHistogram, 2));
 
   StopInstance();
 }
@@ -2498,7 +2501,7 @@
 
   // Get the window id.
   aura::Window* window = app_browser->window()->GetNativeWindow();
-  int32_t window_id = window->GetProperty(app_restore::kWindowIdKey);
+  int32_t window_id = window->GetProperty(::app_restore::kWindowIdKey);
 
   WaitForAppLaunchInfoSaved();
 
@@ -2523,7 +2526,7 @@
   // Get the restore window id.
   window = restore_app_browser->window()->GetNativeWindow();
   int32_t restore_window_id =
-      window->GetProperty(app_restore::kRestoreWindowIdKey);
+      window->GetProperty(::app_restore::kRestoreWindowIdKey);
 
   EXPECT_EQ(window_id, restore_window_id);
 }
@@ -2538,7 +2541,7 @@
 
   // Get the window id.
   aura::Window* window = app_browser->window()->GetNativeWindow();
-  int32_t window_id = window->GetProperty(app_restore::kWindowIdKey);
+  int32_t window_id = window->GetProperty(::app_restore::kWindowIdKey);
 
   SaveWindowInfo(window);
   WaitForAppLaunchInfoSaved();
@@ -2574,7 +2577,7 @@
 
   // Get the window id.
   aura::Window* window = app_browser->window()->GetNativeWindow();
-  int32_t window_id = window->GetProperty(app_restore::kWindowIdKey);
+  int32_t window_id = window->GetProperty(::app_restore::kWindowIdKey);
 
   WaitForAppLaunchInfoSaved();
 
@@ -2610,7 +2613,7 @@
   // Get the restore window id.
   window = restore_app_browser->window()->GetNativeWindow();
   int32_t restore_window_id =
-      window->GetProperty(app_restore::kRestoreWindowIdKey);
+      window->GetProperty(::app_restore::kRestoreWindowIdKey);
 
   EXPECT_EQ(window_id, restore_window_id);
 }
@@ -2625,7 +2628,7 @@
 
   // Get the window id.
   aura::Window* window1 = app_browser1->window()->GetNativeWindow();
-  int32_t window_id1 = window1->GetProperty(app_restore::kWindowIdKey);
+  int32_t window_id1 = window1->GetProperty(::app_restore::kWindowIdKey);
 
   WaitForAppLaunchInfoSaved();
   ::full_restore::FullRestoreSaveHandler::GetInstance()->ClearForTesting();
@@ -2651,7 +2654,7 @@
   Browser* app_browser2 = LaunchMediaSystemWebApp();
   ASSERT_TRUE(app_browser2);
   aura::Window* window2 = app_browser2->window()->GetNativeWindow();
-  int32_t window_id2 = window2->GetProperty(app_restore::kWindowIdKey);
+  int32_t window_id2 = window2->GetProperty(::app_restore::kWindowIdKey);
 
   WaitForAppLaunchInfoSaved(/*allow_save=*/false);
   ::full_restore::FullRestoreSaveHandler::GetInstance()->ClearForTesting();
@@ -2681,7 +2684,7 @@
   // Get the restore window id.
   window1 = restore_app_browser->window()->GetNativeWindow();
   int32_t restore_window_id =
-      window1->GetProperty(app_restore::kRestoreWindowIdKey);
+      window1->GetProperty(::app_restore::kRestoreWindowIdKey);
 
   EXPECT_EQ(window_id1, restore_window_id);
 }
@@ -2696,7 +2699,7 @@
 
   // Get the window id.
   aura::Window* window1 = app_browser1->window()->GetNativeWindow();
-  int32_t window_id1 = window1->GetProperty(app_restore::kWindowIdKey);
+  int32_t window_id1 = window1->GetProperty(::app_restore::kWindowIdKey);
 
   WaitForAppLaunchInfoSaved();
   ::full_restore::FullRestoreSaveHandler::GetInstance()->ClearForTesting();
@@ -2722,7 +2725,7 @@
       LaunchMediaSystemWebApp(apps::mojom::LaunchSource::kFromShelf);
   ASSERT_TRUE(app_browser2);
   aura::Window* window2 = app_browser2->window()->GetNativeWindow();
-  int32_t window_id2 = window2->GetProperty(app_restore::kWindowIdKey);
+  int32_t window_id2 = window2->GetProperty(::app_restore::kWindowIdKey);
 
   WaitForAppLaunchInfoSaved(/*allow_save=*/false);
   ::full_restore::FullRestoreSaveHandler::GetInstance()->ClearForTesting();
@@ -2755,7 +2758,7 @@
   // Get the restore window id.
   window2 = restore_app_browser->window()->GetNativeWindow();
   int32_t restore_window_id =
-      window2->GetProperty(app_restore::kRestoreWindowIdKey);
+      window2->GetProperty(::app_restore::kRestoreWindowIdKey);
 
   EXPECT_EQ(window_id2, restore_window_id);
 }
@@ -2768,7 +2771,7 @@
 
   // Get the window id.
   aura::Window* window = app_browser->window()->GetNativeWindow();
-  int32_t window_id = window->GetProperty(app_restore::kWindowIdKey);
+  int32_t window_id = window->GetProperty(::app_restore::kWindowIdKey);
 
   // Snap |window| to the left and store its window properties.
   // TODO(sammiequon): Store and check desk id and restore bounds.
@@ -2799,7 +2802,7 @@
 
   // Get the restored browser's window.
   window = restore_app_browser->window()->GetNativeWindow();
-  ASSERT_EQ(window_id, window->GetProperty(app_restore::kRestoreWindowIdKey));
+  ASSERT_EQ(window_id, window->GetProperty(::app_restore::kRestoreWindowIdKey));
 
   // Check that |window|'s properties match the one's we stored.
   EXPECT_EQ(pre_save_bounds, window->GetBoundsInScreen());
@@ -2832,8 +2835,8 @@
   ASSERT_EQ(app1_window, split_view_test_api.GetLeftWindow());
   ASSERT_EQ(app2_window, split_view_test_api.GetRightWindow());
 
-  const int32_t app1_id = app1_window->GetProperty(app_restore::kWindowIdKey);
-  const int32_t app2_id = app2_window->GetProperty(app_restore::kWindowIdKey);
+  const int32_t app1_id = app1_window->GetProperty(::app_restore::kWindowIdKey);
+  const int32_t app2_id = app2_window->GetProperty(::app_restore::kWindowIdKey);
 
   SaveWindowInfo(app1_window);
   SaveWindowInfo(app2_window);
@@ -2855,11 +2858,11 @@
   // Find the restored app windows in the browser list.
   for (Browser* browser : *BrowserList::GetInstance()) {
     aura::Window* native_window = browser->window()->GetNativeWindow();
-    if (native_window->GetProperty(app_restore::kRestoreWindowIdKey) ==
+    if (native_window->GetProperty(::app_restore::kRestoreWindowIdKey) ==
         app1_id) {
       restore_app1_window = native_window;
     }
-    if (native_window->GetProperty(app_restore::kRestoreWindowIdKey) ==
+    if (native_window->GetProperty(::app_restore::kRestoreWindowIdKey) ==
         app2_id) {
       restore_app2_window = native_window;
     }
diff --git a/chrome/browser/ash/app_restore/full_restore_arc_task_handler_factory.cc b/chrome/browser/ash/app_restore/full_restore_arc_task_handler_factory.cc
deleted file mode 100644
index 62d8e0f..0000000
--- a/chrome/browser/ash/app_restore/full_restore_arc_task_handler_factory.cc
+++ /dev/null
@@ -1,52 +0,0 @@
-// 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 "chrome/browser/ash/app_restore/full_restore_arc_task_handler_factory.h"
-
-#include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
-#include "chrome/browser/ash/app_restore/full_restore_arc_task_handler.h"
-#include "chrome/browser/ash/arc/arc_util.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.h"
-#include "components/app_restore/features.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
-
-namespace ash {
-namespace full_restore {
-
-// static
-FullRestoreArcTaskHandler* FullRestoreArcTaskHandlerFactory::GetForProfile(
-    Profile* profile) {
-  return static_cast<FullRestoreArcTaskHandler*>(
-      FullRestoreArcTaskHandlerFactory::GetInstance()
-          ->GetServiceForBrowserContext(profile, /*create=*/true));
-}
-
-// static
-FullRestoreArcTaskHandlerFactory*
-FullRestoreArcTaskHandlerFactory::GetInstance() {
-  return base::Singleton<FullRestoreArcTaskHandlerFactory>::get();
-}
-
-FullRestoreArcTaskHandlerFactory::FullRestoreArcTaskHandlerFactory()
-    : BrowserContextKeyedServiceFactory(
-          "FullRestoreArcTaskHandler",
-          BrowserContextDependencyManager::GetInstance()) {
-  DependsOn(ArcAppListPrefsFactory::GetInstance());
-  DependsOn(apps::AppServiceProxyFactory::GetInstance());
-}
-
-KeyedService* FullRestoreArcTaskHandlerFactory::BuildServiceInstanceFor(
-    content::BrowserContext* context) const {
-  if (!::full_restore::features::IsFullRestoreEnabled())
-    return nullptr;
-
-  if (!arc::IsArcAllowedForProfile(Profile::FromBrowserContext(context)))
-    return nullptr;
-
-  return new FullRestoreArcTaskHandler(Profile::FromBrowserContext(context));
-}
-
-}  // namespace full_restore
-}  // namespace ash
diff --git a/chrome/browser/ash/app_restore/full_restore_arc_task_handler_factory.h b/chrome/browser/ash/app_restore/full_restore_arc_task_handler_factory.h
deleted file mode 100644
index d4158af..0000000
--- a/chrome/browser/ash/app_restore/full_restore_arc_task_handler_factory.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// 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.
-
-#ifndef CHROME_BROWSER_ASH_APP_RESTORE_FULL_RESTORE_ARC_TASK_HANDLER_FACTORY_H_
-#define CHROME_BROWSER_ASH_APP_RESTORE_FULL_RESTORE_ARC_TASK_HANDLER_FACTORY_H_
-
-#include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
-
-class Profile;
-
-namespace ash {
-namespace full_restore {
-
-class FullRestoreArcTaskHandler;
-
-class FullRestoreArcTaskHandlerFactory
-    : public BrowserContextKeyedServiceFactory {
- public:
-  static FullRestoreArcTaskHandler* GetForProfile(Profile* profile);
-
-  static FullRestoreArcTaskHandlerFactory* GetInstance();
-
- private:
-  friend struct base::DefaultSingletonTraits<FullRestoreArcTaskHandlerFactory>;
-
-  FullRestoreArcTaskHandlerFactory();
-  FullRestoreArcTaskHandlerFactory(const FullRestoreArcTaskHandlerFactory&) =
-      delete;
-  FullRestoreArcTaskHandlerFactory& operator=(
-      const FullRestoreArcTaskHandlerFactory&) = delete;
-  ~FullRestoreArcTaskHandlerFactory() override = default;
-
-  // BrowserContextKeyedServiceFactory.
-  KeyedService* BuildServiceInstanceFor(
-      content::BrowserContext* context) const override;
-};
-
-}  // namespace full_restore
-}  // namespace ash
-
-#endif  // CHROME_BROWSER_ASH_APP_RESTORE_FULL_RESTORE_ARC_TASK_HANDLER_FACTORY_H_
diff --git a/chrome/browser/ash/app_restore/full_restore_policy_browsertest.cc b/chrome/browser/ash/app_restore/full_restore_policy_browsertest.cc
index 8fddb90..61244b5 100644
--- a/chrome/browser/ash/app_restore/full_restore_policy_browsertest.cc
+++ b/chrome/browser/ash/app_restore/full_restore_policy_browsertest.cc
@@ -6,7 +6,7 @@
 
 #include "ash/constants/ash_switches.h"
 #include "base/test/scoped_feature_list.h"
-#include "chrome/browser/ash/app_restore/full_restore_arc_task_handler.h"
+#include "chrome/browser/ash/app_restore/app_restore_arc_task_handler.h"
 #include "chrome/browser/ash/app_restore/full_restore_prefs.h"
 #include "chrome/browser/ash/app_restore/full_restore_service.h"
 #include "chrome/browser/ash/arc/arc_util.h"
@@ -80,10 +80,12 @@
     ASSERT_FALSE(FullRestoreService::GetForProfile(browser()->profile()));
 
   if (ghost_window_enabled()) {
-    ASSERT_TRUE(FullRestoreArcTaskHandler::GetForProfile(browser()->profile())
+    ASSERT_TRUE(app_restore::AppRestoreArcTaskHandler::GetForProfile(
+                    browser()->profile())
                     ->window_handler());
   } else {
-    ASSERT_FALSE(FullRestoreArcTaskHandler::GetForProfile(browser()->profile())
+    ASSERT_FALSE(app_restore::AppRestoreArcTaskHandler::GetForProfile(
+                     browser()->profile())
                      ->window_handler());
   }
 }
diff --git a/chrome/browser/ash/arc/input_method_manager/arc_input_method_manager_service.cc b/chrome/browser/ash/arc/input_method_manager/arc_input_method_manager_service.cc
index a55412e0..76c1ead 100644
--- a/chrome/browser/ash/arc/input_method_manager/arc_input_method_manager_service.cc
+++ b/chrome/browser/ash/arc/input_method_manager/arc_input_method_manager_service.cc
@@ -57,11 +57,12 @@
   // TODO(yhanana): We should prevent InputMethodManager from changing current
   // input method until this callback is called with true and once it's done the
   // IME switching code below can be removed.
-  LOG(ERROR) << "Switch the active IME to \"" << ime_id << "\"(component_id=\""
+  LOG(ERROR) << "Switch the current IME to \"" << ime_id << "\"(component_id=\""
              << component_id << "\") failed";
   auto* imm = ash::input_method::InputMethodManager::Get();
   if (imm && imm->GetActiveIMEState()) {
-    for (const auto& id : imm->GetActiveIMEState()->GetActiveInputMethodIds()) {
+    for (const auto& id :
+         imm->GetActiveIMEState()->GetEnabledInputMethodIds()) {
       if (!ash::extension_ime_util::IsArcIME(id)) {
         imm->GetActiveIMEState()->ChangeInputMethod(id,
                                                     false /* show_message */);
@@ -415,11 +416,11 @@
   if (ime_id == kChromeOSIMEIdInArcContainer) {
     // Chrome OS Keyboard is selected in Android side.
     auto* imm = ash::input_method::InputMethodManager::Get();
-    // Create a list of active Chrome OS IMEs.
-    auto active_imes = imm->GetActiveIMEState()->GetActiveInputMethodIds();
-    base::EraseIf(active_imes, ash::extension_ime_util::IsArcIME);
-    DCHECK(!active_imes.empty());
-    imm->GetActiveIMEState()->ChangeInputMethod(active_imes[0],
+    // Create a list of enabled Chrome OS IMEs.
+    auto enabled_imes = imm->GetActiveIMEState()->GetEnabledInputMethodIds();
+    base::EraseIf(enabled_imes, ash::extension_ime_util::IsArcIME);
+    DCHECK(!enabled_imes.empty());
+    imm->GetActiveIMEState()->ChangeInputMethod(enabled_imes[0],
                                                 false /* show_message */);
     return;
   }
@@ -460,7 +461,7 @@
 
   base::AutoReset<bool> in_updating(&is_updating_imm_entry_, true);
   scoped_refptr<InputMethodManager::State> state = imm->GetActiveIMEState();
-  const std::string active_ime_id = state->GetCurrentInputMethod().id();
+  const std::string current_ime_id = state->GetCurrentInputMethod().id();
 
   // Remove the old registered entry.
   state->RemoveInputMethodExtension(proxy_ime_extension_id_);
@@ -486,13 +487,13 @@
   for (const auto& descriptor : arc_ime_state_.GetEnabledInputMethods())
     state->EnableInputMethod(descriptor.id());
 
-  state->ChangeInputMethod(active_ime_id, false);
+  state->ChangeInputMethod(current_ime_id, false);
   is_updating_imm_entry_ = false;
 
   // Call ImeMenuListChanged() here to notify the latest state.
   ImeMenuListChanged();
-  // If the active input method is changed, call InputMethodChanged() here.
-  if (active_ime_id != state->GetCurrentInputMethod().id())
+  // If the current input method is changed, call InputMethodChanged() here.
+  if (current_ime_id != state->GetCurrentInputMethod().id())
     InputMethodChanged(InputMethodManager::Get(), nullptr, false);
 }
 
@@ -519,36 +520,37 @@
     return;
   }
 
-  auto new_active_ime_ids =
-      manager->GetActiveIMEState()->GetActiveInputMethodIds();
+  auto new_enabled_ime_ids =
+      manager->GetActiveIMEState()->GetEnabledInputMethodIds();
 
   // Filter out non ARC IME ids.
-  std::set<std::string> new_arc_active_ime_ids;
+  std::set<std::string> new_arc_enabled_ime_ids;
   std::copy_if(
-      new_active_ime_ids.begin(), new_active_ime_ids.end(),
-      std::inserter(new_arc_active_ime_ids, new_arc_active_ime_ids.end()),
+      new_enabled_ime_ids.begin(), new_enabled_ime_ids.end(),
+      std::inserter(new_arc_enabled_ime_ids, new_arc_enabled_ime_ids.end()),
       [](const auto& id) { return ash::extension_ime_util::IsArcIME(id); });
 
   // TODO(yhanada|yusukes): Instead of observing ImeMenuListChanged(), it's
   // probably better to just observe the pref (and not disabling ones still
   // in the prefs.) See also the comment below in the second for-loop.
-  const std::set<std::string> active_ime_ids_on_prefs = prefs_.GetEnabledImes();
+  const std::set<std::string> enabled_ime_ids_on_prefs =
+      prefs_.GetEnabledImes();
 
-  for (const auto& id : new_arc_active_ime_ids) {
+  for (const auto& id : new_arc_enabled_ime_ids) {
     // Enable the IME which is not currently enabled.
-    if (!active_arc_ime_ids_.count(id))
+    if (!enabled_arc_ime_ids_.count(id))
       EnableIme(id, true /* enable */);
   }
 
-  for (const auto& id : active_arc_ime_ids_) {
-    if (!new_arc_active_ime_ids.count(id) &&
-        !active_ime_ids_on_prefs.count(id)) {
+  for (const auto& id : enabled_arc_ime_ids_) {
+    if (!new_arc_enabled_ime_ids.count(id) &&
+        !enabled_ime_ids_on_prefs.count(id)) {
       // This path is taken in the following two cases:
       // 1) The device is in tablet mode, and the user disabled the IME via
       //    chrome://settings.
       // 2) The device was just switched to laptop mode, and this service
       //    disallowed Android IMEs.
-      // In the former case, |active_ime_ids_on_prefs| doesn't have the IME,
+      // In the former case, |enabled_ime_ids_on_prefs| doesn't have the IME,
       // but in the latter case, the set still has it. Here, disable the IME
       // only for the former case so that the temporary deactivation of the
       // IME on laptop mode wouldn't be propagated to the container. Otherwise,
@@ -558,7 +560,7 @@
       EnableIme(id, false /* enable */);
     }
   }
-  active_arc_ime_ids_.swap(new_arc_active_ime_ids);
+  enabled_arc_ime_ids_.swap(new_arc_enabled_ime_ids);
 }
 
 void ArcInputMethodManagerService::InputMethodChanged(
diff --git a/chrome/browser/ash/arc/input_method_manager/arc_input_method_manager_service.h b/chrome/browser/ash/arc/input_method_manager/arc_input_method_manager_service.h
index 9acefdc..fee21ba5a 100644
--- a/chrome/browser/ash/arc/input_method_manager/arc_input_method_manager_service.h
+++ b/chrome/browser/ash/arc/input_method_manager/arc_input_method_manager_service.h
@@ -138,7 +138,7 @@
   Profile* const profile_;
 
   std::unique_ptr<ArcInputMethodManagerBridge> imm_bridge_;
-  std::set<std::string> active_arc_ime_ids_;
+  std::set<std::string> enabled_arc_ime_ids_;
   std::unique_ptr<ArcInputMethodState::Delegate> arc_ime_state_delegate_;
   ArcInputMethodState arc_ime_state_;
   InputMethodPrefs prefs_;
@@ -153,7 +153,7 @@
   const std::string proxy_ime_extension_id_;
   std::unique_ptr<ash::input_method::InputMethodEngine> proxy_ime_engine_;
 
-  // The currently active input method, observed for
+  // The current (active) input method, observed for
   // OnShowVirtualKeyboardIfEnabled.
   ui::InputMethod* input_method_ = nullptr;
   bool is_arc_ime_active_ = false;
diff --git a/chrome/browser/ash/arc/input_method_manager/arc_input_method_manager_service_unittest.cc b/chrome/browser/ash/arc/input_method_manager/arc_input_method_manager_service_unittest.cc
index 365edbc..d7d9b8c 100644
--- a/chrome/browser/ash/arc/input_method_manager/arc_input_method_manager_service_unittest.cc
+++ b/chrome/browser/ash/arc/input_method_manager/arc_input_method_manager_service_unittest.cc
@@ -132,15 +132,15 @@
   class TestState : public im::MockInputMethodManager::State {
    public:
     TestState()
-        : added_input_method_extensions_(), active_input_method_ids_() {}
+        : added_input_method_extensions_(), enabled_input_method_ids_() {}
 
-    const std::vector<std::string>& GetActiveInputMethodIds() const override {
-      return active_input_method_ids_;
+    const std::vector<std::string>& GetEnabledInputMethodIds() const override {
+      return enabled_input_method_ids_;
     }
 
     im::InputMethodDescriptor GetCurrentInputMethod() const override {
       im::InputMethodDescriptor descriptor(
-          active_ime_id_, "", "", "", std::vector<std::string>(),
+          current_ime_id_, "", "", "", std::vector<std::string>(),
           false /* is_login_keyboard */, GURL(), GURL());
       return descriptor;
     }
@@ -158,30 +158,30 @@
     }
 
     bool EnableInputMethod(
-        const std::string& new_active_input_method_id) override {
-      enabled_input_methods_.push_back(new_active_input_method_id);
+        const std::string& new_enabled_input_method_id) override {
+      enabled_input_methods_.push_back(new_enabled_input_method_id);
       return true;
     }
 
-    void AddActiveInputMethodId(const std::string& ime_id) {
-      if (!std::count(active_input_method_ids_.begin(),
-                      active_input_method_ids_.end(), ime_id)) {
-        active_input_method_ids_.push_back(ime_id);
+    void AddEnabledInputMethodId(const std::string& ime_id) {
+      if (!std::count(enabled_input_method_ids_.begin(),
+                      enabled_input_method_ids_.end(), ime_id)) {
+        enabled_input_method_ids_.push_back(ime_id);
       }
     }
 
-    void RemoveActiveInputMethodId(const std::string& ime_id) {
-      base::EraseIf(active_input_method_ids_,
+    void RemoveEnabledInputMethodId(const std::string& ime_id) {
+      base::EraseIf(enabled_input_method_ids_,
                     [&ime_id](const std::string& id) { return id == ime_id; });
     }
 
-    void SetActiveInputMethod(const std::string& ime_id) {
-      active_ime_id_ = ime_id;
+    void SetCurrentInputMethod(const std::string& ime_id) {
+      current_ime_id_ = ime_id;
     }
 
     void GetInputMethodExtensions(
         im::InputMethodDescriptors* descriptors) override {
-      for (const auto& id : active_input_method_ids_) {
+      for (const auto& id : enabled_input_method_ids_) {
         descriptors->push_back(im::InputMethodDescriptor(
             id, "", "", {}, {}, false, GURL(), GURL()));
       }
@@ -205,8 +205,8 @@
     ~TestState() override = default;
 
    private:
-    std::vector<std::string> active_input_method_ids_;
-    std::string active_ime_id_;
+    std::vector<std::string> enabled_input_method_ids_;
+    std::string current_ime_id_;
   };
 
   TestInputMethodManager() {
@@ -335,16 +335,16 @@
       aeiu::GetArcInputMethodID(GenerateId("test.arc.ime"), "us");
 
   // EnableIme is called only when ARC IME is enable or disabled.
-  imm()->state()->AddActiveInputMethodId(extension_ime_id);
+  imm()->state()->AddEnabledInputMethodId(extension_ime_id);
   service()->ImeMenuListChanged();
   EXPECT_EQ(0u, bridge()->enable_ime_calls_.size());
 
-  imm()->state()->AddActiveInputMethodId(component_extension_ime_id);
+  imm()->state()->AddEnabledInputMethodId(component_extension_ime_id);
   service()->ImeMenuListChanged();
   EXPECT_EQ(0u, bridge()->enable_ime_calls_.size());
 
   // Enable the ARC IME and verify that EnableIme is called.
-  imm()->state()->AddActiveInputMethodId(arc_ime_id);
+  imm()->state()->AddEnabledInputMethodId(arc_ime_id);
   service()->ImeMenuListChanged();
   ASSERT_EQ(1u, bridge()->enable_ime_calls_.size());
   EXPECT_EQ(aeiu::GetComponentIDByInputMethodID(arc_ime_id),
@@ -352,7 +352,7 @@
   EXPECT_TRUE(std::get<bool>(bridge()->enable_ime_calls_[0]));
 
   // Disable the ARC IME and verify that EnableIme is called with false.
-  imm()->state()->RemoveActiveInputMethodId(arc_ime_id);
+  imm()->state()->RemoveEnabledInputMethodId(arc_ime_id);
   service()->ImeMenuListChanged();
   ASSERT_EQ(2u, bridge()->enable_ime_calls_.size());
   EXPECT_EQ(aeiu::GetComponentIDByInputMethodID(arc_ime_id),
@@ -360,7 +360,7 @@
   EXPECT_FALSE(std::get<bool>(bridge()->enable_ime_calls_[1]));
 
   // EnableIme is not called when non ARC IME is disabled.
-  imm()->state()->RemoveActiveInputMethodId(extension_ime_id);
+  imm()->state()->RemoveEnabledInputMethodId(extension_ime_id);
   service()->ImeMenuListChanged();
   EXPECT_EQ(2u, bridge()->enable_ime_calls_.size());
 }
@@ -379,11 +379,11 @@
   const std::string arc_ime_id =
       aeiu::GetArcInputMethodID(GenerateId("test.arc.ime"), "us");
 
-  imm()->state()->AddActiveInputMethodId(component_extension_ime_id);
+  imm()->state()->AddEnabledInputMethodId(component_extension_ime_id);
   service()->ImeMenuListChanged();
   EXPECT_EQ(0u, bridge()->enable_ime_calls_.size());
 
-  imm()->state()->AddActiveInputMethodId(arc_ime_id);
+  imm()->state()->AddEnabledInputMethodId(arc_ime_id);
   service()->ImeMenuListChanged();
   ASSERT_EQ(1u, bridge()->enable_ime_calls_.size());
 
@@ -394,7 +394,7 @@
       prefs::kLanguageEnabledImes,
       base::StringPrintf("%s,%s", component_extension_ime_id.c_str(),
                          arc_ime_id.c_str()));
-  imm()->state()->RemoveActiveInputMethodId(arc_ime_id);
+  imm()->state()->RemoveEnabledInputMethodId(arc_ime_id);
   service()->ImeMenuListChanged();
   // Verify that EnableIme(id, false) is NOT called.
   EXPECT_EQ(1u, bridge()->enable_ime_calls_.size());  // still 1u, not 2u.
@@ -419,22 +419,22 @@
   const std::string arc_ime_id = aeiu::GetArcInputMethodID(
       GenerateId("test.arc.ime"), "ime.id.in.arc.container");
 
-  // Set active input method to the extension ime.
-  imm()->state()->SetActiveInputMethod(extension_ime_id);
+  // Set current (active) input method to the extension ime.
+  imm()->state()->SetCurrentInputMethod(extension_ime_id);
   service()->InputMethodChanged(imm(), nullptr, false /* show_message */);
   // ArcImeService should be selected.
   ASSERT_EQ(1u, bridge()->switch_ime_to_calls_.size());
   EXPECT_EQ(arc_ime_service_id, bridge()->switch_ime_to_calls_[0]);
 
-  // Set active input method to the component extension ime.
-  imm()->state()->SetActiveInputMethod(component_extension_ime_id);
+  // Set current (active) input method to the component extension ime.
+  imm()->state()->SetCurrentInputMethod(component_extension_ime_id);
   service()->InputMethodChanged(imm(), nullptr, false /* show_message */);
   // ArcImeService should be selected.
   ASSERT_EQ(2u, bridge()->switch_ime_to_calls_.size());
   EXPECT_EQ(arc_ime_service_id, bridge()->switch_ime_to_calls_[1]);
 
-  // Set active input method to the arc ime.
-  imm()->state()->SetActiveInputMethod(arc_ime_id);
+  // Set current (active) input method to the arc ime.
+  imm()->state()->SetCurrentInputMethod(arc_ime_id);
   service()->InputMethodChanged(imm(), nullptr, false /* show_message */);
   ASSERT_EQ(3u, bridge()->switch_ime_to_calls_.size());
   EXPECT_EQ("ime.id.in.arc.container", bridge()->switch_ime_to_calls_[2]);
@@ -619,8 +619,8 @@
   ToggleTabletMode(true);
 
   // Activate the extension IME and the component extension IME.
-  imm()->state()->AddActiveInputMethodId(extension_ime_id);
-  imm()->state()->AddActiveInputMethodId(component_extension_ime_id);
+  imm()->state()->AddEnabledInputMethodId(extension_ime_id);
+  imm()->state()->AddEnabledInputMethodId(component_extension_ime_id);
   // Update the prefs because the testee checks them.
   profile()->GetPrefs()->SetString(
       prefs::kLanguageEnabledImes,
@@ -728,8 +728,8 @@
   ToggleTabletMode(true);
 
   // Activate the extension IME and the component extension IME.
-  imm()->state()->AddActiveInputMethodId(extension_ime_id);
-  imm()->state()->AddActiveInputMethodId(component_extension_ime_id);
+  imm()->state()->AddEnabledInputMethodId(extension_ime_id);
+  imm()->state()->AddEnabledInputMethodId(component_extension_ime_id);
   // Update the prefs because the testee checks them.
   profile()->GetPrefs()->SetString(
       prefs::kLanguageEnabledImes,
@@ -829,8 +829,8 @@
   ToggleTabletMode(true);
 
   // Activate the extension IME and the component extension IME.
-  imm()->state()->AddActiveInputMethodId(extension_ime_id);
-  imm()->state()->AddActiveInputMethodId(component_extension_ime_id);
+  imm()->state()->AddEnabledInputMethodId(extension_ime_id);
+  imm()->state()->AddEnabledInputMethodId(component_extension_ime_id);
   // Update the prefs because the testee checks them.
   profile()->GetPrefs()->SetString(
       prefs::kLanguageEnabledImes,
@@ -942,8 +942,8 @@
   const std::string arc_ime_id = aeiu::GetArcInputMethodID(
       GenerateId("test.arc.ime"), "ime.id.in.arc.container");
 
-  // Set active input method to the extension ime.
-  imm()->state()->SetActiveInputMethod(extension_ime_id);
+  // Set current (active) input method to the extension ime.
+  imm()->state()->SetCurrentInputMethod(extension_ime_id);
   service()->InputMethodChanged(imm(), profile(), false /* show_message */);
 
   // Enable Chrome OS virtual keyboard
@@ -955,13 +955,13 @@
       client->IsEnableFlagSet(keyboard::KeyboardEnableFlag::kAndroidDisabled));
 
   // It's disabled when the ARC IME is activated.
-  imm()->state()->SetActiveInputMethod(arc_ime_id);
+  imm()->state()->SetCurrentInputMethod(arc_ime_id);
   service()->InputMethodChanged(imm(), profile(), false);
   EXPECT_TRUE(
       client->IsEnableFlagSet(keyboard::KeyboardEnableFlag::kAndroidDisabled));
 
   // It's re-enabled when the ARC IME is deactivated.
-  imm()->state()->SetActiveInputMethod(component_extension_ime_id);
+  imm()->state()->SetCurrentInputMethod(component_extension_ime_id);
   service()->InputMethodChanged(imm(), profile(), false);
   EXPECT_FALSE(
       client->IsEnableFlagSet(keyboard::KeyboardEnableFlag::kAndroidDisabled));
diff --git a/chrome/browser/ash/arc/session/arc_service_launcher.cc b/chrome/browser/ash/arc/session/arc_service_launcher.cc
index 364901e0..137e00e 100644
--- a/chrome/browser/ash/arc/session/arc_service_launcher.cc
+++ b/chrome/browser/ash/arc/session/arc_service_launcher.cc
@@ -12,7 +12,7 @@
 #include "base/check_op.h"
 #include "base/files/file_util.h"
 #include "chrome/browser/apps/app_service/publishers/arc_apps_factory.h"
-#include "chrome/browser/ash/app_restore/full_restore_arc_task_handler.h"
+#include "chrome/browser/ash/app_restore/app_restore_arc_task_handler.h"
 #include "chrome/browser/ash/apps/apk_web_app_service.h"
 #include "chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge.h"
 #include "chrome/browser/ash/arc/adbd/arc_adbd_monitor_bridge.h"
@@ -259,7 +259,7 @@
   CertStoreService::GetForBrowserContext(profile);
   apps::ArcAppsFactory::GetForProfile(profile);
   ash::ApkWebAppService::Get(profile);
-  ash::full_restore::FullRestoreArcTaskHandler::GetForProfile(profile);
+  ash::app_restore::AppRestoreArcTaskHandler::GetForProfile(profile);
 
   if (arc::IsArcVmEnabled()) {
     // ARCVM-only services.
diff --git a/chrome/browser/ash/input_method/input_method_manager_impl.cc b/chrome/browser/ash/input_method/input_method_manager_impl.cc
index d708809..574185e 100644
--- a/chrome/browser/ash/input_method/input_method_manager_impl.cc
+++ b/chrome/browser/ash/input_method/input_method_manager_impl.cc
@@ -150,7 +150,7 @@
   new_state->last_used_input_method_id = last_used_input_method_id;
   new_state->current_input_method = current_input_method;
 
-  new_state->active_input_method_ids = active_input_method_ids;
+  new_state->enabled_input_method_ids = enabled_input_method_ids;
   new_state->allowed_keyboard_layout_input_method_ids =
       allowed_keyboard_layout_input_method_ids;
 
@@ -167,11 +167,11 @@
 }
 
 std::unique_ptr<InputMethodDescriptors>
-InputMethodManagerImpl::StateImpl::GetActiveInputMethods() const {
+InputMethodManagerImpl::StateImpl::GetEnabledInputMethods() const {
   std::unique_ptr<InputMethodDescriptors> result(new InputMethodDescriptors);
-  // Build the active input method descriptors from the active input
-  // methods cache |active_input_method_ids|.
-  for (const auto& input_method_id : active_input_method_ids) {
+  // Build the enabled input method descriptors from the enabled input
+  // methods cache |enabled_input_method_ids|.
+  for (const auto& input_method_id : enabled_input_method_ids) {
     const InputMethodDescriptor* descriptor =
         manager_->util_.GetInputMethodDescriptorFromId(input_method_id);
     if (descriptor) {
@@ -185,7 +185,7 @@
     }
   }
   if (result->empty()) {
-    // Initially |active_input_method_ids| is empty. browser_tests might take
+    // Initially |enabled_input_method_ids| is empty. browser_tests might take
     // this path.
     result->push_back(
         InputMethodUtil::GetFallbackInputMethodDescriptor());
@@ -194,12 +194,12 @@
 }
 
 const std::vector<std::string>&
-InputMethodManagerImpl::StateImpl::GetActiveInputMethodIds() const {
-  return active_input_method_ids;
+InputMethodManagerImpl::StateImpl::GetEnabledInputMethodIds() const {
+  return enabled_input_method_ids;
 }
 
-size_t InputMethodManagerImpl::StateImpl::GetNumActiveInputMethods() const {
-  return active_input_method_ids.size();
+size_t InputMethodManagerImpl::StateImpl::GetNumEnabledInputMethods() const {
+  return enabled_input_method_ids.size();
 }
 
 const InputMethodDescriptor*
@@ -235,7 +235,7 @@
 
   std::vector<std::string> layouts;
   // First, add the initial input method ID, if it's requested, to
-  // layouts, so it appears first on the list of active input
+  // layouts, so it appears first on the list of enabled input
   // methods at the input language status menu.
   for (const auto& initial_layout : initial_layouts) {
     if (manager_->util_.IsValidInputMethodId(initial_layout)) {
@@ -269,13 +269,13 @@
   }
 
   manager_->MigrateInputMethods(&layouts);
-  active_input_method_ids.swap(layouts);
+  enabled_input_method_ids.swap(layouts);
 
   if (IsActive()) {
     // Initialize candidate window controller and widgets such as
     // candidate window, infolist and mode indicator.  Note, mode
     // indicator is used by only keyboard layout input methods.
-    if (active_input_method_ids.size() > 1)
+    if (enabled_input_method_ids.size() > 1)
       manager_->MaybeInitializeCandidateWindowController();
 
     // you can pass empty |initial_layout|.
@@ -293,8 +293,8 @@
   const std::vector<std::string>& hardware_keyboard_ids =
       manager_->util_.GetHardwareLoginInputMethodIds();
 
-  std::vector<std::string> new_active_input_method_ids;
-  for (const auto& input_method_id : active_input_method_ids) {
+  std::vector<std::string> new_enabled_input_method_ids;
+  for (const auto& input_method_id : enabled_input_method_ids) {
     // Skip if it's not a keyboard layout. Drop input methods including
     // extension ones. We need to keep all IMEs to support inputting on inline
     // reply on a notification if notifications on lock screen is enabled.
@@ -303,21 +303,21 @@
         added_ids.count(input_method_id)) {
       continue;
     }
-    new_active_input_method_ids.push_back(input_method_id);
+    new_enabled_input_method_ids.push_back(input_method_id);
     added_ids.insert(input_method_id);
   }
 
   // We'll add the hardware keyboard if it's not included in
-  // |active_input_method_ids| so that the user can always use the hardware
+  // |enabled_input_method_ids| so that the user can always use the hardware
   // keyboard on the screen locker.
   for (const auto& hardware_keyboard_id : hardware_keyboard_ids) {
     if (added_ids.count(hardware_keyboard_id))
       continue;
-    new_active_input_method_ids.push_back(hardware_keyboard_id);
+    new_enabled_input_method_ids.push_back(hardware_keyboard_id);
     added_ids.insert(hardware_keyboard_id);
   }
 
-  active_input_method_ids.swap(new_active_input_method_ids);
+  enabled_input_method_ids.swap(new_enabled_input_method_ids);
 
   // Re-check current_input_method.
   ChangeInputMethod(current_input_method.id(), false);
@@ -326,27 +326,27 @@
 // Adds new input method to given list.
 bool InputMethodManagerImpl::StateImpl::EnableInputMethodImpl(
     const std::string& input_method_id,
-    std::vector<std::string>* new_active_input_method_ids) const {
+    std::vector<std::string>* new_enabled_input_method_ids) const {
   if (!IsInputMethodAllowed(input_method_id)) {
     DVLOG(1) << "EnableInputMethod: " << input_method_id << " is not allowed.";
     return false;
   }
 
-  DCHECK(new_active_input_method_ids);
+  DCHECK(new_enabled_input_method_ids);
   if (!manager_->util_.IsValidInputMethodId(input_method_id)) {
     DVLOG(1) << "EnableInputMethod: Invalid ID: " << input_method_id;
     return false;
   }
 
-  if (!base::Contains(*new_active_input_method_ids, input_method_id))
-    new_active_input_method_ids->push_back(input_method_id);
+  if (!base::Contains(*new_enabled_input_method_ids, input_method_id))
+    new_enabled_input_method_ids->push_back(input_method_id);
 
   return true;
 }
 
 bool InputMethodManagerImpl::StateImpl::EnableInputMethod(
     const std::string& input_method_id) {
-  if (!EnableInputMethodImpl(input_method_id, &active_input_method_ids))
+  if (!EnableInputMethodImpl(input_method_id, &enabled_input_method_ids))
     return false;
 
   manager_->ReconfigureIMFramework(this);
@@ -354,40 +354,43 @@
 }
 
 bool InputMethodManagerImpl::StateImpl::ReplaceEnabledInputMethods(
-    const std::vector<std::string>& new_active_input_method_ids) {
+    const std::vector<std::string>& new_enabled_input_method_ids) {
   if (IsShuttingDown())
     return false;
 
   // Filter unknown or obsolete IDs.
-  std::vector<std::string> new_active_input_method_ids_filtered;
+  std::vector<std::string> new_enabled_input_method_ids_filtered;
 
-  for (const auto& new_active_input_method_id : new_active_input_method_ids)
-    EnableInputMethodImpl(new_active_input_method_id,
-                          &new_active_input_method_ids_filtered);
+  for (const auto& new_enabled_input_method_id : new_enabled_input_method_ids)
+    EnableInputMethodImpl(new_enabled_input_method_id,
+                          &new_enabled_input_method_ids_filtered);
 
-  if (new_active_input_method_ids_filtered.empty()) {
+  if (new_enabled_input_method_ids_filtered.empty()) {
     DVLOG(1) << "ReplaceEnabledInputMethods: No valid input method ID";
     return false;
   }
 
-  // Copy extension IDs to |new_active_input_method_ids_filtered|. We have to
+  // Copy extension IDs to |new_enabled_input_method_ids_filtered|. We have to
   // keep relative order of the extension input method IDs.
-  for (const auto& input_method_id : active_input_method_ids) {
+  for (const auto& input_method_id : enabled_input_method_ids) {
     if (extension_ime_util::IsExtensionIME(input_method_id))
-      new_active_input_method_ids_filtered.push_back(input_method_id);
+      new_enabled_input_method_ids_filtered.push_back(input_method_id);
   }
-  active_input_method_ids.swap(new_active_input_method_ids_filtered);
-  manager_->MigrateInputMethods(&active_input_method_ids);
+  enabled_input_method_ids.swap(new_enabled_input_method_ids_filtered);
+  manager_->MigrateInputMethods(&enabled_input_method_ids);
 
   manager_->ReconfigureIMFramework(this);
 
-  // If |current_input_method| is no longer in |active_input_method_ids|,
-  // ChangeInputMethod() picks the first one in |active_input_method_ids|.
+  // If |current_input_method| is no longer in |enabled_input_method_ids|,
+  // ChangeInputMethod() picks the first one in |enabled_input_method_ids|.
   ChangeInputMethod(current_input_method.id(), false);
 
-  // Record histogram for active input method count.
+  // Record histogram for enabled input method count; "active" in the metric
+  // name is a legacy misnomer; "active" should refer to just the single current
+  // aka. activated input method that's one of the enabled input methods whose
+  // total count is being tracked by this metric.
   UMA_HISTOGRAM_COUNTS_1M("InputMethod.ActiveCount",
-                          active_input_method_ids.size());
+                          enabled_input_method_ids.size());
 
   return true;
 }
@@ -409,26 +412,27 @@
     return false;
   }
 
-  std::vector<std::string> new_active_input_method_ids;
+  std::vector<std::string> new_enabled_input_method_ids;
   if (enable_allowed_input_methods) {
     // Enable all allowed input methods.
-    new_active_input_method_ids = allowed_keyboard_layout_input_method_ids;
+    new_enabled_input_method_ids = allowed_keyboard_layout_input_method_ids;
   } else {
-    // Filter all currently active input methods and leave only non-keyboard or
+    // Filter all currently enabled input methods and leave only non-keyboard or
     // allowed keyboard layouts. If no input method remains, take a fallback
     // keyboard layout.
     bool has_keyboard_layout = false;
-    for (auto active_input_method_id : active_input_method_ids) {
-      if (IsInputMethodAllowed(active_input_method_id)) {
-        new_active_input_method_ids.push_back(active_input_method_id);
+    for (auto enabled_input_method_id : enabled_input_method_ids) {
+      if (IsInputMethodAllowed(enabled_input_method_id)) {
+        new_enabled_input_method_ids.push_back(enabled_input_method_id);
         has_keyboard_layout |=
-            manager_->util_.IsKeyboardLayout(active_input_method_id);
+            manager_->util_.IsKeyboardLayout(enabled_input_method_id);
       }
     }
     if (!has_keyboard_layout)
-      new_active_input_method_ids.push_back(GetAllowedFallBackKeyboardLayout());
+      new_enabled_input_method_ids.push_back(
+          GetAllowedFallBackKeyboardLayout());
   }
-  return ReplaceEnabledInputMethods(new_active_input_method_ids);
+  return ReplaceEnabledInputMethods(new_enabled_input_method_ids);
 }
 
 const std::vector<std::string>&
@@ -469,8 +473,8 @@
 
   // Always lookup input method, even if it is the same as
   // |current_input_method| because If it is no longer in
-  // |active_input_method_ids|, pick the first one in
-  // |active_input_method_ids|.
+  // |enabled_input_method_ids|, pick the first one in
+  // |enabled_input_method_ids|.
   const InputMethodDescriptor* descriptor =
       manager_->LookupInputMethod(input_method_id, this);
   if (!descriptor) {
@@ -532,7 +536,7 @@
   // happens after activating the 3rd party IME.
   // So here to record the 3rd party IME to be activated, and activate it
   // when SetEnabledExtensionImes happens later.
-  return !InputMethodIsActivated(input_method_id) &&
+  return !InputMethodIsEnabled(input_method_id) &&
          extension_ime_util::IsExtensionIME(input_method_id);
 }
 
@@ -553,8 +557,8 @@
     const std::string& id = descriptor.id();
     available_input_methods[id] = descriptor;
     if (base::Contains(enabled_extension_imes, id)) {
-      if (!base::Contains(active_input_method_ids, id)) {
-        active_input_method_ids.push_back(id);
+      if (!base::Contains(enabled_input_method_ids, id)) {
+        enabled_input_method_ids.push_back(id);
       } else {
         DVLOG(1) << "AddInputMethodExtension: already added: " << id << ", "
                  << descriptor.name();
@@ -582,14 +586,14 @@
 
 void InputMethodManagerImpl::StateImpl::RemoveInputMethodExtension(
     const std::string& extension_id) {
-  // Remove the active input methods with |extension_id|.
-  std::vector<std::string> new_active_input_method_ids;
-  for (const auto& active_input_method_id : active_input_method_ids) {
+  // Remove the enabled input methods with |extension_id|.
+  std::vector<std::string> new_enabled_input_method_ids;
+  for (const auto& enabled_input_method_id : enabled_input_method_ids) {
     if (extension_id != extension_ime_util::GetExtensionIDFromInputMethodID(
-                            active_input_method_id))
-      new_active_input_method_ids.push_back(active_input_method_id);
+                            enabled_input_method_id))
+      new_enabled_input_method_ids.push_back(enabled_input_method_id);
   }
-  active_input_method_ids.swap(new_active_input_method_ids);
+  enabled_input_method_ids.swap(new_enabled_input_method_ids);
 
   // Remove the input methods registered by `extension_id`.
   std::map<std::string, InputMethodDescriptor> new_available_input_methods;
@@ -608,8 +612,8 @@
     manager_->engine_map_[profile].erase(extension_id);
   }
 
-  // If |current_input_method| is no longer in |active_input_method_ids|,
-  // switch to the first one in |active_input_method_ids|.
+  // If |current_input_method| is no longer in |enabled_input_method_ids|,
+  // switch to the first one in |enabled_input_method_ids|.
   ChangeInputMethod(current_input_method.id(), false);
   manager_->NotifyInputMethodExtensionRemoved(extension_id);
 }
@@ -631,7 +635,7 @@
   enabled_extension_imes.clear();
   enabled_extension_imes.insert(
       enabled_extension_imes.end(), ids->begin(), ids->end());
-  bool active_imes_changed = false;
+  bool enabled_imes_changed = false;
   bool switch_to_pending = false;
 
   for (const auto& entry : available_input_methods) {
@@ -641,32 +645,33 @@
     if (pending_input_method_id == entry.first)
       switch_to_pending = true;
 
-    const auto active_iter =
-        std::find(active_input_method_ids.begin(),
-                  active_input_method_ids.end(), entry.first);
+    const auto currently_enabled_iter =
+        std::find(enabled_input_method_ids.begin(),
+                  enabled_input_method_ids.end(), entry.first);
 
-    bool active = active_iter != active_input_method_ids.end();
+    bool currently_enabled =
+        currently_enabled_iter != enabled_input_method_ids.end();
     bool enabled = base::Contains(enabled_extension_imes, entry.first);
 
-    if (active && !enabled)
-      active_input_method_ids.erase(active_iter);
+    if (currently_enabled && !enabled)
+      enabled_input_method_ids.erase(currently_enabled_iter);
 
-    if (!active && enabled)
-      active_input_method_ids.push_back(entry.first);
+    if (!currently_enabled && enabled)
+      enabled_input_method_ids.push_back(entry.first);
 
-    if (active == !enabled)
-      active_imes_changed = true;
+    if (currently_enabled == !enabled)
+      enabled_imes_changed = true;
   }
 
-  if (IsActive() && active_imes_changed) {
+  if (IsActive() && enabled_imes_changed) {
     manager_->MaybeInitializeCandidateWindowController();
 
     if (switch_to_pending) {
       ChangeInputMethod(pending_input_method_id, false);
       pending_input_method_id.clear();
     } else {
-      // If |current_input_method| is no longer in |active_input_method_ids_|,
-      // switch to the first one in |active_input_method_ids_|.
+      // If |current_input_method| is no longer in |enabled_input_method_ids_|,
+      // switch to the first one in |enabled_input_method_ids_|.
       ChangeInputMethod(current_input_method.id(), false);
     }
   }
@@ -745,8 +750,8 @@
 
 bool InputMethodManagerImpl::StateImpl::CanCycleInputMethod() const {
   // Sanity checks.
-  if (active_input_method_ids.empty()) {
-    DVLOG(1) << "active input method is empty";
+  if (enabled_input_method_ids.empty()) {
+    DVLOG(1) << "enabled input method is empty";
     return false;
   }
 
@@ -755,7 +760,7 @@
     return false;
   }
 
-  return active_input_method_ids.size() > 1;
+  return enabled_input_method_ids.size() > 1;
 }
 
 void InputMethodManagerImpl::StateImpl::SwitchToNextInputMethod() {
@@ -763,12 +768,12 @@
     return;
 
   auto iter =
-      std::find(active_input_method_ids.begin(), active_input_method_ids.end(),
-                current_input_method.id());
-  if (iter != active_input_method_ids.end())
+      std::find(enabled_input_method_ids.begin(),
+                enabled_input_method_ids.end(), current_input_method.id());
+  if (iter != enabled_input_method_ids.end())
     ++iter;
-  if (iter == active_input_method_ids.end())
-    iter = active_input_method_ids.begin();
+  if (iter == enabled_input_method_ids.end())
+    iter = enabled_input_method_ids.begin();
   ChangeInputMethod(*iter, true);
 }
 
@@ -783,9 +788,9 @@
   }
 
   const auto iter =
-      std::find(active_input_method_ids.begin(), active_input_method_ids.end(),
-                last_used_input_method_id);
-  if (iter == active_input_method_ids.end()) {
+      std::find(enabled_input_method_ids.begin(),
+                enabled_input_method_ids.end(), last_used_input_method_id);
+  if (iter == enabled_input_method_ids.end()) {
     // last_used_input_method_id is not supported.
     SwitchToNextInputMethod();
     return;
@@ -801,9 +806,9 @@
   return current_input_method;
 }
 
-bool InputMethodManagerImpl::StateImpl::InputMethodIsActivated(
+bool InputMethodManagerImpl::StateImpl::InputMethodIsEnabled(
     const std::string& input_method_id) const {
-  return base::Contains(active_input_method_ids, input_method_id);
+  return base::Contains(enabled_input_method_ids, input_method_id);
 }
 
 void InputMethodManagerImpl::StateImpl::EnableInputView() {
@@ -873,7 +878,7 @@
 
   state_ = new_impl_state;
 
-  if (state_.get() && state_->active_input_method_ids.size()) {
+  if (state_.get() && state_->enabled_input_method_ids.size()) {
     // Initialize candidate window controller and widgets such as
     // candidate window, infolist and mode indicator.  Note, mode
     // indicator is used by only keyboard layout input methods.
@@ -988,9 +993,9 @@
   std::string input_method_id_to_switch = input_method_id;
 
   // Sanity check
-  if (!state->InputMethodIsActivated(input_method_id)) {
+  if (!state->InputMethodIsEnabled(input_method_id)) {
     std::unique_ptr<InputMethodDescriptors> input_methods(
-        state->GetActiveInputMethods());
+        state->GetEnabledInputMethods());
     DCHECK(!input_methods->empty());
     input_method_id_to_switch = input_methods->at(0).id();
     if (!input_method_id.empty()) {
@@ -1089,7 +1094,7 @@
 
 void InputMethodManagerImpl::LoadNecessaryComponentExtensions(
     InputMethodManagerImpl::StateImpl* state) {
-  // Load component extensions but also update |active_input_method_ids| as
+  // Load component extensions but also update |enabled_input_method_ids| as
   // some component extension IMEs may have been removed from the Chrome OS
   // image. If specified component extension IME no longer exists, falling back
   // to an existing IME.
@@ -1097,13 +1102,13 @@
   TRACE_EVENT0("ime",
                "InputMethodManagerImpl::LoadNecessaryComponentExtensions");
   std::vector<std::string> unfiltered_input_method_ids;
-  unfiltered_input_method_ids.swap(state->active_input_method_ids);
+  unfiltered_input_method_ids.swap(state->enabled_input_method_ids);
   std::set<std::string> ext_loaded;
   for (const auto& unfiltered_input_method_id : unfiltered_input_method_ids) {
     if (!extension_ime_util::IsComponentExtensionIME(
             unfiltered_input_method_id)) {
-      // Legacy IMEs or xkb layouts are alwayes active.
-      state->active_input_method_ids.push_back(unfiltered_input_method_id);
+      // Legacy IMEs or xkb layouts are alwayes enabled.
+      state->enabled_input_method_ids.push_back(unfiltered_input_method_id);
     } else if (component_extension_ime_manager_->IsAllowlisted(
                    unfiltered_input_method_id)) {
       if (enable_extension_loading_) {
@@ -1111,7 +1116,7 @@
             state->profile, unfiltered_input_method_id, &ext_loaded);
       }
 
-      state->active_input_method_ids.push_back(unfiltered_input_method_id);
+      state->enabled_input_method_ids.push_back(unfiltered_input_method_id);
     }
   }
 }
@@ -1180,7 +1185,7 @@
     Profile* profile) {
   auto* new_state = new StateImpl(this, profile);
 
-  // Active IM should be set to owner/user's default.
+  // Enabled and current (active) IM should be set to owner/user's default.
   PrefService* prefs = g_browser_process->local_state();
   PrefService* user_prefs = profile ? profile->GetPrefs() : nullptr;
   std::string initial_input_method_id;
@@ -1199,7 +1204,7 @@
               ? GetInputMethodUtil()->GetFallbackInputMethodDescriptor().id()
               : initial_input_method_id);
   if (descriptor) {
-    new_state->active_input_method_ids.push_back(descriptor->id());
+    new_state->enabled_input_method_ids.push_back(descriptor->id());
     new_state->current_input_method = *descriptor;
   }
   return scoped_refptr<InputMethodManager::State>(new_state);
diff --git a/chrome/browser/ash/input_method/input_method_manager_impl.h b/chrome/browser/ash/input_method/input_method_manager_impl.h
index 8fc570e..2ba5f73 100644
--- a/chrome/browser/ash/input_method/input_method_manager_impl.h
+++ b/chrome/browser/ash/input_method/input_method_manager_impl.h
@@ -56,10 +56,10 @@
     // Adds new input method to given list if possible
     bool EnableInputMethodImpl(
         const std::string& input_method_id,
-        std::vector<std::string>* new_active_input_method_ids) const;
+        std::vector<std::string>* new_enabled_input_method_ids) const;
 
-    // Returns true if |input_method_id| is in |active_input_method_ids|.
-    bool InputMethodIsActivated(const std::string& input_method_id) const;
+    // Returns true if |input_method_id| is in |enabled_input_method_ids|.
+    bool InputMethodIsEnabled(const std::string& input_method_id) const;
 
     // Returns true if given input method requires pending extension.
     bool MethodAwaitsExtensionLoad(const std::string& input_method_id) const;
@@ -82,18 +82,18 @@
     void ChangeInputMethodToJpIme() override;
     void ToggleInputMethodForJpIme() override;
     bool EnableInputMethod(
-        const std::string& new_active_input_method_id) override;
+        const std::string& new_enabled_input_method_id) override;
     void EnableLoginLayouts(
         const std::string& language_code,
         const std::vector<std::string>& initial_layouts) override;
     void EnableLockScreenLayouts() override;
     void GetInputMethodExtensions(InputMethodDescriptors* result) override;
-    std::unique_ptr<InputMethodDescriptors> GetActiveInputMethods()
+    std::unique_ptr<InputMethodDescriptors> GetEnabledInputMethods()
         const override;
-    const std::vector<std::string>& GetActiveInputMethodIds() const override;
+    const std::vector<std::string>& GetEnabledInputMethodIds() const override;
     const InputMethodDescriptor* GetInputMethodFromId(
         const std::string& input_method_id) const override;
-    size_t GetNumActiveInputMethods() const override;
+    size_t GetNumEnabledInputMethods() const override;
     void SetEnabledExtensionImes(std::vector<std::string>* ids) override;
     void SetInputMethodLoginDefault() override;
     void SetInputMethodLoginDefaultFromVPD(const std::string& locale,
@@ -102,7 +102,7 @@
     void SwitchToLastUsedInputMethod() override;
     InputMethodDescriptor GetCurrentInputMethod() const override;
     bool ReplaceEnabledInputMethods(
-        const std::vector<std::string>& new_active_input_method_ids) override;
+        const std::vector<std::string>& new_enabled_input_method_ids) override;
     bool SetAllowedInputMethods(
         const std::vector<std::string>& new_allowed_input_method_ids,
         bool enable_allowed_input_methods) override;
@@ -125,8 +125,8 @@
     std::string last_used_input_method_id;
     InputMethodDescriptor current_input_method;
 
-    // The active input method ids cache.
-    std::vector<std::string> active_input_method_ids;
+    // The enabled input method ids cache.
+    std::vector<std::string> enabled_input_method_ids;
 
     // The allowed keyboard layout input methods (e.g. by policy).
     std::vector<std::string> allowed_keyboard_layout_input_method_ids;
@@ -161,8 +161,8 @@
     // allowed input method, if no hardware input method is allowed.
     std::string GetAllowedFallBackKeyboardLayout() const;
 
-    // The URL of the input view of the active ime with parameters (e.g. layout,
-    // keyset).
+    // The URL of the input view of the current (active) ime with parameters
+    // (e.g. layout, keyset).
     GURL input_view_url;
 
     // Whether the input view URL has been forcibly overridden e.g. to show a
@@ -274,13 +274,13 @@
 
   // Starts or stops the system input method framework as needed.
   // (after list of enabled input methods has been updated).
-  // If state is active, active input method is updated.
+  // If state is active, current (active) input method is updated.
   void ReconfigureIMFramework(StateImpl* state);
 
   // Record input method usage histograms.
   void RecordInputMethodUsage(const std::string& input_method_id);
 
-  // Notifies the current input method or the list of active input method IDs
+  // Notifies the current input method or the list of enabled input method IDs
   // changed.
   void NotifyImeMenuListChanged();
 
diff --git a/chrome/browser/ash/input_method/input_method_manager_impl_unittest.cc b/chrome/browser/ash/input_method/input_method_manager_impl_unittest.cc
index ad831fad..4f9af60 100644
--- a/chrome/browser/ash/input_method/input_method_manager_impl_unittest.cc
+++ b/chrome/browser/ash/input_method/input_method_manager_impl_unittest.cc
@@ -417,7 +417,8 @@
   EXPECT_EQ(0, observer.input_method_extension_added_count_);
   EXPECT_EQ(0, observer.input_method_extension_removed_count_);
   manager_->GetActiveIMEState()->EnableLoginLayouts("en-US", keyboard_layouts);
-  EXPECT_EQ(8U, manager_->GetActiveIMEState()->GetActiveInputMethods()->size());
+  EXPECT_EQ(8U,
+            manager_->GetActiveIMEState()->GetEnabledInputMethods()->size());
   EXPECT_EQ(1, observer.input_method_changed_count_);
   // Menu change is triggered only if current input method was actually changed.
   EXPECT_EQ(0, observer.input_method_menu_item_changed_count_);
@@ -484,13 +485,13 @@
   std::vector<std::string> keyboard_layouts;
 
   manager_->GetActiveIMEState()->EnableLoginLayouts("en-US", keyboard_layouts);
-  EXPECT_EQ(8U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(8U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
 
   // For http://crbug.com/19655#c11 - (5)
   // The hardware keyboard layout "xkb:us::eng" is always active, hence 2U.
   manager_->GetActiveIMEState()->EnableLoginLayouts(
       "ja", keyboard_layouts);  // Japanese
-  EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
 }
 
 TEST_F(InputMethodManagerImplTest, TestEnableLayoutsAndCurrentInputMethod) {
@@ -511,16 +512,16 @@
   manager_->GetActiveIMEState()->EnableLoginLayouts(
       "en-US",
       manager_->GetInputMethodUtil()->GetHardwareLoginInputMethodIds());
-  EXPECT_EQ(
-      9U,
-      manager_->GetActiveIMEState()->GetNumActiveInputMethods());  // 8 + French
+  EXPECT_EQ(9U,
+            manager_->GetActiveIMEState()
+                ->GetNumEnabledInputMethods());  // 8 + French
   // The physical layout is Japanese.
   manager_->GetInputMethodUtil()->SetHardwareKeyboardLayoutForTesting(
       "xkb:jp::jpn");
   manager_->GetActiveIMEState()->EnableLoginLayouts(
       "ja", manager_->GetInputMethodUtil()->GetHardwareLoginInputMethodIds());
   // "xkb:us::eng" is not needed, hence 1.
-  EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
 
   // The physical layout is Russian.
   manager_->GetInputMethodUtil()->SetHardwareKeyboardLayoutForTesting(
@@ -528,9 +529,9 @@
   manager_->GetActiveIMEState()->EnableLoginLayouts(
       "ru", manager_->GetInputMethodUtil()->GetHardwareLoginInputMethodIds());
   // "xkb:us::eng" only.
-  EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
   EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"),
-            manager_->GetActiveIMEState()->GetActiveInputMethodIds().front());
+            manager_->GetActiveIMEState()->GetEnabledInputMethodIds().front());
 }
 
 TEST_F(InputMethodManagerImplTest, TestEnableMultipleHardwareKeyboardLayout) {
@@ -541,7 +542,7 @@
       "en-US",
       manager_->GetInputMethodUtil()->GetHardwareLoginInputMethodIds());
   // 8 + French + Hungarian
-  EXPECT_EQ(10U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(10U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
 }
 
 TEST_F(InputMethodManagerImplTest,
@@ -552,16 +553,16 @@
   manager_->GetActiveIMEState()->EnableLoginLayouts(
       "ru", manager_->GetInputMethodUtil()->GetHardwareLoginInputMethodIds());
   // xkb:us:eng
-  EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
 }
 
-TEST_F(InputMethodManagerImplTest, TestActiveInputMethods) {
+TEST_F(InputMethodManagerImplTest, TestEnabledInputMethods) {
   std::vector<std::string> keyboard_layouts;
   manager_->GetActiveIMEState()->EnableLoginLayouts(
       "ja", keyboard_layouts);  // Japanese
-  EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
   std::unique_ptr<InputMethodDescriptors> methods(
-      manager_->GetActiveIMEState()->GetActiveInputMethods());
+      manager_->GetActiveIMEState()->GetEnabledInputMethods());
   ASSERT_TRUE(methods.get());
   EXPECT_EQ(2U, methods->size());
   const InputMethodDescriptor* id_to_find =
@@ -581,7 +582,7 @@
   ids.push_back(ImeIdFromEngineId("xkb:us:dvorak:eng"));
   ids.push_back(ImeIdFromEngineId("xkb:us:colemak:eng"));
   EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
-  EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
   // Since all the IDs added avobe are keyboard layouts, Start() should not be
   // called.
   EXPECT_EQ(1, observer.input_method_changed_count_);
@@ -591,7 +592,7 @@
   // Disable Dvorak.
   ids.erase(ids.begin());
   EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
-  EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
   EXPECT_EQ(2, observer.input_method_changed_count_);
   EXPECT_EQ(ImeIdFromEngineId(ids[0]),  // colemak
             manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
@@ -608,7 +609,7 @@
   ids.push_back(ImeIdFromEngineId("xkb:us:dvorak:eng"));
   ids.push_back(ImeIdFromEngineId("xkb:us:colemak:eng"));
   EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
-  EXPECT_EQ(3U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(3U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
   EXPECT_EQ(1, observer.input_method_changed_count_);
   EXPECT_EQ(ImeIdFromEngineId(ids[0]),
             manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
@@ -622,7 +623,7 @@
   // Disable Dvorak.
   ids.erase(ids.begin() + 1);
   EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
-  EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
   EXPECT_EQ(3, observer.input_method_changed_count_);
   EXPECT_EQ(ImeIdFromEngineId(ids[0]),  // US Qwerty
             manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
@@ -651,7 +652,7 @@
   // Disable Mozc.
   ids.erase(ids.begin() + 1);
   EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
-  EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
   EXPECT_EQ(ImeIdFromEngineId(ids[0]),
             manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
   EXPECT_EQ("us(dvorak)", keyboard_->last_layout_);
@@ -673,7 +674,7 @@
   // Disable Dvorak.
   ids.erase(ids.begin());
   EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
-  EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
   EXPECT_EQ(ImeIdFromEngineId(ids[0]),  // Mozc
             manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
   EXPECT_EQ("us", keyboard_->last_layout_);
@@ -717,7 +718,7 @@
   ids.push_back(ImeIdFromEngineId("xkb:us::eng"));
   ids.push_back(ImeIdFromEngineId("xkb:us:dvorak:eng"));
   EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
-  EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
   EXPECT_EQ(1, observer.input_method_changed_count_);
   EXPECT_EQ(ImeIdFromEngineId(ids[0]),
             manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
@@ -735,7 +736,7 @@
       manager_->GetActiveIMEState();
   manager_->SetState(saved_ime_state->Clone());
   manager_->GetActiveIMEState()->EnableLockScreenLayouts();
-  EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
   EXPECT_EQ(ImeIdFromEngineId(ids[1]),  // still Dvorak
             manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
   EXPECT_EQ("us(dvorak)", keyboard_->last_layout_);
@@ -749,7 +750,7 @@
   manager_->SetState(saved_ime_state);
   EXPECT_EQ(manager_->GetActiveIMEState()->GetUIStyle(),
             InputMethodManager::UIStyle::kNormal);
-  EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
   EXPECT_EQ(ImeIdFromEngineId(ids[1]),
             manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
   EXPECT_EQ("us(dvorak)", keyboard_->last_layout_);
@@ -766,7 +767,7 @@
   ids.push_back(ImeIdFromEngineId(kExt2Engine2Id));
   ids.push_back(ImeIdFromEngineId(kExt2Engine1Id));
   EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
-  EXPECT_EQ(3U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(3U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
   EXPECT_EQ(1, observer.input_method_changed_count_);
   EXPECT_EQ(ImeIdFromEngineId(ids[0]),
             manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
@@ -786,7 +787,7 @@
   manager_->GetActiveIMEState()->EnableLockScreenLayouts();
   EXPECT_EQ(2U,
             manager_->GetActiveIMEState()
-                ->GetNumActiveInputMethods());  // Qwerty+Dvorak.
+                ->GetNumEnabledInputMethods());  // Qwerty+Dvorak.
   EXPECT_EQ(ImeIdFromEngineId("xkb:us:dvorak:eng"),
             manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
   EXPECT_EQ("us(dvorak)", keyboard_->last_layout_);
@@ -801,7 +802,7 @@
             InputMethodManager::UIStyle::kNormal);
   EXPECT_EQ(3U,
             manager_->GetActiveIMEState()
-                ->GetNumActiveInputMethods());  // Dvorak and 2 IMEs.
+                ->GetNumEnabledInputMethods());  // Dvorak and 2 IMEs.
   EXPECT_EQ(ImeIdFromEngineId(ids[1]),
             manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
   EXPECT_EQ("us(dvorak)", keyboard_->last_layout_);
@@ -818,7 +819,7 @@
   ids.push_back(ImeIdFromEngineId(kNaclMozcJpId));
   ids.push_back(ImeIdFromEngineId(kNaclMozcUsId));
   EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
-  EXPECT_EQ(4U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(4U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
   EXPECT_EQ(2, keyboard_->set_current_keyboard_layout_by_name_count_);
   EXPECT_EQ("us(dvorak)", keyboard_->last_layout_);
   manager_->GetActiveIMEState()->SwitchToNextInputMethod();
@@ -836,7 +837,7 @@
   // Disable Dvorak.
   ids.erase(ids.begin());
   EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
-  EXPECT_EQ(3U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(3U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
   EXPECT_EQ(7, keyboard_->set_current_keyboard_layout_by_name_count_);
   EXPECT_EQ("us(colemak)", keyboard_->last_layout_);
 }
@@ -863,7 +864,7 @@
   ids.push_back(ImeIdFromEngineId("xkb:us::eng"));
   ids.push_back(ImeIdFromEngineId(kNaclMozcUsId));
   EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
-  EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
   EXPECT_TRUE(menu_manager_->GetCurrentInputMethodMenuItemList().empty());
   manager_->GetActiveIMEState()->ChangeInputMethod(
       ImeIdFromEngineId(kNaclMozcUsId), false /* show_message */);
@@ -889,7 +890,7 @@
   ids.push_back(ImeIdFromEngineId(kNaclMozcUsId));   // Japanese
   ids.push_back(ImeIdFromEngineId(kExt2Engine1Id));  // T-Chinese
   EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
-  EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
   EXPECT_TRUE(menu_manager_->GetCurrentInputMethodMenuItemList().empty());
 
   ui::ime::InputMethodMenuItemList current_property_list;
@@ -925,7 +926,7 @@
   keyboard_layouts.push_back(ImeIdFromEngineId("xkb:us::eng"));
   // For http://crbug.com/19655#c11 - (1)
   manager_->GetActiveIMEState()->EnableLoginLayouts("en-US", keyboard_layouts);
-  EXPECT_EQ(8U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(8U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
   EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"),
             manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
   EXPECT_EQ("us", keyboard_->last_layout_);
@@ -980,7 +981,7 @@
   std::vector<std::string> keyboard_layouts;
   keyboard_layouts.push_back(ImeIdFromEngineId("xkb:us::eng"));
   manager_->GetActiveIMEState()->EnableLoginLayouts("en-US", keyboard_layouts);
-  EXPECT_EQ(8U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(8U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
   EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"),
             manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
   EXPECT_EQ("us", keyboard_->last_layout_);
@@ -1028,12 +1029,12 @@
   manager_->RemoveObserver(&observer);
 }
 
-TEST_F(InputMethodManagerImplTest, CycleInputMethodForOneActiveInputMethod) {
+TEST_F(InputMethodManagerImplTest, CycleInputMethodForOneEnabledInputMethod) {
   // Simulate a single input method.
   std::vector<std::string> ids;
   ids.push_back(ImeIdFromEngineId("xkb:us::eng"));
   EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
-  EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
 
   // Switching to next does nothing.
   manager_->GetActiveIMEState()->SwitchToNextInputMethod();
@@ -1052,7 +1053,7 @@
   std::vector<std::string> ids;
   ids.push_back(ImeIdFromEngineId("xkb:us:dvorak:eng"));
   EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
-  EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
   EXPECT_EQ(1, observer.input_method_changed_count_);
   EXPECT_EQ(ImeIdFromEngineId(ids[0]),
             manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
@@ -1077,16 +1078,16 @@
       kExtensionId1, descriptors, &engine);
 
   // Extension IMEs are not enabled by default.
-  EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
 
   std::vector<std::string> extension_ime_ids;
   extension_ime_ids.push_back(ext1_id);
   manager_->GetActiveIMEState()->SetEnabledExtensionImes(&extension_ime_ids);
-  EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
 
   {
     std::unique_ptr<InputMethodDescriptors> methods(
-        manager_->GetActiveIMEState()->GetActiveInputMethods());
+        manager_->GetActiveIMEState()->GetEnabledInputMethods());
     ASSERT_EQ(2U, methods->size());
     // Ext IMEs should be at the end of the list.
     EXPECT_EQ(ext1_id, methods->at(1).id());
@@ -1105,14 +1106,14 @@
   MockInputMethodEngine engine2;
   manager_->GetActiveIMEState()->AddInputMethodExtension(
       kExtensionId2, descriptors, &engine2);
-  EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
 
   extension_ime_ids.push_back(ext2_id);
   manager_->GetActiveIMEState()->SetEnabledExtensionImes(&extension_ime_ids);
-  EXPECT_EQ(3U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(3U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
   {
     std::unique_ptr<InputMethodDescriptors> methods(
-        manager_->GetActiveIMEState()->GetActiveInputMethods());
+        manager_->GetActiveIMEState()->GetEnabledInputMethods());
     ASSERT_EQ(3U, methods->size());
     // Ext IMEs should be at the end of the list.
     EXPECT_EQ(ext1_id, methods->at(1).id());
@@ -1121,9 +1122,9 @@
 
   // Remove them.
   manager_->GetActiveIMEState()->RemoveInputMethodExtension(kExtensionId1);
-  EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
   manager_->GetActiveIMEState()->RemoveInputMethodExtension(kExtensionId2);
-  EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
 }
 
 TEST_F(InputMethodManagerImplTest, TestAddExtensionInputThenLockScreen) {
@@ -1132,7 +1133,7 @@
   std::vector<std::string> ids;
   ids.push_back(ImeIdFromEngineId("xkb:us::eng"));
   EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
-  EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
   EXPECT_EQ(1, observer.input_method_changed_count_);
   EXPECT_EQ(ImeIdFromEngineId(ids[0]),
             manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
@@ -1156,13 +1157,13 @@
       kExtensionId1, descriptors, &engine);
 
   // Extension IME is not enabled by default.
-  EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
   EXPECT_EQ(1, observer.input_method_changed_count_);
 
   std::vector<std::string> extension_ime_ids;
   extension_ime_ids.push_back(ext_id);
   manager_->GetActiveIMEState()->SetEnabledExtensionImes(&extension_ime_ids);
-  EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
 
   // Switch to the IME.
   manager_->GetActiveIMEState()->SwitchToNextInputMethod();
@@ -1178,7 +1179,7 @@
   manager_->GetActiveIMEState()->EnableLockScreenLayouts();
   EXPECT_EQ(1U,
             manager_->GetActiveIMEState()
-                ->GetNumActiveInputMethods());  // Qwerty. No Ext. IME
+                ->GetNumEnabledInputMethods());  // Qwerty. No Ext. IME
   EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"),
             manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
   EXPECT_EQ("us", keyboard_->last_layout_);
@@ -1187,14 +1188,14 @@
   manager_->SetState(saved_ime_state);
   EXPECT_EQ(manager_->GetActiveIMEState()->GetUIStyle(),
             InputMethodManager::UIStyle::kNormal);
-  EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
   EXPECT_EQ(ext_id,
             manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
   EXPECT_EQ("us(dvorak)", keyboard_->last_layout_);
   {
     // This is for crosbug.com/27052.
     std::unique_ptr<InputMethodDescriptors> methods(
-        manager_->GetActiveIMEState()->GetActiveInputMethods());
+        manager_->GetActiveIMEState()->GetEnabledInputMethods());
     ASSERT_EQ(2U, methods->size());
     // Ext. IMEs should be at the end of the list.
     EXPECT_EQ(ext_id, methods->at(1).id());
@@ -1208,7 +1209,7 @@
   std::vector<std::string> ids;
   ids.push_back(ext_id);
   EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
-  EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
   EXPECT_EQ(ext_id,
             manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
 }
@@ -1222,7 +1223,7 @@
   ids.push_back(ext_id1);
   ids.push_back(ext_id2);
   EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
-  EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
   EXPECT_EQ(ext_id1,
             manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
   manager_->GetActiveIMEState()->ChangeInputMethod(ext_id2,
@@ -1376,7 +1377,7 @@
   std::vector<std::string> allowed = {"xkb:us::eng"};
   EXPECT_TRUE(
       manager_->GetActiveIMEState()->SetAllowedInputMethods(allowed, true));
-  EXPECT_THAT(manager_->GetActiveIMEState()->GetActiveInputMethodIds(),
+  EXPECT_THAT(manager_->GetActiveIMEState()->GetEnabledInputMethodIds(),
               testing::ElementsAre(ImeIdFromEngineId("xkb:us::eng")));
   EXPECT_THAT(manager_->GetActiveIMEState()->GetCurrentInputMethod().id(),
               ImeIdFromEngineId("xkb:us::eng"));
@@ -1443,7 +1444,7 @@
 
   EXPECT_FALSE(manager_->GetActiveIMEState()->EnableInputMethod(
       ImeIdFromEngineId(kNaclMozcUsId)));
-  EXPECT_THAT(manager_->GetActiveIMEState()->GetActiveInputMethodIds(),
+  EXPECT_THAT(manager_->GetActiveIMEState()->GetEnabledInputMethodIds(),
               testing::ElementsAre(ImeIdFromEngineId("xkb:us::eng"),
                                    ImeIdFromEngineId(kNaclMozcJpId)));
 }
@@ -1454,7 +1455,7 @@
   EXPECT_TRUE(
       manager_->GetActiveIMEState()->SetAllowedInputMethods(allowed, true));
   manager_->GetActiveIMEState()->SetInputMethodLoginDefault();
-  EXPECT_THAT(manager_->GetActiveIMEState()->GetActiveInputMethodIds(),
+  EXPECT_THAT(manager_->GetActiveIMEState()->GetEnabledInputMethodIds(),
               testing::ElementsAre(ImeIdFromEngineId("xkb:us::eng"),
                                    ImeIdFromEngineId("xkb:de::ger"),
                                    ImeIdFromEngineId("xkb:fr::fra")));
@@ -1543,7 +1544,7 @@
 
 TEST_F(InputMethodManagerImplTest, TestAddRemoveArcInputMethods) {
   // There is one default IME
-  EXPECT_EQ(1u, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(1u, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
 
   // Add an ARC IMEs.
   std::vector<std::string> languages({"en-US"});
@@ -1566,15 +1567,15 @@
   result.clear();
 
   // The ARC IME is not enabled by default.
-  EXPECT_EQ(1u, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(1u, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
 
   // Enable it.
   std::vector<std::string> extension_ime_ids({ime_id});
   manager_->GetActiveIMEState()->SetEnabledExtensionImes(&extension_ime_ids);
-  EXPECT_EQ(2u, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(2u, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
   {
     std::unique_ptr<InputMethodDescriptors> methods =
-        manager_->GetActiveIMEState()->GetActiveInputMethods();
+        manager_->GetActiveIMEState()->GetEnabledInputMethods();
     EXPECT_EQ(2u, methods->size());
     EXPECT_EQ(ime_id, methods->at(1).id());
   }
@@ -1616,7 +1617,7 @@
   ids.push_back(ImeIdFromEngineId("xkb:us::eng"));
   ids.push_back(ImeIdFromEngineId("xkb:us:dvorak:eng"));
   EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
-  EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
+  EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods());
 
   // Verify the US layout is positional.
   EXPECT_EQ(ImeIdFromEngineId(ids[0]),
diff --git a/chrome/browser/ash/input_method/mock_input_method_manager_impl.cc b/chrome/browser/ash/input_method/mock_input_method_manager_impl.cc
index 271ac30..3ea55c6 100644
--- a/chrome/browser/ash/input_method/mock_input_method_manager_impl.cc
+++ b/chrome/browser/ash/input_method/mock_input_method_manager_impl.cc
@@ -14,7 +14,7 @@
 
 MockInputMethodManagerImpl::State::State(MockInputMethodManagerImpl* manager)
     : manager_(manager) {
-  active_input_method_ids.emplace_back("xkb:us::eng");
+  enabled_input_method_ids.emplace_back("xkb:us::eng");
 }
 
 scoped_refptr<InputMethodManager::State>
@@ -24,7 +24,7 @@
 }
 
 std::unique_ptr<InputMethodDescriptors>
-MockInputMethodManagerImpl::State::GetActiveInputMethods() const {
+MockInputMethodManagerImpl::State::GetEnabledInputMethods() const {
   std::unique_ptr<InputMethodDescriptors> result =
       std::make_unique<InputMethodDescriptors>();
   result->push_back(InputMethodUtil::GetFallbackInputMethodDescriptor());
@@ -36,8 +36,8 @@
     const std::string& input_method_id) const {
   static const InputMethodDescriptor defaultInputMethod =
       InputMethodUtil::GetFallbackInputMethodDescriptor();
-  for (const auto& active_input_method_id : active_input_method_ids) {
-    if (input_method_id == active_input_method_id) {
+  for (const auto& enabled_input_method_id : enabled_input_method_ids) {
+    if (input_method_id == enabled_input_method_id) {
       return &defaultInputMethod;
     }
   }
diff --git a/chrome/browser/ash/input_method/mock_input_method_manager_impl.h b/chrome/browser/ash/input_method/mock_input_method_manager_impl.h
index 3060672b7b..c9189a0 100644
--- a/chrome/browser/ash/input_method/mock_input_method_manager_impl.h
+++ b/chrome/browser/ash/input_method/mock_input_method_manager_impl.h
@@ -26,7 +26,7 @@
 
     // MockInputMethodManager::State:
     scoped_refptr<InputMethodManager::State> Clone() const override;
-    std::unique_ptr<InputMethodDescriptors> GetActiveInputMethods()
+    std::unique_ptr<InputMethodDescriptors> GetEnabledInputMethods()
         const override;
     const InputMethodDescriptor* GetInputMethodFromId(
         const std::string& input_method_id) const override;
diff --git a/chrome/browser/ash/login/lock/lock_screen_browsertest.cc b/chrome/browser/ash/login/lock/lock_screen_browsertest.cc
index 4f94ec92..516faf2 100644
--- a/chrome/browser/ash/login/lock/lock_screen_browsertest.cc
+++ b/chrome/browser/ash/login/lock/lock_screen_browsertest.cc
@@ -147,18 +147,18 @@
   // lock_screen_utils::SetUserInputMethod
   user_ime_state->ChangeInputMethod(valid_lock_screen_method_, false);
 
-  EXPECT_EQ(user_ime_state->GetNumActiveInputMethods(), 3u);
+  EXPECT_EQ(user_ime_state->GetNumEnabledInputMethods(), 3u);
 
   ScreenLockerTester locker_tester;
   locker_tester.Lock();
   auto lock_screen_ime_state = input_manager->GetActiveIMEState();
   EXPECT_NE(user_ime_state, lock_screen_ime_state);
   // Not valid method should be filtered out.
-  EXPECT_EQ(lock_screen_ime_state->GetNumActiveInputMethods(), 2u);
+  EXPECT_EQ(lock_screen_ime_state->GetNumEnabledInputMethods(), 2u);
 
-  EXPECT_TRUE(base::Contains(lock_screen_ime_state->GetActiveInputMethodIds(),
+  EXPECT_TRUE(base::Contains(lock_screen_ime_state->GetEnabledInputMethodIds(),
                              valid_lock_screen_method_));
-  EXPECT_FALSE(base::Contains(lock_screen_ime_state->GetActiveInputMethodIds(),
+  EXPECT_FALSE(base::Contains(lock_screen_ime_state->GetEnabledInputMethodIds(),
                               not_valid_lock_screen_method_));
 
   // Check that input methods are restored in the session.
@@ -166,10 +166,10 @@
   locker_tester.WaitForUnlock();
   EXPECT_EQ(input_manager->GetActiveIMEState(), user_ime_state);
 
-  EXPECT_EQ(user_ime_state->GetNumActiveInputMethods(), 3u);
-  EXPECT_TRUE(base::Contains(user_ime_state->GetActiveInputMethodIds(),
+  EXPECT_EQ(user_ime_state->GetNumEnabledInputMethods(), 3u);
+  EXPECT_TRUE(base::Contains(user_ime_state->GetEnabledInputMethodIds(),
                              valid_lock_screen_method_));
-  EXPECT_TRUE(base::Contains(user_ime_state->GetActiveInputMethodIds(),
+  EXPECT_TRUE(base::Contains(user_ime_state->GetEnabledInputMethodIds(),
                              not_valid_lock_screen_method_));
 }
 
@@ -211,7 +211,7 @@
   input_method::InputMethodManager* input_manager =
       input_method::InputMethodManager::Get();
   // Check that policy applies on the login screen.
-  EXPECT_EQ(input_manager->GetActiveIMEState()->GetActiveInputMethodIds(),
+  EXPECT_EQ(input_manager->GetActiveIMEState()->GetEnabledInputMethodIds(),
             allowed_input_method);
 
   LoginUser(test_account_id);
@@ -226,8 +226,8 @@
   locker_tester.Lock();
 
   // Inputs should stay the same as inside the session.
-  EXPECT_EQ(input_manager->GetActiveIMEState()->GetActiveInputMethodIds(),
-            user_ime_state->GetActiveInputMethodIds());
+  EXPECT_EQ(input_manager->GetActiveIMEState()->GetEnabledInputMethodIds(),
+            user_ime_state->GetEnabledInputMethodIds());
 
   EXPECT_EQ(input_manager->GetActiveIMEState()->GetAllowedInputMethods().size(),
             0u);
diff --git a/chrome/browser/ash/login/lock_screen_utils.cc b/chrome/browser/ash/login/lock_screen_utils.cc
index 9a55870..03990f6 100644
--- a/chrome/browser/ash/login/lock_screen_utils.cc
+++ b/chrome/browser/ash/login/lock_screen_utils.cc
@@ -34,7 +34,7 @@
                  << " (entry dropped). Use hardware default instead.";
     return false;
   }
-  if (!base::Contains(ime_state->GetActiveInputMethodIds(),
+  if (!base::Contains(ime_state->GetEnabledInputMethodIds(),
                       user_input_method)) {
     if (!ime_state->EnableInputMethod(user_input_method)) {
       DLOG(ERROR) << "SetUserInputMethod: user input method '"
diff --git a/chrome/browser/ash/login/login_ui_keyboard_browsertest.cc b/chrome/browser/ash/login/login_ui_keyboard_browsertest.cc
index f75f883..76eca1b 100644
--- a/chrome/browser/ash/login/login_ui_keyboard_browsertest.cc
+++ b/chrome/browser/ash/login/login_ui_keyboard_browsertest.cc
@@ -144,7 +144,7 @@
 
   EXPECT_EQ(expected_input_methods, input_method::InputMethodManager::Get()
                                         ->GetActiveIMEState()
-                                        ->GetActiveInputMethodIds());
+                                        ->GetEnabledInputMethodIds());
 
   EXPECT_EQ(user_input_methods[0], input_method::InputMethodManager::Get()
                                        ->GetActiveIMEState()
@@ -186,7 +186,7 @@
 
   EXPECT_EQ(expected_input_methods, input_method::InputMethodManager::Get()
                                         ->GetActiveIMEState()
-                                        ->GetActiveInputMethodIds());
+                                        ->GetEnabledInputMethodIds());
 }
 
 IN_PROC_BROWSER_TEST_F(LoginUIKeyboardTest, PRE_CheckPODScreenWithUsers) {
@@ -209,12 +209,12 @@
 
   std::vector<std::string> expected_input_methods;
   Append_en_US_InputMethods(&expected_input_methods);
-  // Active IM for the first user (active user POD).
+  // Enabled IM for the first user (active user POD).
   expected_input_methods.push_back(user_input_methods[0]);
 
   EXPECT_EQ(expected_input_methods, input_method::InputMethodManager::Get()
                                         ->GetActiveIMEState()
-                                        ->GetActiveInputMethodIds());
+                                        ->GetEnabledInputMethodIds());
 
   EXPECT_TRUE(LoginScreenTestApi::FocusUser(test_users_[1]));
 
@@ -284,7 +284,7 @@
 
   EXPECT_EQ(expected_input_methods, input_method::InputMethodManager::Get()
                                         ->GetActiveIMEState()
-                                        ->GetActiveInputMethodIds());
+                                        ->GetEnabledInputMethodIds());
 }
 
 IN_PROC_BROWSER_TEST_F(LoginUIKeyboardTestWithUsersAndOwner,
@@ -307,12 +307,12 @@
   expected_input_methods.push_back(user_input_methods[2]);
   // Locale default input methods (the first one also is hardware IM).
   Append_en_US_InputMethods(&expected_input_methods);
-  // Active IM for the first user (active user POD).
+  // Enabled IM for the first user (active user POD).
   expected_input_methods.push_back(user_input_methods[0]);
 
   EXPECT_EQ(expected_input_methods, input_method::InputMethodManager::Get()
                                         ->GetActiveIMEState()
-                                        ->GetActiveInputMethodIds());
+                                        ->GetEnabledInputMethodIds());
 
   // Switch to Gaia.
   ASSERT_TRUE(LoginScreenTestApi::ClickAddUserButton());
@@ -327,7 +327,7 @@
 
   EXPECT_EQ(expected_input_methods, input_method::InputMethodManager::Get()
                                         ->GetActiveIMEState()
-                                        ->GetActiveInputMethodIds());
+                                        ->GetEnabledInputMethodIds());
 }
 
 class LoginUIKeyboardPolicy : public LoginManagerTest {
@@ -360,13 +360,13 @@
   Append_en_US_InputMethods(&expected_input_methods);
   EXPECT_EQ(input_method::InputMethodManager::Get()
                 ->GetActiveIMEState()
-                ->GetActiveInputMethodIds(),
+                ->GetEnabledInputMethodIds(),
             expected_input_methods);
 
   std::vector<std::string> allowed_input_method{"xkb:de::ger"};
   SetAllowedInputMethod(allowed_input_method.front());
   ASSERT_EQ(imm->GetActiveIMEState()->GetAllowedInputMethods().size(), 1U);
-  ASSERT_EQ(imm->GetActiveIMEState()->GetNumActiveInputMethods(), 1U);
+  ASSERT_EQ(imm->GetActiveIMEState()->GetNumEnabledInputMethods(), 1U);
 
   input_method::InputMethodManager::Get()->MigrateInputMethods(
       &allowed_input_method);
@@ -377,7 +377,7 @@
   // it will be there after the policy is gone.
   expected_input_methods.insert(
       expected_input_methods.begin(),
-      imm->GetActiveIMEState()->GetActiveInputMethodIds()[0]);
+      imm->GetActiveIMEState()->GetEnabledInputMethodIds()[0]);
 
   // Remove the policy again
   em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
@@ -389,7 +389,7 @@
   ASSERT_EQ(imm->GetActiveIMEState()->GetAllowedInputMethods().size(), 0U);
   ASSERT_EQ(expected_input_methods, input_method::InputMethodManager::Get()
                                         ->GetActiveIMEState()
-                                        ->GetActiveInputMethodIds());
+                                        ->GetEnabledInputMethodIds());
 }
 
 class LoginUIDevicePolicyUserAdding : public LoginUIKeyboardPolicy {
@@ -425,11 +425,11 @@
   Append_en_US_InputMethods(&default_input_methods);
   // Input methods should be default because the other user (which is focused)
   // does not have saved last input method.
-  EXPECT_EQ(user_adding_ime_state->GetActiveInputMethodIds(),
+  EXPECT_EQ(user_adding_ime_state->GetEnabledInputMethodIds(),
             default_input_methods);
 
   EXPECT_EQ(user_adding_ime_state->GetAllowedInputMethods().size(), 0u);
-  EXPECT_FALSE(base::Contains(user_adding_ime_state->GetActiveInputMethodIds(),
+  EXPECT_FALSE(base::Contains(user_adding_ime_state->GetEnabledInputMethodIds(),
                               allowed_input_method.front()));
 }
 
diff --git a/chrome/browser/ash/login/screens/welcome_screen.cc b/chrome/browser/ash/login/screens/welcome_screen.cc
index 3a52f14..52545ae 100644
--- a/chrome/browser/ash/login/screens/welcome_screen.cc
+++ b/chrome/browser/ash/login/screens/welcome_screen.cc
@@ -267,7 +267,7 @@
   const std::vector<std::string>& input_methods =
       input_method::InputMethodManager::Get()
           ->GetActiveIMEState()
-          ->GetActiveInputMethodIds();
+          ->GetEnabledInputMethodIds();
   if (input_method.empty() || !base::Contains(input_methods, input_method)) {
     LOG(WARNING) << "The input method is empty or ineligible!";
     return;
diff --git a/chrome/browser/ash/login/ui/login_display_host_common.cc b/chrome/browser/ash/login/ui/login_display_host_common.cc
index 6ddf90d..94468ab0 100644
--- a/chrome/browser/ash/login/ui/login_display_host_common.cc
+++ b/chrome/browser/ash/login/ui/login_display_host_common.cc
@@ -488,9 +488,9 @@
   if (IsAuthError(error)) {
     input_method::InputMethodManager* ime_manager =
         input_method::InputMethodManager::Get();
-    // Display a hint to switch keyboards if there are other active input
+    // Display a hint to switch keyboards if there are other enabled input
     // methods.
-    if (ime_manager->GetActiveIMEState()->GetNumActiveInputMethods() > 1) {
+    if (ime_manager->GetActiveIMEState()->GetNumEnabledInputMethods() > 1) {
       keyboard_hint =
           l10n_util::GetStringUTF8(IDS_LOGIN_ERROR_KEYBOARD_SWITCH_HINT);
     }
diff --git a/chrome/browser/ash/policy/core/device_cloud_policy_manager_ash.cc b/chrome/browser/ash/policy/core/device_cloud_policy_manager_ash.cc
index 0e3dc020..e699226 100644
--- a/chrome/browser/ash/policy/core/device_cloud_policy_manager_ash.cc
+++ b/chrome/browser/ash/policy/core/device_cloud_policy_manager_ash.cc
@@ -34,12 +34,15 @@
 #include "chrome/browser/ash/policy/rsu/lookup_key_uploader.h"
 #include "chrome/browser/ash/policy/server_backed_state/server_backed_state_keys_broker.h"
 #include "chrome/browser/ash/policy/status_collector/device_status_collector.h"
+#include "chrome/browser/ash/policy/status_collector/legacy_device_status_collector.h"
 #include "chrome/browser/ash/policy/status_collector/managed_session_service.h"
 #include "chrome/browser/ash/policy/uploading/heartbeat_scheduler.h"
 #include "chrome/browser/ash/policy/uploading/status_uploader.h"
 #include "chrome/browser/ash/policy/uploading/system_log_uploader.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/common/pref_names.h"
+#include "chromeos/settings/cros_settings_names.h"
+#include "chromeos/settings/cros_settings_provider.h"
 #include "chromeos/system/statistics_provider.h"
 #include "chromeos/tpm/install_attributes.h"
 #include "components/policy/core/common/cloud/cloud_external_data_manager.h"
@@ -299,11 +302,26 @@
 }
 
 void DeviceCloudPolicyManagerAsh::CreateStatusUploader() {
+  std::unique_ptr<StatusCollector> collector;
+  bool granular_reporting_enabled;
+  ash::CrosSettings* settings = ash::CrosSettings::Get();
+
+  if (!settings->GetBoolean(chromeos::kEnableDeviceGranularReporting,
+                            &granular_reporting_enabled)) {
+    granular_reporting_enabled = true;
+  }
+
+  if (granular_reporting_enabled) {
+    collector = std::make_unique<DeviceStatusCollector>(
+        local_state_, chromeos::system::StatisticsProvider::GetInstance());
+  } else {
+    collector = std::make_unique<LegacyDeviceStatusCollector>(
+        local_state_, chromeos::system::StatisticsProvider::GetInstance());
+  }
+
   status_uploader_ = std::make_unique<StatusUploader>(
-      client(),
-      std::make_unique<DeviceStatusCollector>(
-          local_state_, chromeos::system::StatisticsProvider::GetInstance()),
-      task_runner_, kDeviceStatusUploadFrequency);
+      client(), std::move(collector), task_runner_,
+      kDeviceStatusUploadFrequency);
 }
 
 }  // namespace policy
diff --git a/chrome/browser/ash/policy/core/device_local_account_browsertest.cc b/chrome/browser/ash/policy/core/device_local_account_browsertest.cc
index a621671..3ac96031 100644
--- a/chrome/browser/ash/policy/core/device_local_account_browsertest.cc
+++ b/chrome/browser/ash/policy/core/device_local_account_browsertest.cc
@@ -1952,7 +1952,7 @@
 
   EXPECT_GT(ash::input_method::InputMethodManager::Get()
                 ->GetActiveIMEState()
-                ->GetNumActiveInputMethods(),
+                ->GetNumEnabledInputMethods(),
             1u);
 }
 
@@ -1964,7 +1964,7 @@
 
   EXPECT_EQ(1u, ash::input_method::InputMethodManager::Get()
                     ->GetActiveIMEState()
-                    ->GetNumActiveInputMethods());
+                    ->GetNumEnabledInputMethods());
 }
 
 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest,
diff --git a/chrome/browser/ash/policy/status_collector/child_status_collector.cc b/chrome/browser/ash/policy/status_collector/child_status_collector.cc
index deb1807..7bcbd1e5 100644
--- a/chrome/browser/ash/policy/status_collector/child_status_collector.cc
+++ b/chrome/browser/ash/policy/status_collector/child_status_collector.cc
@@ -412,22 +412,26 @@
   OnAppActivityReportSubmitted();
 }
 
-bool ChildStatusCollector::ShouldReportActivityTimes() const {
+bool ChildStatusCollector::IsReportingActivityTimes() const {
   return true;
 }
 
-bool ChildStatusCollector::ShouldReportNetworkInterfaces() const {
+bool ChildStatusCollector::IsReportingHardwareData() const {
   return false;
 }
 
-bool ChildStatusCollector::ShouldReportUsers() const {
+bool ChildStatusCollector::IsReportingNetworkData() const {
   return false;
 }
 
-bool ChildStatusCollector::ShouldReportCrashReportInfo() const {
+bool ChildStatusCollector::IsReportingUsers() const {
   return false;
 }
-bool ChildStatusCollector::ShouldReportAppInfoAndActivity() const {
+
+bool ChildStatusCollector::IsReportingCrashReportInfo() const {
+  return false;
+}
+bool ChildStatusCollector::IsReportingAppInfoAndActivity() const {
   return false;
 }
 
diff --git a/chrome/browser/ash/policy/status_collector/child_status_collector.h b/chrome/browser/ash/policy/status_collector/child_status_collector.h
index a3c884b..ed360adf 100644
--- a/chrome/browser/ash/policy/status_collector/child_status_collector.h
+++ b/chrome/browser/ash/policy/status_collector/child_status_collector.h
@@ -68,11 +68,12 @@
   // StatusCollector:
   void GetStatusAsync(StatusCollectorCallback response) override;
   void OnSubmittedSuccessfully() override;
-  bool ShouldReportActivityTimes() const override;
-  bool ShouldReportNetworkInterfaces() const override;
-  bool ShouldReportUsers() const override;
-  bool ShouldReportCrashReportInfo() const override;
-  bool ShouldReportAppInfoAndActivity() const override;
+  bool IsReportingActivityTimes() const override;
+  bool IsReportingNetworkData() const override;
+  bool IsReportingHardwareData() const override;
+  bool IsReportingUsers() const override;
+  bool IsReportingCrashReportInfo() const override;
+  bool IsReportingAppInfoAndActivity() const override;
 
   // Returns the amount of time the child has used so far today. If there is no
   // user logged in, it returns 0.
diff --git a/chrome/browser/ash/policy/status_collector/child_status_collector_browsertest.cc b/chrome/browser/ash/policy/status_collector/child_status_collector_browsertest.cc
index 6287638..b369099 100644
--- a/chrome/browser/ash/policy/status_collector/child_status_collector_browsertest.cc
+++ b/chrome/browser/ash/policy/status_collector/child_status_collector_browsertest.cc
@@ -236,9 +236,11 @@
   void SetUp() override {
     RestartStatusCollector(base::BindRepeating(&GetEmptyAndroidStatus));
 
-    // Disable network interface reporting since it requires additional setup.
+    // Disable network reporting since it requires additional setup.
     scoped_testing_cros_settings_.device_settings()->SetBoolean(
-        chromeos::kReportDeviceNetworkInterfaces, false);
+        chromeos::kReportDeviceNetworkConfiguration, false);
+    scoped_testing_cros_settings_.device_settings()->SetBoolean(
+        chromeos::kReportDeviceNetworkStatus, false);
 
     // Mock clock in task environment is set to Unix Epoch, advance it to avoid
     // using times from before Unix Epoch in some tests.
diff --git a/chrome/browser/ash/policy/status_collector/device_status_collector.cc b/chrome/browser/ash/policy/status_collector/device_status_collector.cc
index c3c35bb8..d7241a0c 100644
--- a/chrome/browser/ash/policy/status_collector/device_status_collector.cc
+++ b/chrome/browser/ash/policy/status_collector/device_status_collector.cc
@@ -739,7 +739,8 @@
     cros_healthd_data_fetcher.Run(
         CrosHealthdCollectionMode::kFull,
         base::BindOnce(&DeviceStatusCollectorState::OnCrosHealthdDataReceived,
-                       this, report_system_info, report_vpd_info, report_storage_status));
+                       this, report_system_info, report_vpd_info,
+                       report_storage_status));
   }
 
   void FetchEMMCLifeTime(
@@ -826,7 +827,8 @@
     em::TpmStatusInfo* const tpm_status_proto =
         response_params_.device_status->mutable_tpm_status_info();
 
-    LOG(WARNING) << "tpm_status_struct.attestation_prepared: " << tpm_status_struct.attestation_prepared;
+    LOG(WARNING) << "tpm_status_struct.attestation_prepared: "
+                 << tpm_status_struct.attestation_prepared;
     tpm_status_proto->set_enabled(tpm_status_struct.enabled);
     tpm_status_proto->set_owned(tpm_status_struct.owned);
     tpm_status_proto->set_tpm_initialized(tpm_status_struct.initialized);
@@ -1567,8 +1569,6 @@
       chromeos::kReportDeviceBootMode, callback);
   audio_status_subscription_ = cros_settings_->AddSettingsObserver(
       chromeos::kReportDeviceAudioStatus, callback);
-  network_interfaces_subscription_ = cros_settings_->AddSettingsObserver(
-      chromeos::kReportDeviceNetworkInterfaces, callback);
   network_configuration_subscription_ = cros_settings_->AddSettingsObserver(
       chromeos::kReportDeviceNetworkConfiguration, callback);
   network_status_subscription_ = cros_settings_->AddSettingsObserver(
@@ -2872,7 +2872,7 @@
   app_info_generator_.OnReportedSuccessfully(last_requested_);
 }
 
-bool DeviceStatusCollector::ShouldReportActivityTimes() const {
+bool DeviceStatusCollector::IsReportingActivityTimes() const {
   // This function is used for checking if a message about activity reporting
   // should be displayed to a user in the transparency panel. User activity for
   // a current user is reported only if the user is managed by the same
@@ -2884,22 +2884,28 @@
   return !user_email.empty() && !IsDeviceLocalAccountUser(user_email, NULL);
 }
 // TODO(b/192252043): Remove this once management ui has been refactored.
-bool DeviceStatusCollector::ShouldReportNetworkInterfaces() const {
-  return false;
+bool DeviceStatusCollector::IsReportingNetworkData() const {
+  return report_network_configuration_ || report_network_status_;
 }
-bool DeviceStatusCollector::ShouldReportUsers() const {
+bool DeviceStatusCollector::IsReportingHardwareData() const {
+  return report_power_status_ || report_storage_status_ ||
+         report_board_status_ || report_memory_info_ || report_cpu_info_ ||
+         report_backlight_info_ || report_bluetooth_info_ || report_fan_info_ ||
+         report_vpd_info_ || report_system_info_;
+}
+bool DeviceStatusCollector::IsReportingUsers() const {
   // For more details, see comment in
-  // DeviceStatusCollector::ShouldReportActivityTimes() function.
+  // DeviceStatusCollector::IsReportingActivityTimes() function.
   if (!report_users_) {
     return false;
   }
   std::string user_email = GetUserForActivityReporting();
   return !user_email.empty() && !IsDeviceLocalAccountUser(user_email, NULL);
 }
-bool DeviceStatusCollector::ShouldReportCrashReportInfo() const {
+bool DeviceStatusCollector::IsReportingCrashReportInfo() const {
   return report_crash_report_info_ && stat_reporting_pref_;
 }
-bool DeviceStatusCollector::ShouldReportAppInfoAndActivity() const {
+bool DeviceStatusCollector::IsReportingAppInfoAndActivity() const {
   return report_app_info_;
 }
 
diff --git a/chrome/browser/ash/policy/status_collector/device_status_collector.h b/chrome/browser/ash/policy/status_collector/device_status_collector.h
index 7582e8d..bcf19fa 100644
--- a/chrome/browser/ash/policy/status_collector/device_status_collector.h
+++ b/chrome/browser/ash/policy/status_collector/device_status_collector.h
@@ -208,11 +208,12 @@
   // StatusCollector:
   void GetStatusAsync(StatusCollectorCallback response) override;
   void OnSubmittedSuccessfully() override;
-  bool ShouldReportActivityTimes() const override;
-  bool ShouldReportNetworkInterfaces() const override;
-  bool ShouldReportUsers() const override;
-  bool ShouldReportCrashReportInfo() const override;
-  bool ShouldReportAppInfoAndActivity() const override;
+  bool IsReportingActivityTimes() const override;
+  bool IsReportingNetworkData() const override;
+  bool IsReportingHardwareData() const override;
+  bool IsReportingUsers() const override;
+  bool IsReportingCrashReportInfo() const override;
+  bool IsReportingAppInfoAndActivity() const override;
 
   static void RegisterPrefs(PrefRegistrySimple* registry);
 
@@ -487,7 +488,6 @@
   base::CallbackListSubscription activity_times_subscription_;
   base::CallbackListSubscription audio_status_subscription_;
   base::CallbackListSubscription network_configuration_subscription_;
-  base::CallbackListSubscription network_interfaces_subscription_;
   base::CallbackListSubscription network_status_subscription_;
   base::CallbackListSubscription users_subscription_;
   base::CallbackListSubscription session_status_subscription_;
diff --git a/chrome/browser/ash/policy/status_collector/device_status_collector_browsertest.cc b/chrome/browser/ash/policy/status_collector/device_status_collector_browsertest.cc
index 1ced7a22..726442b 100644
--- a/chrome/browser/ash/policy/status_collector/device_status_collector_browsertest.cc
+++ b/chrome/browser/ash/policy/status_collector/device_status_collector_browsertest.cc
@@ -1492,8 +1492,8 @@
   scoped_testing_cros_settings_.device_settings()->SetBoolean(
       chromeos::kReportDeviceUsers, true);
 
-  EXPECT_FALSE(status_collector_->ShouldReportActivityTimes());
-  EXPECT_FALSE(status_collector_->ShouldReportUsers());
+  EXPECT_FALSE(status_collector_->IsReportingActivityTimes());
+  EXPECT_FALSE(status_collector_->IsReportingUsers());
 
   status_collector_->Simulate(test_states, 3);
   GetStatus();
@@ -1515,8 +1515,8 @@
       "public@public-accounts.device-local.localhost"));
   user_manager_->CreatePublicAccountUser(public_account_id);
 
-  EXPECT_FALSE(status_collector_->ShouldReportActivityTimes());
-  EXPECT_FALSE(status_collector_->ShouldReportUsers());
+  EXPECT_FALSE(status_collector_->IsReportingActivityTimes());
+  EXPECT_FALSE(status_collector_->IsReportingUsers());
 
   status_collector_->Simulate(test_states, 3);
   GetStatus();
@@ -1539,8 +1539,8 @@
       AccountId::FromUserEmail("public@web-kiosk-apps.device-local.localhost"));
   user_manager_->CreatePublicAccountUser(public_account_id);
 
-  EXPECT_FALSE(status_collector_->ShouldReportActivityTimes());
-  EXPECT_FALSE(status_collector_->ShouldReportUsers());
+  EXPECT_FALSE(status_collector_->IsReportingActivityTimes());
+  EXPECT_FALSE(status_collector_->IsReportingUsers());
 
   status_collector_->Simulate(test_states, 3);
   GetStatus();
@@ -1563,8 +1563,8 @@
   user_manager_->AddUserWithAffiliationAndType(account_id0, true,
                                                user_manager::USER_TYPE_REGULAR);
 
-  EXPECT_TRUE(status_collector_->ShouldReportActivityTimes());
-  EXPECT_TRUE(status_collector_->ShouldReportUsers());
+  EXPECT_TRUE(status_collector_->IsReportingActivityTimes());
+  EXPECT_TRUE(status_collector_->IsReportingUsers());
 
   status_collector_->Simulate(test_states, 3);
   GetStatus();
@@ -1578,8 +1578,8 @@
   scoped_testing_cros_settings_.device_settings()->SetBoolean(
       chromeos::kReportDeviceUsers, false);
 
-  EXPECT_TRUE(status_collector_->ShouldReportActivityTimes());
-  EXPECT_FALSE(status_collector_->ShouldReportUsers());
+  EXPECT_TRUE(status_collector_->IsReportingActivityTimes());
+  EXPECT_FALSE(status_collector_->IsReportingUsers());
 
   status_collector_->Simulate(test_states, 3);
   GetStatus();
@@ -1601,8 +1601,8 @@
   user_manager_->AddUserWithAffiliationAndType(account_id0, false,
                                                user_manager::USER_TYPE_REGULAR);
 
-  EXPECT_FALSE(status_collector_->ShouldReportActivityTimes());
-  EXPECT_FALSE(status_collector_->ShouldReportUsers());
+  EXPECT_FALSE(status_collector_->IsReportingActivityTimes());
+  EXPECT_FALSE(status_collector_->IsReportingUsers());
 
   status_collector_->Simulate(test_states, 3);
   GetStatus();
@@ -1614,8 +1614,8 @@
   scoped_testing_cros_settings_.device_settings()->SetBoolean(
       chromeos::kReportDeviceUsers, false);
 
-  EXPECT_FALSE(status_collector_->ShouldReportActivityTimes());
-  EXPECT_FALSE(status_collector_->ShouldReportUsers());
+  EXPECT_FALSE(status_collector_->IsReportingActivityTimes());
+  EXPECT_FALSE(status_collector_->IsReportingUsers());
 
   status_collector_->Simulate(test_states, 3);
   GetStatus();
diff --git a/chrome/browser/ash/policy/status_collector/legacy_device_status_collector.cc b/chrome/browser/ash/policy/status_collector/legacy_device_status_collector.cc
index 85d2eb1..bbb73226 100644
--- a/chrome/browser/ash/policy/status_collector/legacy_device_status_collector.cc
+++ b/chrome/browser/ash/policy/status_collector/legacy_device_status_collector.cc
@@ -2825,7 +2825,7 @@
   app_info_generator_.OnReportedSuccessfully(last_requested_);
 }
 
-bool LegacyDeviceStatusCollector::ShouldReportActivityTimes() const {
+bool LegacyDeviceStatusCollector::IsReportingActivityTimes() const {
   // This function is used for checking if a message about activity reporting
   // should be displayed to a user in the transparency panel. User activity for
   // a current user is reported only if the user is managed by the same
@@ -2836,22 +2836,25 @@
   std::string user_email = GetUserForActivityReporting();
   return !user_email.empty() && !IsDeviceLocalAccountUser(user_email, NULL);
 }
-bool LegacyDeviceStatusCollector::ShouldReportNetworkInterfaces() const {
+bool LegacyDeviceStatusCollector::IsReportingNetworkData() const {
   return report_network_interfaces_;
 }
-bool LegacyDeviceStatusCollector::ShouldReportUsers() const {
+bool LegacyDeviceStatusCollector::IsReportingUsers() const {
   // For more details, see comment in
-  // LegacyDeviceStatusCollector::ShouldReportActivityTimes() function.
+  // LegacyDeviceStatusCollector::IsReportingActivityTimes() function.
   if (!report_users_) {
     return false;
   }
   std::string user_email = GetUserForActivityReporting();
   return !user_email.empty() && !IsDeviceLocalAccountUser(user_email, NULL);
 }
-bool LegacyDeviceStatusCollector::ShouldReportCrashReportInfo() const {
+bool LegacyDeviceStatusCollector::IsReportingHardwareData() const {
+  return report_hardware_status_;
+}
+bool LegacyDeviceStatusCollector::IsReportingCrashReportInfo() const {
   return report_crash_report_info_ && stat_reporting_pref_;
 }
-bool LegacyDeviceStatusCollector::ShouldReportAppInfoAndActivity() const {
+bool LegacyDeviceStatusCollector::IsReportingAppInfoAndActivity() const {
   return report_app_info_;
 }
 
diff --git a/chrome/browser/ash/policy/status_collector/legacy_device_status_collector.h b/chrome/browser/ash/policy/status_collector/legacy_device_status_collector.h
index a76e8218..7f63a517 100644
--- a/chrome/browser/ash/policy/status_collector/legacy_device_status_collector.h
+++ b/chrome/browser/ash/policy/status_collector/legacy_device_status_collector.h
@@ -160,11 +160,12 @@
   // StatusCollector:
   void GetStatusAsync(StatusCollectorCallback response) override;
   void OnSubmittedSuccessfully() override;
-  bool ShouldReportActivityTimes() const override;
-  bool ShouldReportNetworkInterfaces() const override;
-  bool ShouldReportUsers() const override;
-  bool ShouldReportCrashReportInfo() const override;
-  bool ShouldReportAppInfoAndActivity() const override;
+  bool IsReportingActivityTimes() const override;
+  bool IsReportingNetworkData() const override;
+  bool IsReportingHardwareData() const override;
+  bool IsReportingUsers() const override;
+  bool IsReportingCrashReportInfo() const override;
+  bool IsReportingAppInfoAndActivity() const override;
 
   static void RegisterPrefs(PrefRegistrySimple* registry);
 
diff --git a/chrome/browser/ash/policy/status_collector/legacy_device_status_collector_browsertest.cc b/chrome/browser/ash/policy/status_collector/legacy_device_status_collector_browsertest.cc
index bb95f724..9a55d087 100644
--- a/chrome/browser/ash/policy/status_collector/legacy_device_status_collector_browsertest.cc
+++ b/chrome/browser/ash/policy/status_collector/legacy_device_status_collector_browsertest.cc
@@ -1487,8 +1487,8 @@
   scoped_testing_cros_settings_.device_settings()->SetBoolean(
       chromeos::kReportDeviceUsers, true);
 
-  EXPECT_FALSE(status_collector_->ShouldReportActivityTimes());
-  EXPECT_FALSE(status_collector_->ShouldReportUsers());
+  EXPECT_FALSE(status_collector_->IsReportingActivityTimes());
+  EXPECT_FALSE(status_collector_->IsReportingUsers());
 
   status_collector_->Simulate(test_states, 3);
   GetStatus();
@@ -1510,8 +1510,8 @@
       "public@public-accounts.device-local.localhost"));
   user_manager_->CreatePublicAccountUser(public_account_id);
 
-  EXPECT_FALSE(status_collector_->ShouldReportActivityTimes());
-  EXPECT_FALSE(status_collector_->ShouldReportUsers());
+  EXPECT_FALSE(status_collector_->IsReportingActivityTimes());
+  EXPECT_FALSE(status_collector_->IsReportingUsers());
 
   status_collector_->Simulate(test_states, 3);
   GetStatus();
@@ -1534,8 +1534,8 @@
       AccountId::FromUserEmail("public@web-kiosk-apps.device-local.localhost"));
   user_manager_->CreatePublicAccountUser(public_account_id);
 
-  EXPECT_FALSE(status_collector_->ShouldReportActivityTimes());
-  EXPECT_FALSE(status_collector_->ShouldReportUsers());
+  EXPECT_FALSE(status_collector_->IsReportingActivityTimes());
+  EXPECT_FALSE(status_collector_->IsReportingUsers());
 
   status_collector_->Simulate(test_states, 3);
   GetStatus();
@@ -1558,8 +1558,8 @@
   user_manager_->AddUserWithAffiliationAndType(account_id0, true,
                                                user_manager::USER_TYPE_REGULAR);
 
-  EXPECT_TRUE(status_collector_->ShouldReportActivityTimes());
-  EXPECT_TRUE(status_collector_->ShouldReportUsers());
+  EXPECT_TRUE(status_collector_->IsReportingActivityTimes());
+  EXPECT_TRUE(status_collector_->IsReportingUsers());
 
   status_collector_->Simulate(test_states, 3);
   GetStatus();
@@ -1573,8 +1573,8 @@
   scoped_testing_cros_settings_.device_settings()->SetBoolean(
       chromeos::kReportDeviceUsers, false);
 
-  EXPECT_TRUE(status_collector_->ShouldReportActivityTimes());
-  EXPECT_FALSE(status_collector_->ShouldReportUsers());
+  EXPECT_TRUE(status_collector_->IsReportingActivityTimes());
+  EXPECT_FALSE(status_collector_->IsReportingUsers());
 
   status_collector_->Simulate(test_states, 3);
   GetStatus();
@@ -1596,8 +1596,8 @@
   user_manager_->AddUserWithAffiliationAndType(account_id0, false,
                                                user_manager::USER_TYPE_REGULAR);
 
-  EXPECT_FALSE(status_collector_->ShouldReportActivityTimes());
-  EXPECT_FALSE(status_collector_->ShouldReportUsers());
+  EXPECT_FALSE(status_collector_->IsReportingActivityTimes());
+  EXPECT_FALSE(status_collector_->IsReportingUsers());
 
   status_collector_->Simulate(test_states, 3);
   GetStatus();
@@ -1609,8 +1609,8 @@
   scoped_testing_cros_settings_.device_settings()->SetBoolean(
       chromeos::kReportDeviceUsers, false);
 
-  EXPECT_FALSE(status_collector_->ShouldReportActivityTimes());
-  EXPECT_FALSE(status_collector_->ShouldReportUsers());
+  EXPECT_FALSE(status_collector_->IsReportingActivityTimes());
+  EXPECT_FALSE(status_collector_->IsReportingUsers());
 
   status_collector_->Simulate(test_states, 3);
   GetStatus();
diff --git a/chrome/browser/ash/policy/status_collector/status_collector.h b/chrome/browser/ash/policy/status_collector/status_collector.h
index f259c17..e2b4c4c 100644
--- a/chrome/browser/ash/policy/status_collector/status_collector.h
+++ b/chrome/browser/ash/policy/status_collector/status_collector.h
@@ -98,14 +98,15 @@
   // the server.
   virtual void OnSubmittedSuccessfully() = 0;
 
-  // Methods used to decide whether a specific categories of data should be
-  // included in the reports or not. See:
+  // Methods used to determine if privacy notes should be displayed in
+  // management UI.
   // https://cs.chromium.org/search/?q=AddDeviceReportingInfo
-  virtual bool ShouldReportActivityTimes() const = 0;
-  virtual bool ShouldReportNetworkInterfaces() const = 0;
-  virtual bool ShouldReportUsers() const = 0;
-  virtual bool ShouldReportCrashReportInfo() const = 0;
-  virtual bool ShouldReportAppInfoAndActivity() const = 0;
+  virtual bool IsReportingActivityTimes() const = 0;
+  virtual bool IsReportingNetworkData() const = 0;
+  virtual bool IsReportingHardwareData() const = 0;
+  virtual bool IsReportingUsers() const = 0;
+  virtual bool IsReportingCrashReportInfo() const = 0;
+  virtual bool IsReportingAppInfoAndActivity() const = 0;
 
   // Returns the DeviceLocalAccount associated with the currently active kiosk
   // session, if the session was auto-launched with zero delay (this enables
diff --git a/chrome/browser/ash/policy/uploading/status_uploader.cc b/chrome/browser/ash/policy/uploading/status_uploader.cc
index 57a8be488b..b2ff49e0 100644
--- a/chrome/browser/ash/policy/uploading/status_uploader.cc
+++ b/chrome/browser/ash/policy/uploading/status_uploader.cc
@@ -15,9 +15,13 @@
 #include "base/syslog_logging.h"
 #include "base/system/sys_info.h"
 #include "chrome/browser/ash/policy/core/device_local_account.h"
+#include "chrome/browser/ash/policy/status_collector/device_status_collector.h"
+#include "chrome/browser/ash/policy/status_collector/legacy_device_status_collector.h"
 #include "chrome/browser/ash/policy/status_collector/status_collector.h"
+#include "chrome/browser/browser_process.h"
 #include "chromeos/settings/cros_settings_names.h"
 #include "chromeos/settings/cros_settings_provider.h"
+#include "chromeos/system/statistics_provider.h"
 #include "components/policy/core/common/cloud/cloud_policy_client.h"
 #include "components/policy/core/common/cloud/device_management_service.h"
 #include "content/public/browser/browser_thread.h"
@@ -59,6 +63,11 @@
           chromeos::kReportUploadFrequency,
           base::BindRepeating(&StatusUploader::RefreshUploadFrequency,
                               base::Unretained(this)));
+  granular_reporting_subscription_ =
+      ash::CrosSettings::Get()->AddSettingsObserver(
+          chromeos::kEnableDeviceGranularReporting,
+          base::BindRepeating(&StatusUploader::UpdateStatusCollector,
+                              base::Unretained(this)));
 
   // Update the upload frequency from settings.
   RefreshUploadFrequency();
@@ -102,6 +111,37 @@
   return true;
 }
 
+void StatusUploader::UpdateStatusCollector() {
+  if (user_manager::UserManager::Get()->GetActiveUser()->IsChild()) {
+    return;
+  }
+
+  ash::CrosSettings* settings = ash::CrosSettings::Get();
+  if (chromeos::CrosSettingsProvider::TRUSTED !=
+      settings->PrepareTrustedValues(
+          base::BindOnce(&StatusUploader::UpdateStatusCollector,
+                         weak_factory_.GetWeakPtr()))) {
+    return;
+  }
+
+  bool granular_reporting_enabled;
+  if (!settings->GetBoolean(chromeos::kEnableDeviceGranularReporting,
+                            &granular_reporting_enabled)) {
+    granular_reporting_enabled = true;
+  }
+  PrefService* local_state = g_browser_process->local_state();
+
+  if (granular_reporting_enabled) {
+    SYSLOG(INFO) << "Enabling granular reporting controls";
+    collector_ = std::make_unique<DeviceStatusCollector>(
+        local_state, chromeos::system::StatisticsProvider::GetInstance());
+  } else {
+    SYSLOG(INFO) << "Disabling granular reporting controls";
+    collector_ = std::make_unique<LegacyDeviceStatusCollector>(
+        local_state, chromeos::system::StatisticsProvider::GetInstance());
+  }
+}
+
 void StatusUploader::RefreshUploadFrequency() {
   // Attempt to fetch the current value of the reporting settings.
   // If trusted values are not available, register this function to be called
diff --git a/chrome/browser/ash/policy/uploading/status_uploader.h b/chrome/browser/ash/policy/uploading/status_uploader.h
index b5c92839..718a3e5 100644
--- a/chrome/browser/ash/policy/uploading/status_uploader.h
+++ b/chrome/browser/ash/policy/uploading/status_uploader.h
@@ -85,6 +85,9 @@
   // if appropriate.
   void RefreshUploadFrequency();
 
+  // Updates the status collector being used.
+  void UpdateStatusCollector();
+
   // CloudPolicyClient used to issue requests to the server.
   CloudPolicyClient* client_;
 
@@ -100,6 +103,9 @@
   // Subscription for the callback about changes in the upload frequency.
   base::CallbackListSubscription upload_frequency_subscription_;
 
+  // Subscription for whether or not to user granular reporting.
+  base::CallbackListSubscription granular_reporting_subscription_;
+
   // The time the last upload was performed.
   base::Time last_upload_;
 
diff --git a/chrome/browser/ash/remote_apps/remote_apps_manager.cc b/chrome/browser/ash/remote_apps/remote_apps_manager.cc
index aa62e100..4171cebe 100644
--- a/chrome/browser/ash/remote_apps/remote_apps_manager.cc
+++ b/chrome/browser/ash/remote_apps/remote_apps_manager.cc
@@ -197,7 +197,7 @@
   // Move all items out of the folder. Empty folders are automatically deleted.
   RemoteAppsModel::FolderInfo& folder_info = model_->GetFolderInfo(folder_id);
   for (const auto& app : folder_info.items)
-    model_updater_->MoveItemToFolder(app, std::string());
+    model_updater_->SetItemFolderId(app, std::string());
   model_->DeleteFolder(folder_id);
   return RemoteAppsError::kNone;
 }
@@ -318,7 +318,7 @@
   // we don't have to check if it was deleted.
   if (!folder_id.empty()) {
     bool folder_already_exists = model_updater_->FindFolderItem(folder_id);
-    model_updater_->MoveItemToFolder(id, folder_id);
+    model_updater_->SetItemFolderId(id, folder_id);
     RemoteAppsModel::FolderInfo& folder_info = model_->GetFolderInfo(folder_id);
 
     if (!folder_already_exists) {
diff --git a/chrome/browser/ash/scanning/scan_service.cc b/chrome/browser/ash/scanning/scan_service.cc
index a603be7..23fc68a 100644
--- a/chrome/browser/ash/scanning/scan_service.cc
+++ b/chrome/browser/ash/scanning/scan_service.cc
@@ -251,6 +251,8 @@
   multi_page_controller_receiver_.set_disconnect_handler(base::BindOnce(
       &ScanService::ResetMultiPageScanController, base::Unretained(this)));
   std::move(callback).Run(std::move(pending_remote));
+
+  multi_page_start_time_ = base::TimeTicks::Now();
 }
 
 bool ScanService::SendScanRequest(
@@ -363,6 +365,10 @@
                   lorgnette::SCAN_FAILURE_MODE_NO_FAILURE);
   base::UmaHistogramCounts100("Scanning.MultiPageScan.NumPagesScanned",
                               num_pages_scanned_);
+  base::UmaHistogramLongTimes100(
+      "Scanning.MultiPageScan.SessionDuration",
+      base::TimeTicks::Now() - multi_page_start_time_);
+  multi_page_start_time_ = base::TimeTicks();
   multi_page_controller_receiver_.reset();
 }
 
diff --git a/chrome/browser/ash/scanning/scan_service.h b/chrome/browser/ash/scanning/scan_service.h
index 9255114..e22178c 100644
--- a/chrome/browser/ash/scanning/scan_service.h
+++ b/chrome/browser/ash/scanning/scan_service.h
@@ -215,6 +215,10 @@
   // a user launching the Scan app and being able to interact with it.
   base::TimeTicks get_scanners_time_;
 
+  // The time a multi-page scan session starts. Used to record the duration of a
+  // multi-page scan session.
+  base::TimeTicks multi_page_start_time_;
+
   // Helper class for for file path manipulation and verification.
   ScanningFilePathHelper file_path_helper_;
 
diff --git a/chrome/browser/browser_features.cc b/chrome/browser/browser_features.cc
index 8e28549..d22035a 100644
--- a/chrome/browser/browser_features.cc
+++ b/chrome/browser/browser_features.cc
@@ -77,8 +77,8 @@
 
 bool ShouldTriggerNetworkDataMigration() {
 #if defined(OS_WIN)
-  // LPAC Sandbox enabled means data must be migrated.
-  if (sandbox::policy::features::IsNetworkServiceSandboxLPACEnabled())
+  // On Windows, if sandbox enabled means data must be migrated.
+  if (sandbox::policy::features::IsWinNetworkServiceSandboxEnabled())
     return true;
 #endif  // defined(OS_WIN)
   if (base::FeatureList::IsEnabled(kTriggerNetworkDataMigration))
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index d1bb0707..f2427f6f 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -1984,9 +1984,10 @@
   return base::FeatureList::IsEnabled(features::kSitePerProcess);
 }
 
-bool ChromeContentBrowserClient::ShouldDisableSiteIsolation() {
+bool ChromeContentBrowserClient::ShouldDisableSiteIsolation(
+    content::SiteIsolationMode site_isolation_mode) {
   return site_isolation::SiteIsolationPolicy::
-      ShouldDisableSiteIsolationDueToMemoryThreshold();
+      ShouldDisableSiteIsolationDueToMemoryThreshold(site_isolation_mode);
 }
 
 std::vector<std::string>
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h
index 35aeec2..145eaf8 100644
--- a/chrome/browser/chrome_content_browser_client.h
+++ b/chrome/browser/chrome_content_browser_client.h
@@ -219,7 +219,8 @@
   bool ShouldAssignSiteForURL(const GURL& url) override;
   std::vector<url::Origin> GetOriginsRequiringDedicatedProcess() override;
   bool ShouldEnableStrictSiteIsolation() override;
-  bool ShouldDisableSiteIsolation() override;
+  bool ShouldDisableSiteIsolation(
+      content::SiteIsolationMode site_isolation_mode) override;
   std::vector<std::string> GetAdditionalSiteIsolationModes() override;
   void PersistIsolatedOrigin(
       content::BrowserContext* context,
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index ddd190c..fe25b5e 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -636,6 +636,10 @@
     "../ash/app_mode/web_app/web_kiosk_app_manager.h",
     "../ash/app_restore/app_launch_handler.cc",
     "../ash/app_restore/app_launch_handler.h",
+    "../ash/app_restore/app_restore_arc_task_handler.cc",
+    "../ash/app_restore/app_restore_arc_task_handler.h",
+    "../ash/app_restore/app_restore_arc_task_handler_factory.cc",
+    "../ash/app_restore/app_restore_arc_task_handler_factory.h",
     "../ash/app_restore/arc_app_launch_handler.cc",
     "../ash/app_restore/arc_app_launch_handler.h",
     "../ash/app_restore/arc_ghost_window_delegate.cc",
@@ -650,10 +654,6 @@
     "../ash/app_restore/arc_window_utils.h",
     "../ash/app_restore/full_restore_app_launch_handler.cc",
     "../ash/app_restore/full_restore_app_launch_handler.h",
-    "../ash/app_restore/full_restore_arc_task_handler.cc",
-    "../ash/app_restore/full_restore_arc_task_handler.h",
-    "../ash/app_restore/full_restore_arc_task_handler_factory.cc",
-    "../ash/app_restore/full_restore_arc_task_handler_factory.h",
     "../ash/app_restore/full_restore_data_handler.cc",
     "../ash/app_restore/full_restore_data_handler.h",
     "../ash/app_restore/full_restore_prefs.cc",
diff --git a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
index 47575d6..7f153f6f 100644
--- a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
+++ b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
@@ -5038,6 +5038,14 @@
                       base::NumberToString(display_id)})));
   }
 
+  // ThroughputTracker::Stop does not invoke the report callback when
+  // gpu-process crashes and has no valid data to report. Start a timer to
+  // handle this case.
+  timeout_timer_.Start(
+      FROM_HERE, base::TimeDelta::FromSeconds(5),
+      base::BindOnce(&AutotestPrivateStopSmoothnessTrackingFunction::OnTimeOut,
+                     this, display_id));
+
   it->second.callback = base::BindOnce(
       &AutotestPrivateStopSmoothnessTrackingFunction::OnReportData, this);
   it->second.stopping = true;
@@ -5048,6 +5056,11 @@
 
 void AutotestPrivateStopSmoothnessTrackingFunction::OnReportData(
     const cc::FrameSequenceMetrics::CustomReportData& data) {
+  if (did_respond())
+    return;
+
+  timeout_timer_.AbandonAndStop();
+
   api::autotest_private::ThroughputTrackerAnimationData result_data;
   result_data.frames_expected = data.frames_expected;
   result_data.frames_produced = data.frames_produced;
@@ -5058,6 +5071,21 @@
           result_data)));
 }
 
+void AutotestPrivateStopSmoothnessTrackingFunction::OnTimeOut(
+    int64_t display_id) {
+  if (did_respond())
+    return;
+
+  // Clean up the non-functional tracker.
+  auto* infos = GetDisplaySmoothnessTrackerInfos();
+  auto it = infos->find(display_id);
+  if (it == infos->end())
+    return;
+  infos->erase(it);
+
+  Respond(Error("Smoothness is not available"));
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // AutotestPrivateWaitForAmbientPhotoAnimationFunction
 //////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h
index db3be91e..ea76e98 100644
--- a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h
+++ b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h
@@ -1347,6 +1347,9 @@
   ResponseAction Run() override;
 
   void OnReportData(const cc::FrameSequenceMetrics::CustomReportData& data);
+  void OnTimeOut(int64_t display_id);
+
+  base::OneShotTimer timeout_timer_;
 };
 
 class AutotestPrivateWaitForAmbientPhotoAnimationFunction
diff --git a/chrome/browser/chromeos/extensions/input_method_api.cc b/chrome/browser/chromeos/extensions/input_method_api.cc
index 2ad4056..214bfca 100644
--- a/chrome/browser/chromeos/extensions/input_method_api.cc
+++ b/chrome/browser/chromeos/extensions/input_method_api.cc
@@ -152,7 +152,7 @@
   scoped_refptr<ash::input_method::InputMethodManager::State> ime_state =
       ash::input_method::InputMethodManager::Get()->GetActiveIMEState();
   const std::vector<std::string>& input_methods =
-      ime_state->GetActiveInputMethodIds();
+      ime_state->GetEnabledInputMethodIds();
   for (size_t i = 0; i < input_methods.size(); ++i) {
     const std::string& input_method = input_methods[i];
     if (input_method == params->input_method_id) {
@@ -175,7 +175,7 @@
   scoped_refptr<ash::input_method::InputMethodManager::State> ime_state =
       manager->GetActiveIMEState();
   std::unique_ptr<ash::input_method::InputMethodDescriptors> input_methods =
-      ime_state->GetActiveInputMethods();
+      ime_state->GetEnabledInputMethods();
   for (size_t i = 0; i < input_methods->size(); ++i) {
     const ash::input_method::InputMethodDescriptor& input_method =
         (*input_methods)[i];
diff --git a/chrome/browser/chromeos/preferences.cc b/chrome/browser/chromeos/preferences.cc
index 2d9baa5..577d0cd 100644
--- a/chrome/browser/chromeos/preferences.cc
+++ b/chrome/browser/chromeos/preferences.cc
@@ -914,7 +914,7 @@
 
     if (managed_by_policy) {
       preload_engines_.SetValue(
-          base::JoinString(ime_state_->GetActiveInputMethodIds(), ","));
+          base::JoinString(ime_state_->GetEnabledInputMethodIds(), ","));
     }
   }
   if (reason != REASON_PREF_CHANGED || pref_name == ::prefs::kAllowedLanguages)
diff --git a/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceDropNotificationManager.java b/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceDropNotificationManager.java
index d77ff0e84..c7adf98 100644
--- a/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceDropNotificationManager.java
+++ b/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceDropNotificationManager.java
@@ -217,15 +217,6 @@
     }
 
     /**
-     * @See {@link #onNotificationActionClicked(String, String, String, boolean)}.
-     */
-    @Deprecated
-    public void onNotificationActionClicked(String actionId, String url, @Nullable String offerId) {
-        // TODO(xingliu): Change download stream callsite and remove this.
-        onNotificationActionClicked(actionId, url, offerId, /*recordMetrics=*/true);
-    }
-
-    /**
      * @return The intent that we will use to send users to the tab which triggered the
      *         notification.
      *
@@ -264,15 +255,6 @@
     }
 
     /**
-     * See {@link #getNotificationActionClickIntent(String, String)}, without an offer id.
-     */
-    @Deprecated
-    public Intent getNotificationActionClickIntent(String actionId, String url) {
-        // TODO(xingliu): Make changes in downstream and delete this function. OfferId is needed.
-        return getNotificationActionClickIntent(actionId, url, /*offerId=*/null);
-    }
-
-    /**
      * @return Whether app notifications are enabled.
      */
     public boolean areAppNotificationsEnabled() {
diff --git a/chrome/browser/commerce/price_tracking/android/javatests/src/org/chromium/chrome/browser/price_tracking/PriceDropNotificationManagerTest.java b/chrome/browser/commerce/price_tracking/android/javatests/src/org/chromium/chrome/browser/price_tracking/PriceDropNotificationManagerTest.java
index ea8f07a3..d88c6cf 100644
--- a/chrome/browser/commerce/price_tracking/android/javatests/src/org/chromium/chrome/browser/price_tracking/PriceDropNotificationManagerTest.java
+++ b/chrome/browser/commerce/price_tracking/android/javatests/src/org/chromium/chrome/browser/price_tracking/PriceDropNotificationManagerTest.java
@@ -242,12 +242,12 @@
                         SubscriptionManagementType.CHROME_MANAGED, TrackingIdType.OFFER_ID);
 
         mPriceDropNotificationManager.onNotificationActionClicked(
-                ACTION_ID_TURN_OFF_ALERT, TEST_URL, null);
+                ACTION_ID_TURN_OFF_ALERT, TEST_URL, null, false);
         verify(mMockSubscriptionsManager, times(0))
                 .unsubscribe(eq(commerceSubscription), any(Callback.class));
 
         mPriceDropNotificationManager.onNotificationActionClicked(
-                ACTION_ID_TURN_OFF_ALERT, TEST_URL, offerId);
+                ACTION_ID_TURN_OFF_ALERT, TEST_URL, offerId, false);
         verify(mMockSubscriptionsManager, times(1))
                 .unsubscribe(eq(commerceSubscription), any(Callback.class));
     }
diff --git a/chrome/browser/extensions/activity_log/activity_log.cc b/chrome/browser/extensions/activity_log/activity_log.cc
index 7b388e2..4accc05 100644
--- a/chrome/browser/extensions/activity_log/activity_log.cc
+++ b/chrome/browser/extensions/activity_log/activity_log.cc
@@ -25,7 +25,6 @@
 #include "chrome/browser/extensions/activity_log/activity_action_constants.h"
 #include "chrome/browser/extensions/activity_log/counting_policy.h"
 #include "chrome/browser/extensions/activity_log/fullstream_ui_policy.h"
-#include "chrome/browser/extensions/api/activity_log_private/activity_log_private_api.h"
 #include "chrome/browser/extensions/extension_tab_util.h"
 #include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/browser/profiles/profile.h"
@@ -48,6 +47,9 @@
 #include "extensions/browser/renderer_startup_helper.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/extension_messages.h"
+#include "extensions/common/features/feature.h"
+#include "extensions/common/features/feature_provider.h"
+#include "extensions/common/hashed_extension_id.h"
 #include "extensions/common/mojom/renderer.mojom.h"
 #include "third_party/re2/src/re2/re2.h"
 #include "url/gurl.h"
@@ -359,6 +361,13 @@
   return ActivityLog::GetInstance(browser_context);
 }
 
+bool IsExtensionAllowlisted(const std::string& extension_id) {
+  // TODO(devlin): Pass in a HashedExtensionId to avoid this conversion.
+  return FeatureProvider::GetPermissionFeatures()
+      ->GetFeature("activityLogPrivate")
+      ->IsIdInAllowlist(HashedExtensionId(extension_id));
+}
+
 // Calls into the ActivityLog to log an api event or function call.
 void LogApiActivity(content::BrowserContext* browser_context,
                     const std::string& extension_id,
@@ -366,7 +375,7 @@
                     const base::ListValue& args,
                     Action::ActionType type) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  if (ActivityLogAPI::IsExtensionAllowlisted(extension_id))
+  if (IsExtensionAllowlisted(extension_id))
     return;
 
   ActivityLog* activity_log = SafeGetActivityLog(browser_context);
@@ -405,7 +414,7 @@
                            const std::string& api_call,
                            std::unique_ptr<base::DictionaryValue> details) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  if (ActivityLogAPI::IsExtensionAllowlisted(extension_id))
+  if (IsExtensionAllowlisted(extension_id))
     return;
 
   ActivityLog* activity_log = SafeGetActivityLog(browser_context);
@@ -569,7 +578,7 @@
 
 void ActivityLog::OnExtensionLoaded(content::BrowserContext* browser_context,
                                     const Extension* extension) {
-  if (!ActivityLogAPI::IsExtensionAllowlisted(extension->id()))
+  if (!IsExtensionAllowlisted(extension->id()))
     return;
 
   ++active_consumers_;
@@ -584,7 +593,7 @@
 void ActivityLog::OnExtensionUnloaded(content::BrowserContext* browser_context,
                                       const Extension* extension,
                                       UnloadedExtensionReason reason) {
-  if (!ActivityLogAPI::IsExtensionAllowlisted(extension->id()))
+  if (!IsExtensionAllowlisted(extension->id()))
     return;
   --active_consumers_;
 
@@ -600,7 +609,7 @@
     content::BrowserContext* browser_context,
     const Extension* extension,
     extensions::UninstallReason reason) {
-  if (ActivityLogAPI::IsExtensionAllowlisted(extension->id()) &&
+  if (IsExtensionAllowlisted(extension->id()) &&
       !base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kEnableExtensionActivityLogging) &&
       active_consumers_ == 0) {
@@ -657,7 +666,7 @@
   // Do not log for activities from the browser/WebUI, which is indicated by an
   // empty extension ID.
   return is_active_ && !extension_id.empty() &&
-         !ActivityLogAPI::IsExtensionAllowlisted(extension_id);
+         !IsExtensionAllowlisted(extension_id);
 }
 
 void ActivityLog::OnScriptsExecuted(content::WebContents* web_contents,
@@ -669,7 +678,7 @@
   for (auto it = extension_ids.begin(); it != extension_ids.end(); ++it) {
     const Extension* extension =
         registry->GetExtensionById(it->first, ExtensionRegistry::ENABLED);
-    if (!extension || ActivityLogAPI::IsExtensionAllowlisted(extension->id()))
+    if (!extension || IsExtensionAllowlisted(extension->id()))
       continue;
 
     // If OnScriptsExecuted is fired because of tabs.executeScript, the list
diff --git a/chrome/browser/extensions/activity_log/activity_log_enabled_unittest.cc b/chrome/browser/extensions/activity_log/activity_log_enabled_unittest.cc
index 78b98a5..827ba57 100644
--- a/chrome/browser/extensions/activity_log/activity_log_enabled_unittest.cc
+++ b/chrome/browser/extensions/activity_log/activity_log_enabled_unittest.cc
@@ -7,7 +7,6 @@
 #include "base/test/scoped_command_line.h"
 #include "chrome/browser/extensions/activity_log/activity_log.h"
 #include "chrome/browser/extensions/activity_log/activity_log_task_runner.h"
-#include "chrome/browser/extensions/api/activity_log_private/activity_log_private_api.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/test_extension_system.h"
 #include "chrome/common/chrome_switches.h"
diff --git a/chrome/browser/extensions/api/activity_log_private/activity_log_private_api.cc b/chrome/browser/extensions/api/activity_log_private/activity_log_private_api.cc
index 40c12d8..654aaa34 100644
--- a/chrome/browser/extensions/api/activity_log_private/activity_log_private_api.cc
+++ b/chrome/browser/extensions/api/activity_log_private/activity_log_private_api.cc
@@ -22,9 +22,6 @@
 #include "content/public/browser/browser_context.h"
 #include "extensions/browser/extension_system_provider.h"
 #include "extensions/browser/extensions_browser_client.h"
-#include "extensions/common/features/feature.h"
-#include "extensions/common/features/feature_provider.h"
-#include "extensions/common/hashed_extension_id.h"
 
 namespace extensions {
 
@@ -74,14 +71,6 @@
   activity_log_->RemoveObserver(this);
 }
 
-// static
-bool ActivityLogAPI::IsExtensionAllowlisted(const std::string& extension_id) {
-  // TODO(devlin): Pass in a HashedExtensionId to avoid this conversion.
-  return FeatureProvider::GetPermissionFeatures()
-      ->GetFeature("activityLogPrivate")
-      ->IsIdInAllowlist(HashedExtensionId(extension_id));
-}
-
 void ActivityLogAPI::OnListenerAdded(const EventListenerInfo& details) {
   if (activity_log_->has_listeners())
     return;
diff --git a/chrome/browser/extensions/api/activity_log_private/activity_log_private_api.h b/chrome/browser/extensions/api/activity_log_private/activity_log_private_api.h
index 8df0861..5fac6632 100644
--- a/chrome/browser/extensions/api/activity_log_private/activity_log_private_api.h
+++ b/chrome/browser/extensions/api/activity_log_private/activity_log_private_api.h
@@ -39,9 +39,6 @@
 
   void Shutdown() override;
 
-  // Lookup whether the extension ID is allowlisted.
-  static bool IsExtensionAllowlisted(const std::string& extension_id);
-
  private:
   friend class BrowserContextKeyedAPIFactory<ActivityLogAPI>;
   static const char* service_name() { return "ActivityLogPrivateAPI"; }
diff --git a/chrome/browser/extensions/api/scripting/scripting_api.cc b/chrome/browser/extensions/api/scripting/scripting_api.cc
index 5c2a6ff..ffa75d9 100644
--- a/chrome/browser/extensions/api/scripting/scripting_api.cc
+++ b/chrome/browser/extensions/api/scripting/scripting_api.cc
@@ -18,6 +18,7 @@
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "extensions/browser/api/extension_types_utils.h"
+#include "extensions/browser/api/scripting/constants.h"
 #include "extensions/browser/extension_api_frame_id_map.h"
 #include "extensions/browser/extension_file_task_runner.h"
 #include "extensions/browser/extension_system.h"
@@ -53,16 +54,6 @@
 constexpr mojom::RunLocation kCSSRunLocation =
     mojom::RunLocation::kDocumentStart;
 
-// TODO(crbug.com/1168627): The can_execute_script_everywhere flag is currently
-// only used by the legacy version Chromevox extension. We can assume it will
-// always be false here, but it may be added back if needed.
-constexpr bool kScriptsCanExecuteEverywhere = false;
-
-// The all_urls_includes_chrome_urls flag is only true for the legacy ChromeVox
-// extension, which does not call this API. Therefore we can assume it to be
-// always false.
-constexpr bool kAllUrlsIncludesChromeUrls = false;
-
 // Converts the given `style_origin` to a CSSOrigin.
 mojom::CSSOrigin ConvertStyleOriginToCSSOrigin(
     api::scripting::StyleOrigin style_origin) {
@@ -360,8 +351,8 @@
   if (!script_parsing::ParseMatchPatterns(
           *content_script.matches, content_script.exclude_matches.get(),
           definition_index, extension.creation_flags(),
-          kScriptsCanExecuteEverywhere, valid_schemes,
-          kAllUrlsIncludesChromeUrls, result.get(), error,
+          scripting::kScriptsCanExecuteEverywhere, valid_schemes,
+          scripting::kAllUrlsIncludesChromeUrls, result.get(), error,
           /*wants_file_access=*/nullptr)) {
     return nullptr;
   }
@@ -822,8 +813,9 @@
 
   std::u16string parse_error;
   auto parsed_scripts = std::make_unique<UserScriptList>();
-  const int valid_schemes =
-      UserScript::ValidUserScriptSchemes(kScriptsCanExecuteEverywhere);
+  std::set<std::string> persistent_script_ids;
+  const int valid_schemes = UserScript::ValidUserScriptSchemes(
+      scripting::kScriptsCanExecuteEverywhere);
 
   parsed_scripts->reserve(scripts.size());
   for (size_t i = 0; i < scripts.size(); ++i) {
@@ -839,6 +831,11 @@
     if (!user_script)
       return RespondNow(Error(base::UTF16ToASCII(parse_error)));
 
+    // Scripts will persist across sessions by default.
+    if (!scripts[i].persist_across_sessions ||
+        *scripts[i].persist_across_sessions) {
+      persistent_script_ids.insert(user_script->id());
+    }
     parsed_scripts->push_back(std::move(user_script));
   }
 
@@ -853,7 +850,7 @@
                      std::move(parsed_scripts)),
       base::BindOnce(&ScriptingRegisterContentScriptsFunction::
                          OnContentScriptFilesValidated,
-                     this));
+                     this, std::move(persistent_script_ids)));
 
   // Balanced in `OnContentScriptFilesValidated()` or
   // `OnContentScriptsRegistered()`.
@@ -862,6 +859,7 @@
 }
 
 void ScriptingRegisterContentScriptsFunction::OnContentScriptFilesValidated(
+    std::set<std::string> persistent_script_ids,
     ValidateContentScriptsResult result) {
   auto error = std::move(result.second);
   auto scripts = std::move(result.first);
@@ -882,7 +880,7 @@
   }
 
   loader->AddDynamicScripts(
-      std::move(scripts),
+      std::move(scripts), std::move(persistent_script_ids),
       base::BindOnce(
           &ScriptingRegisterContentScriptsFunction::OnContentScriptsRegistered,
           this));
@@ -922,9 +920,15 @@
   const UserScriptList& dynamic_scripts = loader->GetLoadedDynamicScripts();
 
   std::vector<api::scripting::RegisteredContentScript> script_infos;
+  std::set<std::string> persistent_script_ids =
+      loader->GetPersistentDynamicScriptIDs();
   for (const std::unique_ptr<UserScript>& script : dynamic_scripts) {
-    if (id_filter.empty() || base::Contains(id_filter, script->id()))
-      script_infos.push_back(CreateRegisteredContentScriptInfo(*script));
+    if (id_filter.empty() || base::Contains(id_filter, script->id())) {
+      auto registered_script = CreateRegisteredContentScriptInfo(*script);
+      registered_script.persist_across_sessions = std::make_unique<bool>(
+          base::Contains(persistent_script_ids, script->id()));
+      script_infos.push_back(std::move(registered_script));
+    }
   }
 
   return RespondNow(
@@ -1040,8 +1044,12 @@
 
   std::u16string parse_error;
   auto parsed_scripts = std::make_unique<UserScriptList>();
-  const int valid_schemes =
-      UserScript::ValidUserScriptSchemes(kScriptsCanExecuteEverywhere);
+  const int valid_schemes = UserScript::ValidUserScriptSchemes(
+      scripting::kScriptsCanExecuteEverywhere);
+
+  std::set<std::string> updated_script_ids_to_persist;
+  std::set<std::string> persistent_script_ids =
+      loader->GetPersistentDynamicScriptIDs();
 
   parsed_scripts->reserve(scripts.size());
   for (size_t i = 0; i < scripts.size(); ++i) {
@@ -1080,6 +1088,15 @@
     if (!user_script)
       return RespondNow(Error(base::UTF16ToASCII(parse_error)));
 
+    // Persist the updated script if the flag is specified as true, or if the
+    // original script is persisted and the flag is not specified.
+    if ((update_delta.persist_across_sessions &&
+         *update_delta.persist_across_sessions) ||
+        (!update_delta.persist_across_sessions &&
+         base::Contains(persistent_script_ids, update_delta.id))) {
+      updated_script_ids_to_persist.insert(update_delta.id);
+    }
+
     parsed_scripts->push_back(std::move(user_script));
   }
 
@@ -1094,7 +1111,7 @@
                      std::move(parsed_scripts)),
       base::BindOnce(
           &ScriptingUpdateContentScriptsFunction::OnContentScriptFilesValidated,
-          this));
+          this, std::move(updated_script_ids_to_persist)));
 
   // Balanced in `OnContentScriptFilesValidated()` or
   // `OnContentScriptsRegistered()`.
@@ -1103,6 +1120,7 @@
 }
 
 void ScriptingUpdateContentScriptsFunction::OnContentScriptFilesValidated(
+    std::set<std::string> persistent_script_ids,
     ValidateContentScriptsResult result) {
   auto error = std::move(result.second);
   auto scripts = std::move(result.first);
@@ -1133,7 +1151,7 @@
   loader->AddPendingDynamicScriptIDs(std::move(script_ids));
 
   loader->AddDynamicScripts(
-      std::move(scripts),
+      std::move(scripts), std::move(persistent_script_ids),
       base::BindOnce(
           &ScriptingUpdateContentScriptsFunction::OnContentScriptsUpdated,
           this));
diff --git a/chrome/browser/extensions/api/scripting/scripting_api.h b/chrome/browser/extensions/api/scripting/scripting_api.h
index 96141fc..093562d 100644
--- a/chrome/browser/extensions/api/scripting/scripting_api.h
+++ b/chrome/browser/extensions/api/scripting/scripting_api.h
@@ -129,7 +129,9 @@
   ~ScriptingRegisterContentScriptsFunction() override;
 
   // Called when script files have been checked.
-  void OnContentScriptFilesValidated(ValidateContentScriptsResult result);
+  void OnContentScriptFilesValidated(
+      std::set<std::string> persistent_script_ids,
+      ValidateContentScriptsResult result);
 
   // Called when content scripts have been registered.
   void OnContentScriptsRegistered(const absl::optional<std::string>& error);
@@ -192,7 +194,9 @@
   ~ScriptingUpdateContentScriptsFunction() override;
 
   // Called when script files have been checked.
-  void OnContentScriptFilesValidated(ValidateContentScriptsResult result);
+  void OnContentScriptFilesValidated(
+      std::set<std::string> persistent_script_ids,
+      ValidateContentScriptsResult result);
 
   // Called when content scripts have been updated.
   void OnContentScriptsUpdated(const absl::optional<std::string>& error);
diff --git a/chrome/browser/extensions/api/scripting/scripting_apitest.cc b/chrome/browser/extensions/api/scripting/scripting_apitest.cc
index f30de944..b567877 100644
--- a/chrome/browser/extensions/api/scripting/scripting_apitest.cc
+++ b/chrome/browser/extensions/api/scripting/scripting_apitest.cc
@@ -11,6 +11,8 @@
 #include "content/public/test/browser_test.h"
 #include "content/public/test/test_navigation_observer.h"
 #include "extensions/common/features/feature_channel.h"
+#include "extensions/test/extension_test_message_listener.h"
+#include "extensions/test/result_catcher.h"
 #include "net/dns/mock_host_resolver.h"
 #include "ui/base/window_open_disposition.h"
 #include "url/gurl.h"
@@ -103,4 +105,48 @@
   ASSERT_TRUE(RunExtensionTest("scripting/dynamic_scripts")) << message_;
 }
 
+// Base test fixture for tests spanning multiple sessions where a custom arg is
+// set before the test is run.
+class PersistentScriptingAPITest : public ScriptingAPITest {
+ public:
+  PersistentScriptingAPITest() = default;
+
+  // ScriptingAPITest override.
+  void SetUpOnMainThread() override {
+    ScriptingAPITest::SetUpOnMainThread();
+
+    // Set the test name as a custom arge before the test is run. This avoids a
+    // race condition where the extension loads (as part of browser startup) and
+    // sends a message before a message listener in C++ has been initialized.
+    SetCustomArg(testing::UnitTest::GetInstance()->current_test_info()->name());
+  }
+
+ protected:
+  // Used to wait for results from extension tests. This is initialized before
+  // the test is run which avoids a race condition where the extension is loaded
+  // (as part of startup) and finishes its tests before the ResultCatcher is
+  // created.
+  extensions::ResultCatcher result_catcher_;
+};
+
+// Tests that registered content scripts which persist across sessions behave as
+// expected. The test is run across three sessions.
+IN_PROC_BROWSER_TEST_F(PersistentScriptingAPITest,
+                       PRE_PRE_PersistentDynamicContentScripts) {
+  const extensions::Extension* extension = LoadExtension(
+      test_data_dir_.AppendASCII("scripting/persistent_dynamic_scripts"));
+  ASSERT_TRUE(extension);
+  EXPECT_TRUE(result_catcher_.GetNextResult()) << result_catcher_.message();
+}
+
+IN_PROC_BROWSER_TEST_F(PersistentScriptingAPITest,
+                       PRE_PersistentDynamicContentScripts) {
+  EXPECT_TRUE(result_catcher_.GetNextResult()) << result_catcher_.message();
+}
+
+IN_PROC_BROWSER_TEST_F(PersistentScriptingAPITest,
+                       PersistentDynamicContentScripts) {
+  EXPECT_TRUE(result_catcher_.GetNextResult()) << result_catcher_.message();
+}
+
 }  // namespace extensions
diff --git a/chrome/browser/extensions/corb_and_cors_extension_browsertest.cc b/chrome/browser/extensions/corb_and_cors_extension_browsertest.cc
index 525f637..aeb6b957 100644
--- a/chrome/browser/extensions/corb_and_cors_extension_browsertest.cc
+++ b/chrome/browser/extensions/corb_and_cors_extension_browsertest.cc
@@ -17,7 +17,6 @@
 #include "base/values.h"
 #include "build/build_config.h"
 #include "chrome/browser/apps/platform_apps/app_browsertest_util.h"
-#include "chrome/browser/extensions/api/permissions/permissions_api.h"
 #include "chrome/browser/extensions/api/tabs/tabs_api.h"
 #include "chrome/browser/extensions/chrome_content_browser_client_extensions_part.h"
 #include "chrome/browser/extensions/extension_action_runner.h"
@@ -260,7 +259,8 @@
                               "has been blocked by CORS policy")));
   }
 
-  void VerifyFetchWasBlockedByCorb(const base::HistogramTester& histograms) {
+  void VerifyFetchFromContentScriptWasBlockedByCorb(
+      const base::HistogramTester& histograms) {
     // Make sure that histograms logged in other processes (e.g. in
     // NetworkService process) get synced.
     metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
@@ -271,8 +271,9 @@
                                  CORBAction::kBlockedWithoutSniffing, 1);
   }
 
-  void VerifyFetchWasAllowedByCorb(const base::HistogramTester& histograms,
-                                   bool expecting_sniffing = false) {
+  void VerifyFetchFromContentScriptWasAllowedByCorb(
+      const base::HistogramTester& histograms,
+      bool expecting_sniffing = false) {
     // Make sure that histograms logged in other processes (e.g. in
     // NetworkService process) get synced.
     metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
@@ -319,7 +320,8 @@
       const std::string& actual_fetch_result,
       const std::string& expected_fetch_result_prefix) {
     // Verify that CORB allowed the response.
-    VerifyFetchWasAllowedByCorb(histograms, false /* expecting_sniffing */);
+    VerifyFetchFromContentScriptWasAllowedByCorb(
+        histograms, false /* expecting_sniffing */);
 
     // Verify that the response body was blocked by CORS.
     EXPECT_EQ(kCorsErrorWhenFetching, actual_fetch_result);
@@ -330,15 +332,6 @@
     return browser()->tab_strip_model()->GetActiveWebContents();
   }
 
-  const Extension* InstallExtensionWithManifest(base::StringPiece manifest) {
-    dir_.WriteManifest(manifest);
-    dir_.WriteFile(FILE_PATH_LITERAL("background_script.js"), "");
-    dir_.WriteFile(FILE_PATH_LITERAL("page.html"), "");
-
-    extension_ = LoadExtension(dir_.UnpackedPath());
-    return extension_;
-  }
-
   const Extension* InstallExtensionWithPermissionToAllUrls(
       bool enable_file_access = false) {
     const char kManifestTemplate[] = R"(
@@ -725,11 +718,10 @@
     content::ExecuteScriptAsync(active_web_contents(), kFetchInitiatingScript);
     std::string fetch_result = PopString(&queue);
 
-    // Verify that the fetch was blocked by CORS.  (CORB only applies to
-    // `no-cors` requests.)
     EXPECT_EQ(kCorsErrorWhenFetching, fetch_result);
+    VerifyFetchFromContentScriptWasAllowedByCorb(
+        histograms, false /* expecting_sniffing */);
     VerifyFetchWasBlockedByCors(console_observer);
-    VerifyFetchWasAllowedByCorb(histograms, false /* expecting_sniffing */);
   }
 }
 
@@ -781,11 +773,11 @@
     std::string fetch_result =
         FetchViaContentScript(cross_site_resource, active_web_contents());
 
-    // Verify that the fetch was blocked by CORS.  (CORB only applies to
-    // `no-cors` requests.)
+    // Verify that the fetch was blocked by CORS.
     EXPECT_EQ(kCorsErrorWhenFetching, fetch_result);
+    VerifyFetchFromContentScriptWasAllowedByCorb(
+        histograms, false /* expecting_sniffing */);
     VerifyFetchWasBlockedByCors(console_observer);
-    VerifyFetchWasAllowedByCorb(histograms, false /* expecting_sniffing */);
   }
 }
 
@@ -839,7 +831,8 @@
 
     // Verify that the fetch was blocked by CORS.
     EXPECT_EQ(kCorsErrorWhenFetching, fetch_result);
-    VerifyFetchWasAllowedByCorb(histograms, false /* expecting_sniffing */);
+    VerifyFetchFromContentScriptWasAllowedByCorb(
+        histograms, false /* expecting_sniffing */);
     VerifyFetchWasBlockedByCors(console_observer);
   }
 }
@@ -1065,7 +1058,7 @@
   // Verify that the fetch succeeded (because of the server's
   // Access-Control-Allow-Origin response header).
   EXPECT_EQ("cors-ok.txt - body\n", fetch_result);
-  VerifyFetchWasAllowedByCorb(histograms);
+  VerifyFetchFromContentScriptWasAllowedByCorb(histograms);
 }
 
 // Test that verifies that CORS blocks non-CORB-eligible fetches for targets
@@ -1100,7 +1093,8 @@
 
   // Verify that the fetch was allowed by CORB (because CORB doesn't apply to
   // CORS requests).
-  VerifyFetchWasAllowedByCorb(histograms, false /* expecting_sniffing */);
+  VerifyFetchFromContentScriptWasAllowedByCorb(histograms,
+                                               false /* expecting_sniffing */);
 }
 
 // Tests that same-origin fetches (same-origin relative to the webpage the
@@ -1129,7 +1123,8 @@
 
   // Verify that no blocking occurred.
   EXPECT_THAT(fetch_result, ::testing::StartsWith("nosniff.xml - body"));
-  VerifyFetchWasAllowedByCorb(histograms, false /* expecting_sniffing */);
+  VerifyFetchFromContentScriptWasAllowedByCorb(histograms,
+                                               false /* expecting_sniffing */);
 }
 
 // Test that responses that would have been allowed by CORB anyway are not
@@ -1345,7 +1340,7 @@
                                            "" /* expected_response_body */);
 }
 
-// Test that requests from an extension background page use relaxed CORB
+// Test that requests from an extension background page use relaxed CORS
 // processing.
 IN_PROC_BROWSER_TEST_F(CorbAndCorsExtensionBrowserTest,
                        FromBackgroundPage_NoSniffXml) {
@@ -1357,18 +1352,44 @@
   EXPECT_FALSE(IncognitoInfo::IsSplitMode(extension()));
 
   // Performs a cross-origin fetch from the background page.
-  {
-    base::HistogramTester histograms;
-    GURL cross_site_resource(
-        embedded_test_server()->GetURL("cross-site.com", "/nosniff.xml"));
-    std::string fetch_result = FetchViaBackgroundPage(cross_site_resource);
+  GURL cross_site_resource(
+      embedded_test_server()->GetURL("cross-site.com", "/nosniff.xml"));
+  std::string fetch_result = FetchViaBackgroundPage(cross_site_resource);
 
-    // Verify that CORS did *not* block the response.
-    EXPECT_EQ("nosniff.xml - body\n", fetch_result);
+  // Verify that no blocking occurred.
+  EXPECT_EQ("nosniff.xml - body\n", fetch_result);
+}
 
-    // CORB only applies to `no-cors` requests.
-    VerifyFetchWasAllowedByCorb(histograms, false /* expecting_sniffing */);
-  }
+// Test that requests from an extension background page use relaxed CORB
+// processing in `no-cors` mode.  See also https://crbug.com/1252173.
+IN_PROC_BROWSER_TEST_F(CorbAndCorsExtensionBrowserTest,
+                       FromBackgroundPage_NoSniffXml_NoCors) {
+  ASSERT_TRUE(embedded_test_server()->Start());
+  ASSERT_TRUE(InstallExtension());
+
+  // This test covers the default incognito mode (spanning mode) where there is
+  // only a single background page (i.e. no separate incognito background page).
+  EXPECT_FALSE(IncognitoInfo::IsSplitMode(extension()));
+
+  // Performs a cross-origin fetch from the background page in "no-cors" mode.
+  GURL cross_site_resource(
+      embedded_test_server()->GetURL("cross-site.com", "/nosniff.xml"));
+  base::Value request_init(base::Value::Type::DICTIONARY);
+  request_init.SetStringPath("mode", "no-cors");
+  std::string script =
+      CreateFetchScript(cross_site_resource, std::move(request_init));
+  content::WebContents* background_web_contents =
+      ProcessManager::Get(browser()->profile())
+          ->GetBackgroundHostForExtension(extension()->id())
+          ->host_contents();
+  content::DOMMessageQueue message_queue;
+  content::ExecuteScriptAsync(background_web_contents, script);
+  std::string fetch_result = PopString(&message_queue);
+
+  // Verify that no blocking occurred (this is a bit unusual, as "no-cors"
+  // responses are normally "opaque" - their body is normally not exposed to
+  // Javascript).  See also https://crbug.com/1252173.
+  EXPECT_EQ("nosniff.xml - body\n", fetch_result);
 }
 
 // Test that requests from an extension background page use relaxed CORB
@@ -1439,148 +1460,6 @@
   }
 }
 
-// Test that CORB+CORS are enforced for extensions with no permissions to
-// http/https origins.
-IN_PROC_BROWSER_TEST_F(CorbAndCorsExtensionBrowserTest,
-                       ExtensionWithNoHttpPermissions) {
-  ASSERT_TRUE(embedded_test_server()->Start());
-
-  // "permission" entry in the manifest below mimics the PDF extension which
-  // has no permissions to http/https origins (and therefore doesn't care
-  // about relaxed CORB and/or CORS).
-  const char kManifest[] = R"(
-      {
-        "name": "CrossOriginReadBlockingTest - Extension",
-        "version": "1.0",
-        "manifest_version": 2,
-        "permissions": [ "contentSettings" ],
-        "background": {"scripts": ["background_script.js"]}
-      } )";
-  ASSERT_TRUE(InstallExtensionWithManifest(kManifest));
-
-  // Perform a cross-origin CORS fetch from the background page.
-  {
-    base::HistogramTester histograms;
-    GURL cross_site_resource1(
-        embedded_test_server()->GetURL("cross-site.com", "/nosniff.empty"));
-    std::string fetch_result = FetchViaBackgroundPage(cross_site_resource1);
-
-    // Verify that the fetch was blocked by CORS.
-    //
-    // This behavior verification is a bit important, but here it mostly tests
-    // the test setup, rather than the behavior this test was created for.
-    EXPECT_EQ(kCorsErrorWhenFetching, fetch_result);
-
-    // CORB only applies to `no-cors` requests.
-    VerifyFetchWasAllowedByCorb(histograms, false /* expecting_sniffing */);
-  }
-
-  // Perform a cross-origin `no-cors` request from the background page.
-  {
-    // Use a slightly different URL to avoid having to think what effect the
-    // network cache might have on test results.
-    GURL cross_site_resource2(
-        embedded_test_server()->GetURL("cross-site.com", "/nosniff.xml"));
-
-    base::Value request_init(base::Value::Type::DICTIONARY);
-    request_init.SetStringPath("method", "GET");
-    request_init.SetStringPath("mode", "no-cors");
-
-    content::WebContents* background_web_contents =
-        ProcessManager::Get(browser()->profile())
-            ->GetBackgroundHostForExtension(extension()->id())
-            ->host_contents();
-
-    base::HistogramTester histograms;
-    content::DOMMessageQueue queue;
-    content::ExecuteScriptAsync(
-        background_web_contents,
-        CreateFetchScript(cross_site_resource2, std::move(request_init)));
-    std::string fetch_result = PopString(&queue);
-
-    // Verify that the fetch was blocked by CORB.
-    //
-    // This is the main verification in the test.  This verifies that the
-    // extension background page uses a URLLoaderFactory created with
-    // URLLoaderFactoryParams::is_corb_enabled set to the default, secure value
-    // of `true`.
-    EXPECT_EQ("", fetch_result);  // `no-cors` = empty, opaque response.
-    VerifyFetchWasBlockedByCorb(histograms);
-  }
-}
-
-// Test that CORB+CORS are enforced for extensions with optional permissions to
-// http/https origins.
-IN_PROC_BROWSER_TEST_F(CorbAndCorsExtensionBrowserTest,
-                       ExtensionWithOptionalHttpPermissions) {
-  ASSERT_TRUE(embedded_test_server()->Start());
-
-  // There are only *optional* HTTP permissions declared in the manifest below -
-  // they will be granted later, at runtime (but not at the extension
-  // installation time).
-  const char kManifest[] = R"(
-      {
-        "name": "CrossOriginReadBlockingTest - Extension",
-        "version": "1.0",
-        "manifest_version": 2,
-        "optional_permissions": [ "<all_urls>", "http://example.com/" ],
-        "background": {"scripts": ["background_script.js"]}
-      } )";
-  ASSERT_TRUE(InstallExtensionWithManifest(kManifest));
-
-  // Navigate a tab to the extension origin.
-  GURL extension_resource = GetExtensionResource("page.html");
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), extension_resource));
-  content::RenderFrameHost* test_frame =
-      browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame();
-  ASSERT_EQ(GetExtensionOrigin(), test_frame->GetLastCommittedOrigin());
-
-  // Perform a cross-origin fetch from an extension frame and verify that it got
-  // blocked by CORS.
-  GURL cross_site_url(
-      embedded_test_server()->GetURL("cross-site.com", "/nosniff.xml"));
-  url::Origin cross_site_origin = url::Origin::Create(cross_site_url);
-  {
-    base::HistogramTester histograms;
-    std::string fetch_result = FetchViaFrame(cross_site_url, test_frame);
-
-    // Verify that the fetch was blocked by CORS.  (CORB only applies to
-    // `no-cors` requests.)
-    EXPECT_EQ(kCorsErrorWhenFetching, fetch_result);
-    VerifyFetchWasAllowedByCorb(histograms, false /* expecting_sniffing */);
-  }
-
-  // Grant the optional permissions to the extension.
-  {
-    PermissionsRequestFunction::SetAutoConfirmForTests(true);
-    const char kPermissionGrantingScriptTemplate[] = R"(
-        chrome.permissions.request(
-            { origins: [$1] },
-            granted => { domAutomationController.send(granted); });
-    )";
-    bool has_permission_been_granted = false;
-    std::string script = content::JsReplace(kPermissionGrantingScriptTemplate,
-                                            cross_site_origin.GetURL());
-    ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
-        test_frame, script, &has_permission_been_granted));
-    ASSERT_TRUE(has_permission_been_granted);
-    PermissionsRequestFunction::SetAutoConfirmForTests(false);
-  }
-
-  // Performs a cross-origin fetch from the background page and verify that it
-  // didn't get blocked by CORS.
-  {
-    base::HistogramTester histograms;
-    std::string fetch_result = FetchViaFrame(cross_site_url, test_frame);
-
-    // Verify that CORS did *not* block the response.
-    EXPECT_EQ("nosniff.xml - body\n", fetch_result);
-
-    // CORB only applies to `no-cors` requests.
-    VerifyFetchWasAllowedByCorb(histograms, false /* expecting_sniffing */);
-  }
-}
-
 // Test that requests from an extension page hosted in a foreground tab use
 // relaxed CORB processing.
 IN_PROC_BROWSER_TEST_F(CorbAndCorsExtensionBrowserTest,
@@ -2078,12 +1957,12 @@
       } )";
   TestExtensionDir dir;
   dir.WriteManifest(kManifest);
-  const char kBackgroundScript[] = R"(
+  const char kBackgroungScript[] = R"(
       chrome.app.runtime.onLaunched.addListener(function() {
         chrome.app.window.create('page.html', {}, function () {});
       });
   )";
-  dir.WriteFile(FILE_PATH_LITERAL("background_script.js"), kBackgroundScript);
+  dir.WriteFile(FILE_PATH_LITERAL("background_script.js"), kBackgroungScript);
   const char kPage[] = R"(
       <div id="webview-tag-container"></div>
   )";
diff --git a/chrome/browser/extensions/extension_system_impl.cc b/chrome/browser/extensions/extension_system_impl.cc
index d1833cb9..6c856bc 100644
--- a/chrome/browser/extensions/extension_system_impl.cc
+++ b/chrome/browser/extensions/extension_system_impl.cc
@@ -109,15 +109,18 @@
   store_factory_ = base::MakeRefCounted<value_store::ValueStoreFactoryImpl>(
       profile_->GetPath());
 
-  // Two state stores. The latter, which contains declarative rules, must be
-  // loaded immediately so that the rules are ready before we issue network
-  // requests.
+  // Three state stores. Two stores, which contain declarative rules and dynamic
+  // user scripts respectively, must be loaded immediately so that the
+  // rules/scripts are ready before we issue network requests.
   state_store_ = std::make_unique<StateStore>(
       profile_, store_factory_, StateStore::BackendType::STATE, true);
 
   rules_store_ = std::make_unique<StateStore>(
       profile_, store_factory_, StateStore::BackendType::RULES, false);
 
+  dynamic_user_scripts_store_ = std::make_unique<StateStore>(
+      profile_, store_factory_, StateStore::BackendType::SCRIPTS, false);
+
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   // We can not perform check for Signin Profile here, as it would result in
   // recursive call upon creation of Signin Profile, so we will create
@@ -315,6 +318,10 @@
   return rules_store_.get();
 }
 
+StateStore* ExtensionSystemImpl::Shared::dynamic_user_scripts_store() {
+  return dynamic_user_scripts_store_.get();
+}
+
 scoped_refptr<value_store::ValueStoreFactory>
 ExtensionSystemImpl::Shared::store_factory() const {
   return store_factory_;
@@ -412,6 +419,10 @@
   return shared_->rules_store();
 }
 
+StateStore* ExtensionSystemImpl::dynamic_user_scripts_store() {
+  return shared_->dynamic_user_scripts_store();
+}
+
 scoped_refptr<value_store::ValueStoreFactory>
 ExtensionSystemImpl::store_factory() {
   return shared_->store_factory();
diff --git a/chrome/browser/extensions/extension_system_impl.h b/chrome/browser/extensions/extension_system_impl.h
index 641fe1b2..d68b24e3 100644
--- a/chrome/browser/extensions/extension_system_impl.h
+++ b/chrome/browser/extensions/extension_system_impl.h
@@ -64,6 +64,7 @@
   UserScriptManager* user_script_manager() override;        // shared
   StateStore* state_store() override;                              // shared
   StateStore* rules_store() override;                              // shared
+  StateStore* dynamic_user_scripts_store() override;               // shared
   scoped_refptr<value_store::ValueStoreFactory> store_factory()
       override;                                                    // shared
   InfoMap* info_map() override;                                    // shared
@@ -116,6 +117,7 @@
 
     StateStore* state_store();
     StateStore* rules_store();
+    StateStore* dynamic_user_scripts_store();
     scoped_refptr<value_store::ValueStoreFactory> store_factory() const;
     ExtensionService* extension_service();
     RuntimeData* runtime_data();
@@ -136,6 +138,7 @@
 
     std::unique_ptr<StateStore> state_store_;
     std::unique_ptr<StateStore> rules_store_;
+    std::unique_ptr<StateStore> dynamic_user_scripts_store_;
     scoped_refptr<value_store::ValueStoreFactoryImpl> store_factory_;
     std::unique_ptr<NavigationObserver> navigation_observer_;
     std::unique_ptr<ServiceWorkerManager> service_worker_manager_;
diff --git a/chrome/browser/extensions/extension_user_script_loader_unittest.cc b/chrome/browser/extensions/extension_user_script_loader_unittest.cc
index 7f5f0f4..5361da5a 100644
--- a/chrome/browser/extensions/extension_user_script_loader_unittest.cc
+++ b/chrome/browser/extensions/extension_user_script_loader_unittest.cc
@@ -66,6 +66,7 @@
   TestingProfile profile;
   scoped_refptr<const Extension> extension(ExtensionBuilder("Test").Build());
   ExtensionUserScriptLoader loader(&profile, *extension,
+                                   /*state_store=*/nullptr,
                                    /*listen_for_extension_system_loaded=*/true,
                                    /*content_verifier=*/nullptr);
   base::RunLoop run_loop;
@@ -86,6 +87,7 @@
   TestingProfile profile;
   scoped_refptr<const Extension> extension(ExtensionBuilder("Test").Build());
   ExtensionUserScriptLoader loader(&profile, *extension,
+                                   /*state_store=*/nullptr,
                                    /*listen_for_extension_system_loaded=*/true,
                                    /*content_verifier=*/nullptr);
 
@@ -111,6 +113,7 @@
   TestingProfile profile;
   scoped_refptr<const Extension> extension(ExtensionBuilder("Test").Build());
   ExtensionUserScriptLoader loader(&profile, *extension,
+                                   /*state_store=*/nullptr,
                                    /*listen_for_extension_system_loaded=*/true,
                                    /*content_verifier=*/nullptr);
   base::RunLoop run_loop;
@@ -283,6 +286,7 @@
   TestingProfile profile;
   scoped_refptr<const Extension> extension(ExtensionBuilder("Test").Build());
   ExtensionUserScriptLoader loader(&profile, *extension,
+                                   /*state_store=*/nullptr,
                                    /*listen_for_extension_system_loaded=*/true,
                                    /*content_verifier=*/nullptr);
   user_scripts = loader.LoadScriptsForTest(std::move(user_scripts));
@@ -307,6 +311,7 @@
   TestingProfile profile;
   scoped_refptr<const Extension> extension(ExtensionBuilder("Test").Build());
   ExtensionUserScriptLoader loader(&profile, *extension,
+                                   /*state_store=*/nullptr,
                                    /*listen_for_extension_system_loaded=*/true,
                                    /*content_verifier=*/nullptr);
   user_scripts = loader.LoadScriptsForTest(std::move(user_scripts));
@@ -332,6 +337,7 @@
   TestingProfile profile;
   scoped_refptr<const Extension> extension(ExtensionBuilder("Test").Build());
   ExtensionUserScriptLoader loader(&profile, *extension,
+                                   /*state_store=*/nullptr,
                                    /*listen_for_extension_system_loaded=*/true,
                                    /*content_verifier=*/nullptr);
   user_scripts = loader.LoadScriptsForTest(std::move(user_scripts));
diff --git a/chrome/browser/extensions/extension_view_host.cc b/chrome/browser/extensions/extension_view_host.cc
index 0307f5c..bc44eb1 100644
--- a/chrome/browser/extensions/extension_view_host.cc
+++ b/chrome/browser/extensions/extension_view_host.cc
@@ -225,6 +225,12 @@
                                    params);
 }
 
+std::unique_ptr<content::EyeDropper> ExtensionViewHost::OpenEyeDropper(
+    content::RenderFrameHost* frame,
+    content::EyeDropperListener* listener) {
+  return browser_ ? browser_->OpenEyeDropper(frame, listener) : nullptr;
+}
+
 void ExtensionViewHost::ResizeDueToAutoResize(content::WebContents* source,
                                               const gfx::Size& new_size) {
   view_->ResizeDueToAutoResize(source, new_size);
diff --git a/chrome/browser/extensions/extension_view_host.h b/chrome/browser/extensions/extension_view_host.h
index e3554c5..b25dbf4 100644
--- a/chrome/browser/extensions/extension_view_host.h
+++ b/chrome/browser/extensions/extension_view_host.h
@@ -85,6 +85,9 @@
   void RunFileChooser(content::RenderFrameHost* render_frame_host,
                       scoped_refptr<content::FileSelectListener> listener,
                       const blink::mojom::FileChooserParams& params) override;
+  std::unique_ptr<content::EyeDropper> OpenEyeDropper(
+      content::RenderFrameHost* frame,
+      content::EyeDropperListener* listener) override;
   void ResizeDueToAutoResize(content::WebContents* source,
                              const gfx::Size& new_size) override;
 
diff --git a/chrome/browser/extensions/test_extension_system.cc b/chrome/browser/extensions/test_extension_system.cc
index 721af8f..40c3c59 100644
--- a/chrome/browser/extensions/test_extension_system.cc
+++ b/chrome/browser/extensions/test_extension_system.cc
@@ -128,6 +128,10 @@
   return state_store_.get();
 }
 
+StateStore* TestExtensionSystem::dynamic_user_scripts_store() {
+  return state_store_.get();
+}
+
 scoped_refptr<value_store::ValueStoreFactory>
 TestExtensionSystem::store_factory() {
   return store_factory_;
diff --git a/chrome/browser/extensions/test_extension_system.h b/chrome/browser/extensions/test_extension_system.h
index 9e87680..b16e32c 100644
--- a/chrome/browser/extensions/test_extension_system.h
+++ b/chrome/browser/extensions/test_extension_system.h
@@ -66,6 +66,7 @@
   UserScriptManager* user_script_manager() override;
   StateStore* state_store() override;
   StateStore* rules_store() override;
+  StateStore* dynamic_user_scripts_store() override;
   scoped_refptr<value_store::ValueStoreFactory> store_factory() override;
   value_store::TestingValueStore* value_store();
   InfoMap* info_map() override;
diff --git a/chrome/browser/extensions/user_script_listener.cc b/chrome/browser/extensions/user_script_listener.cc
index e5432a8..44acff7 100644
--- a/chrome/browser/extensions/user_script_listener.cc
+++ b/chrome/browser/extensions/user_script_listener.cc
@@ -193,6 +193,9 @@
 
 void UserScriptListener::CollectURLPatterns(const Extension* extension,
                                             URLPatterns* patterns) {
+  // TODO(crbug.com/1239040): Retrieve the appropriate URL patterns to withhold
+  // requests which match an extension's set of persistent dynamic scripts on
+  // startup.
   for (const std::unique_ptr<UserScript>& script :
        ContentScriptsInfo::GetContentScripts(extension)) {
     patterns->insert(patterns->end(), script->url_patterns().begin(),
diff --git a/chrome/browser/history_clusters/history_clusters_metrics_browsertest.cc b/chrome/browser/history_clusters/history_clusters_metrics_browsertest.cc
index 099e9d91..0c0c5ed 100644
--- a/chrome/browser/history_clusters/history_clusters_metrics_browsertest.cc
+++ b/chrome/browser/history_clusters/history_clusters_metrics_browsertest.cc
@@ -153,4 +153,25 @@
       HistoryClustersFinalState::kCloseTab, 0, 1);
 }
 
+IN_PROC_BROWSER_TEST_F(HistoryClustersMetricsBrowserTest, IndirectNavigation) {
+  ukm::TestAutoSetUkmRecorder ukm_recorder;
+
+  EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(),
+                                           GURL(chrome::kChromeUIHistoryURL)));
+  EXPECT_TRUE(content::ExecJs(
+      browser()->tab_strip_model()->GetActiveWebContents(),
+      "document.querySelector('#history-app').shadowRoot.querySelector('#"
+      "content-side-bar').shadowRoot.querySelector('#historyClusters').click()",
+      content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, 1 /* world_id */));
+
+  EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL("https://foo.com")));
+  auto entries =
+      ukm_recorder.GetEntriesByName(ukm::builders::HistoryClusters::kEntryName);
+  EXPECT_EQ(1u, entries.size());
+  auto* ukm_entry = entries[0];
+  ValidateHistoryClustersUKMEntry(
+      ukm_entry, HistoryClustersInitialState::kIndirectNavigation,
+      HistoryClustersFinalState::kCloseTab, 0, 0);
+}
+
 }  // namespace history_clusters
diff --git a/chrome/browser/history_clusters/history_clusters_metrics_logger.h b/chrome/browser/history_clusters/history_clusters_metrics_logger.h
index 4d83580..318233d 100644
--- a/chrome/browser/history_clusters/history_clusters_metrics_logger.h
+++ b/chrome/browser/history_clusters/history_clusters_metrics_logger.h
@@ -14,15 +14,18 @@
 // The initial state that describes how an interaction with the HistoryClusters
 // UI was started.
 //
-// Keep in sync with HistoryClustersInitialState in enums.xml.
+// Keep in sync with HistoryClustersInitialState in
+// tools/metrics/histograms/enums.xml.
 enum class HistoryClustersInitialState {
   kUnknown = 0,
   // The HistoryClusters UI was opened via direct URL, i.e., not opened via any
   // other surface/path such as an omnibox action or other UI surface.
   kDirectNavigation = 1,
-
+  // The HistoryClusters UI was opened indirectly; e.g., using the link the
+  // chrome://history sidebar.
+  kIndirectNavigation = 2,
   // Add new values above this line.
-  kMax = kDirectNavigation,
+  kMax = kIndirectNavigation,
 };
 
 // The final state, or outcome, of an interaction on the HistoryClusters UI.
diff --git a/chrome/browser/history_clusters/history_clusters_tab_helper.cc b/chrome/browser/history_clusters/history_clusters_tab_helper.cc
index 5be5db6a..c11bff7 100644
--- a/chrome/browser/history_clusters/history_clusters_tab_helper.cc
+++ b/chrome/browser/history_clusters/history_clusters_tab_helper.cc
@@ -310,39 +310,38 @@
 
 void HistoryClustersTabHelper::DidFinishNavigation(
     content::NavigationHandle* navigation_handle) {
-  // Will detect when the history clusters page was navigated to directly (e.g.,
-  // through the omnibox, by page refresh, or by page back/forward), as opposed
-  // to indirectly (e.g. through the side bar on the history page).
-  // And will update this page's associated `HistoryClustersMetricsLogger`.
-  // TODO(manukh): Indirect navigations currently don't log UKM and UMA metrics
-  //  but they should.
+  // Will detect when the history clusters page was navigated to, either
+  // directly (e.g., through the omnibox, by page refresh, or by page
+  // back/forward), or indirectly (e.g. through the side bar on the history
+  // page). And will update this page's associated
+  // `HistoryClustersMetricsLogger`.
 
   if (!navigation_handle->IsInPrimaryMainFrame()) {
     return;
   }
-  if (navigation_handle->IsSameDocument()) {
-    return;
-  }
 
   if (!IsHistoryPage(navigation_handle->GetURL(),
                      GURL(chrome::kChromeUIHistoryClustersURL))) {
     return;
   }
+
+  auto* logger =
+      history_clusters::HistoryClustersMetricsLogger::GetOrCreateForPage(
+          navigation_handle->GetWebContents()->GetPrimaryPage());
+  logger->set_navigation_id(navigation_handle->GetNavigationId());
+
   // If the transition type is typed (meaning directly entered into the
   // address bar), PAGE_TRANSITION_TYPED, or is partially typed and selected
   // from the omnibox history, which results in PAGE_TRANSITION_RELOADS, this
   // usage of the history clusters UI is considered a "direct" navigation.
-  if (PageTransitionCoreTypeIs(navigation_handle->GetPageTransition(),
-                               ui::PAGE_TRANSITION_TYPED) ||
+  auto initial_state =
       PageTransitionCoreTypeIs(navigation_handle->GetPageTransition(),
-                               ui::PAGE_TRANSITION_RELOAD)) {
-    auto* logger =
-        history_clusters::HistoryClustersMetricsLogger::GetOrCreateForPage(
-            navigation_handle->GetWebContents()->GetPrimaryPage());
-    logger->set_navigation_id(navigation_handle->GetNavigationId());
-    logger->set_initial_state(
-        history_clusters::HistoryClustersInitialState::kDirectNavigation);
-  }
+                               ui::PAGE_TRANSITION_TYPED) ||
+              PageTransitionCoreTypeIs(navigation_handle->GetPageTransition(),
+                                       ui::PAGE_TRANSITION_RELOAD)
+          ? history_clusters::HistoryClustersInitialState::kDirectNavigation
+          : history_clusters::HistoryClustersInitialState::kIndirectNavigation;
+  logger->set_initial_state(initial_state);
 }
 
 void HistoryClustersTabHelper::DidOpenRequestedURL(
diff --git a/chrome/browser/image_editor/screenshot_flow.cc b/chrome/browser/image_editor/screenshot_flow.cc
index d1579ed..551e81e 100644
--- a/chrome/browser/image_editor/screenshot_flow.cc
+++ b/chrome/browser/image_editor/screenshot_flow.cc
@@ -199,6 +199,7 @@
   switch (event->type()) {
     case ui::ET_MOUSE_MOVED:
       SetCursor(ui::mojom::CursorType::kCross);
+      event->SetHandled();
       break;
     case ui::ET_MOUSE_PRESSED:
       if (event->IsLeftMouseButton()) {
diff --git a/chrome/browser/new_tab_page/modules/photos/photos.mojom b/chrome/browser/new_tab_page/modules/photos/photos.mojom
index 9eb6ab4..83feee96 100644
--- a/chrome/browser/new_tab_page/modules/photos/photos.mojom
+++ b/chrome/browser/new_tab_page/modules/photos/photos.mojom
@@ -26,4 +26,9 @@
   DismissModule();
   // Restores the module immediately.
   RestoreModule();
+  // Returns whether to show opt-in surface in the module.
+  ShouldShowOptInScreen() => (bool show_opt_in_screen);
+  // Stores in profile prefs whether the user has opt-in
+  // see the module content.
+  OnUserOptIn(bool accept);
 };
diff --git a/chrome/browser/new_tab_page/modules/photos/photos_handler.cc b/chrome/browser/new_tab_page/modules/photos/photos_handler.cc
index 9c48a53..423a692 100644
--- a/chrome/browser/new_tab_page/modules/photos/photos_handler.cc
+++ b/chrome/browser/new_tab_page/modules/photos/photos_handler.cc
@@ -26,3 +26,13 @@
 void PhotosHandler::RestoreModule() {
   PhotosServiceFactory::GetForProfile(profile_)->RestoreModule();
 }
+
+void PhotosHandler::ShouldShowOptInScreen(
+    ShouldShowOptInScreenCallback callback) {
+  std::move(callback).Run(
+      PhotosServiceFactory::GetForProfile(profile_)->ShouldShowOptInScreen());
+}
+
+void PhotosHandler::OnUserOptIn(bool accept) {
+  PhotosServiceFactory::GetForProfile(profile_)->OnUserOptIn(accept);
+}
diff --git a/chrome/browser/new_tab_page/modules/photos/photos_handler.h b/chrome/browser/new_tab_page/modules/photos/photos_handler.h
index 7166e65c..d7726103 100644
--- a/chrome/browser/new_tab_page/modules/photos/photos_handler.h
+++ b/chrome/browser/new_tab_page/modules/photos/photos_handler.h
@@ -22,6 +22,8 @@
   void GetMemories(GetMemoriesCallback callback) override;
   void DismissModule() override;
   void RestoreModule() override;
+  void ShouldShowOptInScreen(ShouldShowOptInScreenCallback callback) override;
+  void OnUserOptIn(bool accept) override;
 
  private:
   mojo::Receiver<photos::mojom::PhotosHandler> handler_;
diff --git a/chrome/browser/new_tab_page/modules/photos/photos_service.cc b/chrome/browser/new_tab_page/modules/photos/photos_service.cc
index 19b0a67..0e659f3 100644
--- a/chrome/browser/new_tab_page/modules/photos/photos_service.cc
+++ b/chrome/browser/new_tab_page/modules/photos/photos_service.cc
@@ -67,6 +67,8 @@
 // static
 const char PhotosService::kLastDismissedTimePrefName[] =
     "NewTabPage.Photos.LastDimissedTime";
+const char PhotosService::kOptInAcknowledgedPrefName[] =
+    "NewTabPage.Photos.OptInAcknowledged";
 
 // static
 const base::TimeDelta PhotosService::kDismissDuration =
@@ -85,6 +87,7 @@
 // static
 void PhotosService::RegisterProfilePrefs(PrefRegistrySimple* registry) {
   registry->RegisterTimePref(kLastDismissedTimePrefName, base::Time());
+  registry->RegisterBooleanPref(kOptInAcknowledgedPrefName, false);
 }
 
 void PhotosService::GetMemories(GetMemoriesCallback callback) {
@@ -124,6 +127,14 @@
   pref_service_->SetTime(kLastDismissedTimePrefName, base::Time());
 }
 
+bool PhotosService::ShouldShowOptInScreen() {
+  return !pref_service_->GetBoolean(kOptInAcknowledgedPrefName);
+}
+
+void PhotosService::OnUserOptIn(bool accept) {
+  pref_service_->SetBoolean(kOptInAcknowledgedPrefName, accept);
+}
+
 void PhotosService::OnTokenReceived(GoogleServiceAuthError error,
                                     signin::AccessTokenInfo token_info) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/chrome/browser/new_tab_page/modules/photos/photos_service.h b/chrome/browser/new_tab_page/modules/photos/photos_service.h
index a8bb30f..e447944 100644
--- a/chrome/browser/new_tab_page/modules/photos/photos_service.h
+++ b/chrome/browser/new_tab_page/modules/photos/photos_service.h
@@ -29,6 +29,7 @@
 class PhotosService : public KeyedService {
  public:
   static const char kLastDismissedTimePrefName[];
+  static const char kOptInAcknowledgedPrefName[];
   static const base::TimeDelta kDismissDuration;
 
   PhotosService(const PhotosService&) = delete;
@@ -47,6 +48,10 @@
   void DismissModule();
   // Makes the service return data again even if dimiss time is not yet over.
   void RestoreModule();
+  // Returns whether to show opt-in surface in the module.
+  bool ShouldShowOptInScreen();
+  // Stores whether the user has opt-in to see the module content.
+  void OnUserOptIn(bool accept);
 
  private:
   void OnTokenReceived(GoogleServiceAuthError error,
diff --git a/chrome/browser/new_tab_page/modules/photos/photos_service_unittest.cc b/chrome/browser/new_tab_page/modules/photos/photos_service_unittest.cc
index 000f213..448f174a 100644
--- a/chrome/browser/new_tab_page/modules/photos/photos_service_unittest.cc
+++ b/chrome/browser/new_tab_page/modules/photos/photos_service_unittest.cc
@@ -329,3 +329,17 @@
   EXPECT_EQ(base::Time(),
             prefs_.GetTime(PhotosService::kLastDismissedTimePrefName));
 }
+
+TEST_F(PhotosServiceTest, OptInShown) {
+  EXPECT_TRUE(service_->ShouldShowOptInScreen());
+
+  // If user does not accept opt-in, we should keep showing screen.
+  service_->OnUserOptIn(false);
+  EXPECT_TRUE(service_->ShouldShowOptInScreen());
+  EXPECT_FALSE(prefs_.GetBoolean(PhotosService::kOptInAcknowledgedPrefName));
+
+  // If user accept opt-in, we should stop showing screen.
+  service_->OnUserOptIn(true);
+  EXPECT_FALSE(service_->ShouldShowOptInScreen());
+  EXPECT_TRUE(prefs_.GetBoolean(PhotosService::kOptInAcknowledgedPrefName));
+}
diff --git a/chrome/browser/optimization_guide/prediction/prediction_model_download_manager.cc b/chrome/browser/optimization_guide/prediction/prediction_model_download_manager.cc
index 2ea498025..d65c49e 100644
--- a/chrome/browser/optimization_guide/prediction/prediction_model_download_manager.cc
+++ b/chrome/browser/optimization_guide/prediction/prediction_model_download_manager.cc
@@ -111,6 +111,9 @@
                           ui_weak_ptr_factory_.GetWeakPtr());
   download_params.traffic_annotation = net::MutableNetworkTrafficAnnotationTag(
       kOptimizationGuidePredictionModelsTrafficAnnotation);
+  // The downloaded models are all Google-generated, so bypass the safety
+  // checks.
+  download_params.request_params.require_safety_checks = false;
   download_params.request_params.url = download_url;
   download_params.request_params.method = "GET";
   download_params.request_params.request_headers.SetHeader(kGoogApiKey,
diff --git a/chrome/browser/optimization_guide/prediction/prediction_model_download_manager_unittest.cc b/chrome/browser/optimization_guide/prediction/prediction_model_download_manager_unittest.cc
index fd317487..900ca8c3 100644
--- a/chrome/browser/optimization_guide/prediction/prediction_model_download_manager_unittest.cc
+++ b/chrome/browser/optimization_guide/prediction/prediction_model_download_manager_unittest.cc
@@ -276,6 +276,7 @@
   EXPECT_EQ(download_params.request_params.method, "GET");
   EXPECT_TRUE(download_params.request_params.request_headers.HasHeader(
       "X-Goog-Api-Key"));
+  EXPECT_FALSE(download_params.request_params.require_safety_checks);
   EXPECT_EQ(download_params.scheduling_params.priority,
             download::SchedulingParams::Priority::NORMAL);
   EXPECT_EQ(
@@ -316,6 +317,7 @@
   EXPECT_EQ(download_params.request_params.method, "GET");
   EXPECT_TRUE(download_params.request_params.request_headers.HasHeader(
       "X-Goog-Api-Key"));
+  EXPECT_FALSE(download_params.request_params.require_safety_checks);
   EXPECT_EQ(download_params.scheduling_params.priority,
             download::SchedulingParams::Priority::HIGH);
   EXPECT_EQ(
diff --git a/chrome/browser/page_load_metrics/observers/core/amp_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/core/amp_page_load_metrics_observer.cc
index 6bc1ff2..5eb7fa7a 100644
--- a/chrome/browser/page_load_metrics/observers/core/amp_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/core/amp_page_load_metrics_observer.cc
@@ -528,17 +528,6 @@
   builder.Record(ukm::UkmRecorder::Get());
 }
 
-static constexpr int ViewportStatusToInt(blink::mojom::ViewportStatus status) {
-  switch (status) {
-    case blink::mojom::ViewportStatus::kYes:
-      return 1;
-    case blink::mojom::ViewportStatus::kNo:
-      return 0;
-    case blink::mojom::ViewportStatus::kUnknown:
-      return -1;
-  }
-}
-
 void AMPPageLoadMetricsObserver::RecordMobileFriendliness(
     ukm::builders::AmpPageLoad& builder) {
   auto it = amp_subframe_info_.find(current_main_frame_nav_info_->subframe_rfh);
@@ -559,9 +548,8 @@
     return;
 
   builder.SetSubFrame_MobileFriendliness_ViewportDeviceWidth(
-      ViewportStatusToInt(mf.viewport_device_width));
-  builder.SetSubFrame_MobileFriendliness_AllowUserZoom(
-      ViewportStatusToInt(mf.allow_user_zoom));
+      mf.viewport_device_width);
+  builder.SetSubFrame_MobileFriendliness_AllowUserZoom(mf.allow_user_zoom);
   builder.SetSubFrame_MobileFriendliness_SmallTextRatio(mf.small_text_ratio);
   builder.SetSubFrame_MobileFriendliness_ViewportInitialScaleX10(
       page_load_metrics::GetBucketedViewportInitialScale(mf));
diff --git a/chrome/browser/page_load_metrics/observers/core/ukm_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/core/ukm_page_load_metrics_observer.cc
index 4a4b1260..3cc071e 100644
--- a/chrome/browser/page_load_metrics/observers/core/ukm_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/core/ukm_page_load_metrics_observer.cc
@@ -1166,10 +1166,8 @@
   ukm::builders::MobileFriendliness builder(GetDelegate().GetPageUkmSourceId());
   const blink::MobileFriendliness& mf = GetDelegate().GetMobileFriendliness();
 
-  builder.SetViewportDeviceWidth(mf.viewport_device_width ==
-                                 blink::mojom::ViewportStatus::kYes);
-  builder.SetAllowUserZoom(mf.allow_user_zoom ==
-                           blink::mojom::ViewportStatus::kYes);
+  builder.SetViewportDeviceWidth(mf.viewport_device_width);
+  builder.SetAllowUserZoom(mf.allow_user_zoom);
 
   builder.SetSmallTextRatio(mf.small_text_ratio);
   builder.SetViewportInitialScaleX10(
diff --git a/chrome/browser/page_load_metrics/observers/core/ukm_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/core/ukm_page_load_metrics_observer_unittest.cc
index a19a983..ec2bc44 100644
--- a/chrome/browser/page_load_metrics/observers/core/ukm_page_load_metrics_observer_unittest.cc
+++ b/chrome/browser/page_load_metrics/observers/core/ukm_page_load_metrics_observer_unittest.cc
@@ -1145,10 +1145,10 @@
 TEST_F(UkmPageLoadMetricsObserverTest, MobileFriendliness) {
   NavigateAndCommit(GURL(kTestUrl1));
   blink::MobileFriendliness mobile_friendliness;
-  mobile_friendliness.viewport_device_width = blink::mojom::ViewportStatus::kNo;
+  mobile_friendliness.viewport_device_width = false;
   mobile_friendliness.viewport_hardcoded_width = 533;
   mobile_friendliness.viewport_initial_scale_x10 = 10;
-  mobile_friendliness.allow_user_zoom = blink::mojom::ViewportStatus::kYes;
+  mobile_friendliness.allow_user_zoom = true;
   mobile_friendliness.small_text_ratio = 2;
   const int expected_viewport_hardcoded_width = 520;
   const int expected_viewport_initial_scale = 10;
diff --git a/chrome/browser/policy/login_policy_test_base_browsertest.cc b/chrome/browser/policy/login_policy_test_base_browsertest.cc
index 7cc69dd..1a542ee3 100644
--- a/chrome/browser/policy/login_policy_test_base_browsertest.cc
+++ b/chrome/browser/policy/login_policy_test_base_browsertest.cc
@@ -127,7 +127,7 @@
   // should be "xkb:fr::fra", enabling "xkb:us::eng" should not be possible,
   // enabling "xkb:de::ger" should be possible.
   EXPECT_EQ(2U, ime_state->GetAllowedInputMethods().size());
-  EXPECT_EQ(2U, ime_state->GetActiveInputMethods()->size());
+  EXPECT_EQ(2U, ime_state->GetEnabledInputMethods()->size());
   EXPECT_EQ(input_methods[1], ime_state->GetCurrentInputMethod().id());
   EXPECT_FALSE(ime_state->EnableInputMethod(input_methods[0]));
   EXPECT_TRUE(ime_state->EnableInputMethod(input_methods[2]));
diff --git a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java
index 371d788..90da181 100644
--- a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java
+++ b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java
@@ -608,6 +608,8 @@
     public static final KeyPrefix MULTI_INSTANCE_TASK_MAP =
             new KeyPrefix("Chrome.MultiInstance.TaskMap.*");
     public static final String MULTI_WINDOW_START_TIME = "Chrome.MultiWindow.StartTime";
+    public static final String MULTI_INSTANCE_CLOSE_WINDOW_SKIP_CONFIRM =
+            "Chrome.MultiWindow.CloseWindowSkipConfirm";
 
     // Information on each instance.
     public static final KeyPrefix MULTI_INSTANCE_INCOGNITO_TAB_COUNT =
@@ -1086,6 +1088,7 @@
                 LAST_SESSION_BROWSER_PID,
                 LAST_SESSION_APPLICATION_STATE,
                 MULTI_WINDOW_START_TIME,
+                MULTI_INSTANCE_CLOSE_WINDOW_SKIP_CONFIRM,
                 MULTI_INSTANCE_IS_INCOGNITO_SELECTED.pattern(),
                 MULTI_INSTANCE_INCOGNITO_TAB_COUNT.pattern(),
                 MULTI_INSTANCE_LAST_ACCESSED_TIME.pattern(),
diff --git a/chrome/browser/resources/history/history_clusters/clusters.html b/chrome/browser/resources/history/history_clusters/clusters.html
index 75e6440..974ac49 100644
--- a/chrome/browser/resources/history/history_clusters/clusters.html
+++ b/chrome/browser/resources/history/history_clusters/clusters.html
@@ -12,14 +12,12 @@
     width: var(--cluster-width);
   }
 
-  #title {
+  #header {
     font-size: 1.75rem;  /* 28px */
     padding: 0 var(--cluster-padding);
   }
 </style>
-<div id="header" hidden="[[!result_.query]]">
-  <div id="title">[[title_]]</div>
-</div>
+<div id="header" hidden="[[!result_.query]]">[[headerText_]]</div>
 <iron-list id="clusters"
     items="[[result_.clusters]]"
     on-remove-visits="onRemoveVisits_">
diff --git a/chrome/browser/resources/history/history_clusters/clusters.ts b/chrome/browser/resources/history/history_clusters/clusters.ts
index ab32f485..d7ac5dc 100644
--- a/chrome/browser/resources/history/history_clusters/clusters.ts
+++ b/chrome/browser/resources/history/history_clusters/clusters.ts
@@ -81,11 +81,11 @@
       result_: Object,
 
       /**
-       * The title to show when the query is non-empty.
+       * The header text to show when the query is non-empty.
        */
-      title_: {
+      headerText_: {
         type: String,
-        computed: `computeTitle_(result_)`,
+        computed: `computeHeaderText_(result_)`,
       },
 
       /**
@@ -109,7 +109,6 @@
   private onVisitsRemovedListenerId_: number|null = null;
   private pageHandler_: PageHandlerRemote;
   private result_: QueryResult = new QueryResult();
-  private title_: string = '';
   private visitsToBeRemoved_: Array<URLVisit> = [];
 
   //============================================================================
@@ -229,9 +228,9 @@
   // Helper methods
   //============================================================================
 
-  private computeTitle_(): string {
+  private computeHeaderText_(): string {
     return this.result_ ?
-        loadTimeData.getStringF('headerTitle', this.result_.query || '') :
+        loadTimeData.getStringF('headerText', this.result_.query || '') :
         '';
   }
 
diff --git a/chrome/browser/resources/history/history_clusters/top_visit.html b/chrome/browser/resources/history/history_clusters/top_visit.html
index 54fa3e9c..dc2a599 100644
--- a/chrome/browser/resources/history/history_clusters/top_visit.html
+++ b/chrome/browser/resources/history/history_clusters/top_visit.html
@@ -107,7 +107,7 @@
     </iron-collapse>
   </div>
   <div id="related-searches" hidden="[[!visit.relatedSearches.length]]">
-    <div id="related-searches-label">$i18n{relatedSearchesLabel}</div>
+    <div id="related-searches-label">$i18n{relatedSearchesHeader}</div>
     <div id="search-queries">
       <template is="dom-repeat" items="[[visit.relatedSearches]]">
         <search-query class="pill" search-query="[[item]]">
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/esim_rename_dialog.html b/chrome/browser/resources/settings/chromeos/internet_page/esim_rename_dialog.html
index 2a342537..3c38bb83 100644
--- a/chrome/browser/resources/settings/chromeos/internet_page/esim_rename_dialog.html
+++ b/chrome/browser/resources/settings/chromeos/internet_page/esim_rename_dialog.html
@@ -10,7 +10,7 @@
   }
 
   #warningMessage {
-    --iron-icon-fill-color: var(--google-grey-600);
+    --iron-icon-fill-color: var(--cros-icon-color-disabled);
     --iron-icon-height: 16px;
     --iron-icon-width: 16px;
     font-size: smaller;
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/switch_access_subpage.js b/chrome/browser/resources/settings/chromeos/os_a11y_page/switch_access_subpage.js
index 18c286af..0ca082cb 100644
--- a/chrome/browser/resources/settings/chromeos/os_a11y_page/switch_access_subpage.js
+++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/switch_access_subpage.js
@@ -7,25 +7,27 @@
  * Switch Access settings.
  */
 
-import {afterNextRender, Polymer, html, flush, Templatizer, TemplateInstanceBase} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-
-import {I18nBehavior} from '//resources/js/i18n_behavior.m.js';
 import '//resources/cr_elements/md_select_css.m.js';
-import {WebUIListenerBehavior} from '//resources/js/web_ui_listener_behavior.m.js';
-import {SliderTick} from '//resources/cr_elements/cr_slider/cr_slider.js';
 import '../../controls/settings_slider.js';
 import '../../controls/settings_toggle_button.js';
-import {DeepLinkingBehavior} from '../deep_linking_behavior.m.js';
-import {routes} from '../os_route.m.js';
-import {Router, Route, RouteObserverBehavior} from '../../router.js';
-import {loadTimeData} from '//resources/js/load_time_data.m.js';
-import {PrefsBehavior} from '../../prefs/prefs_behavior.js';
 import '../../settings_shared_css.js';
 import './switch_access_action_assignment_dialog.js';
-import {actionToPref, AUTO_SCAN_SPEED_RANGE_MS, AssignmentContext, SwitchAccessCommand, SwitchAccessDeviceType} from './switch_access_constants.js';
-import {getLabelForAssignment} from './switch_access_action_assignment_pane.js';
 import './switch_access_setup_guide_dialog.js';
 import './switch_access_setup_guide_warning_dialog.js';
+
+import {SliderTick} from '//resources/cr_elements/cr_slider/cr_slider.js';
+import {I18nBehavior} from '//resources/js/i18n_behavior.m.js';
+import {loadTimeData} from '//resources/js/load_time_data.m.js';
+import {WebUIListenerBehavior} from '//resources/js/web_ui_listener_behavior.m.js';
+import {afterNextRender, flush, html, Polymer, TemplateInstanceBase, Templatizer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+import {PrefsBehavior} from '../../prefs/prefs_behavior.js';
+import {Route, RouteObserverBehavior, Router} from '../../router.js';
+import {DeepLinkingBehavior} from '../deep_linking_behavior.m.js';
+import {routes} from '../os_route.m.js';
+
+import {getLabelForAssignment} from './switch_access_action_assignment_pane.js';
+import {actionToPref, AssignmentContext, AUTO_SCAN_SPEED_RANGE_MS, SwitchAccessCommand, SwitchAccessDeviceType} from './switch_access_constants.js';
 import {SwitchAccessSubpageBrowserProxy, SwitchAccessSubpageBrowserProxyImpl} from './switch_access_subpage_browser_proxy.js';
 
 /**
@@ -306,7 +308,7 @@
     // If this method is called with no SELECT switches, then the page has just
     // loaded, and we should open the setup guide.
     if (Object.keys(this.selectAssignments_).length === 0 &&
-        this.showSetupGuide_) {
+        this.showSetupGuide_()) {
       this.openSetupGuide_();
     }
   },
@@ -366,7 +368,8 @@
    * @private
    */
   showSetupGuide_() {
-    return loadTimeData.getBoolean('showSwitchAccessSetupGuide');
+    return loadTimeData.getBoolean('showSwitchAccessSetupGuide') &&
+        !this.showSwitchAccessActionAssignmentDialog_;
   },
 
   /**
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/long_screenshots/LongScreenshotsMediator.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/long_screenshots/LongScreenshotsMediator.java
index 035d2ce..048e3915 100644
--- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/long_screenshots/LongScreenshotsMediator.java
+++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/long_screenshots/LongScreenshotsMediator.java
@@ -69,6 +69,10 @@
     private static final int MINIMUM_VERTICAL_SELECTION_DP = 50;
     // Minimum height for mask views; should scale with ImageView margins.
     private static final int MINIMUM_MASK_HEIGHT_DP = 20;
+    // Distance from top/bottom edge dragging will scroll the view.
+    private static final int EDGE_DRAG_THRESHOLD_DP = 15;
+    // Distance for each auto-scroll-at-edge step.
+    private static final int EDGE_DRAG_STEP_DP = 5;
 
     private static final String TAG = "long_screenshots";
 
@@ -343,7 +347,7 @@
                 int bottomMaskY = getBottomMaskY();
                 int layoutHeight = ((View) mBottomAreaMaskView.getParent()).getHeight();
                 int minimumVerticalSelectionPx = dpToPx(MINIMUM_VERTICAL_SELECTION_DP);
-                // Ensure masks don't overlap and are separacted by a minimum distance.
+                // Ensure masks don't overlap and are separated by a minimum distance.
                 if (isTop && params.height + minimumVerticalSelectionPx > bottomMaskY) {
                     params.height = bottomMaskY - minimumVerticalSelectionPx;
                 }
@@ -357,6 +361,18 @@
                     params.height = minimumMaskHeightPx;
                 }
 
+                // Auto-scroll at edges.
+                int scrollY = mScrollView.getScrollY();
+                int edgeDragThresholdPx = dpToPx(EDGE_DRAG_THRESHOLD_DP);
+                if (isTop && Math.abs(topMaskY - scrollY) < edgeDragThresholdPx) {
+                    mScrollView.smoothScrollBy(0, dpToPx(-EDGE_DRAG_STEP_DP));
+                }
+                if (!isTop
+                        && Math.abs(scrollY + mScrollView.getHeight() - bottomMaskY)
+                                < edgeDragThresholdPx) {
+                    mScrollView.smoothScrollBy(0, dpToPx(EDGE_DRAG_STEP_DP));
+                }
+
                 maskView.setLayoutParams(params);
                 handled = true;
                 break;
diff --git a/chrome/browser/share/share_submenu_model.cc b/chrome/browser/share/share_submenu_model.cc
index 8f0f6c53..527c306a 100644
--- a/chrome/browser/share/share_submenu_model.cc
+++ b/chrome/browser/share/share_submenu_model.cc
@@ -14,7 +14,7 @@
 #include "chrome/browser/sharing_hub/sharing_hub_service_factory.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/qrcode_generator/qrcode_generator_bubble_controller.h"
-#include "chrome/browser/ui/send_tab_to_self/send_tab_to_self_sub_menu_model.h"
+#include "chrome/browser/ui/send_tab_to_self/send_tab_to_self_bubble_controller.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
@@ -29,14 +29,6 @@
 
 namespace {
 
-bool ShouldUseSendTabToSelfIcons() {
-#if defined(OS_MAC)
-  return false;
-#else
-  return true;
-#endif
-}
-
 // TODO(ellyjones): This is duplicated from RenderViewContextMenu, where it
 // doesn't really belong. There is a note on the RenderViewContextMenu to remove
 // it once it is no longer needed there, after https://crbug.com/1250494 is
@@ -84,6 +76,8 @@
       context_(context),
       url_(url),
       text_(text) {
+  // These methods will silently not add the specified item if it doesn't apply
+  // to the given context or URL.
   AddGenerateQRCodeItem();
   AddSendTabToSelfItem();
   AddCopyLinkItem();
@@ -97,8 +91,8 @@
     case IDC_CONTENT_CONTEXT_GENERATE_QR_CODE:
       GenerateQRCode();
       break;
-    case IDC_SEND_TAB_TO_SELF_SINGLE_TARGET:
-      SendTabToSelfSingleTarget();
+    case IDC_SEND_TAB_TO_SELF:
+      SendTabToSelf();
       break;
     case IDC_CONTENT_CONTEXT_COPYLINKLOCATION:
     case IDC_CONTENT_CONTEXT_COPYIMAGELOCATION:
@@ -121,7 +115,8 @@
                           IDS_CONTEXT_MENU_GENERATE_QR_CODE_PAGE);
       break;
     case Context::LINK:
-      NOTIMPLEMENTED();
+      // TODO(https://crbug.com/1252129): Support this mode, which will require
+      // a new string.
       break;
     default:
       break;
@@ -129,42 +124,11 @@
 }
 
 void ShareSubmenuModel::AddSendTabToSelfItem() {
-  // This can happen in unit tests which don't want to supply a browser or
-  // profile.
-  if (!browser_ || !browser_->profile())
-    return;
-
-  size_t devices = send_tab_to_self::GetValidDeviceCount(browser_->profile());
-
-  if (devices == 0)
-    return;
-
-  if (devices == 1) {
-    AddSendTabToSelfSingleTargetItem();
-    return;
-  }
-
-  int label_id, command_id;
-  send_tab_to_self::SendTabToSelfMenuType menu_type;
-  if (context_ == Context::LINK) {
-    label_id = IDS_LINK_MENU_SEND_TAB_TO_SELF;
-    command_id = IDC_CONTENT_LINK_SEND_TAB_TO_SELF;
-    menu_type = send_tab_to_self::SendTabToSelfMenuType::kLink;
-  } else {
-    label_id = IDS_CONTEXT_MENU_SEND_TAB_TO_SELF;
-    command_id = IDC_SEND_TAB_TO_SELF;
-    menu_type = send_tab_to_self::SendTabToSelfMenuType::kContent;
-  }
-
-  stts_submenu_model_ =
-      std::make_unique<send_tab_to_self::SendTabToSelfSubMenuModel>(
-          browser_->tab_strip_model()->GetActiveWebContents(), menu_type);
-  if (ShouldUseSendTabToSelfIcons()) {
-    AddSubMenuWithStringIdAndIcon(
-        command_id, label_id, stts_submenu_model_.get(),
-        ui::ImageModel::FromVectorIcon(kSendTabToSelfIcon));
-  } else {
-    AddSubMenuWithStringId(command_id, label_id, stts_submenu_model_.get());
+  // Only offer STTS when the context is actually the entire page; STTS can't
+  // currently be used on links or images.
+  if (context_ == Context::PAGE) {
+    AddItemWithStringId(IDC_SEND_TAB_TO_SELF,
+                        IDS_CONTEXT_MENU_SEND_TAB_TO_SELF);
   }
 }
 
@@ -207,21 +171,6 @@
   }
 }
 
-void ShareSubmenuModel::AddSendTabToSelfSingleTargetItem() {
-  std::u16string label = l10n_util::GetStringFUTF16(
-      IDS_LINK_MENU_SEND_TAB_TO_SELF_SINGLE_TARGET,
-      send_tab_to_self::GetSingleTargetDeviceName(browser_->profile()));
-  int command_id = context_ == Context::LINK
-                       ? IDC_CONTENT_LINK_SEND_TAB_TO_SELF_SINGLE_TARGET
-                       : IDC_SEND_TAB_TO_SELF_SINGLE_TARGET;
-  if (ShouldUseSendTabToSelfIcons()) {
-    AddItemWithIcon(command_id, label,
-                    ui::ImageModel::FromVectorIcon(kSendTabToSelfIcon));
-  } else {
-    AddItem(command_id, label);
-  }
-}
-
 void ShareSubmenuModel::GenerateQRCode() {
   auto* web_contents = browser_->tab_strip_model()->GetActiveWebContents();
   auto* bubble_controller =
@@ -238,18 +187,13 @@
   bubble_controller->ShowBubble(url_);
 }
 
-void ShareSubmenuModel::SendTabToSelfSingleTarget() {
-  if (context_ == Context::LINK) {
-    send_tab_to_self::ShareToSingleTarget(
-        browser_->tab_strip_model()->GetActiveWebContents(), url_);
-    send_tab_to_self::RecordDeviceClicked(
-        send_tab_to_self::ShareEntryPoint::kLinkMenu);
-  } else {
-    send_tab_to_self::ShareToSingleTarget(
-        browser_->tab_strip_model()->GetActiveWebContents());
-    send_tab_to_self::RecordDeviceClicked(
-        send_tab_to_self::ShareEntryPoint::kContentMenu);
-  }
+void ShareSubmenuModel::SendTabToSelf() {
+  content::WebContents* web_contents =
+      browser_->tab_strip_model()->GetActiveWebContents();
+  send_tab_to_self::SendTabToSelfBubbleController* controller =
+      send_tab_to_self::SendTabToSelfBubbleController::
+          CreateOrGetFromWebContents(web_contents);
+  controller->ShowBubble();
 }
 
 void ShareSubmenuModel::CopyLink() {
diff --git a/chrome/browser/share/share_submenu_model.h b/chrome/browser/share/share_submenu_model.h
index 87226423..32b27e1f 100644
--- a/chrome/browser/share/share_submenu_model.h
+++ b/chrome/browser/share/share_submenu_model.h
@@ -12,10 +12,6 @@
 
 class Browser;
 
-namespace send_tab_to_self {
-class SendTabToSelfSubMenuModel;
-}
-
 namespace sharing_hub {
 class SharingHubModel;
 }
@@ -68,10 +64,8 @@
   void AddCopyLinkItem();
   void AddShareToThirdPartyItems();
 
-  void AddSendTabToSelfSingleTargetItem();
-
   void GenerateQRCode();
-  void SendTabToSelfSingleTarget();
+  void SendTabToSelf();
   void CopyLink();
   void ShareToThirdParty(int command_id);
 
@@ -82,9 +76,6 @@
   Context context_;
   GURL url_;
   std::u16string text_;
-
-  std::unique_ptr<send_tab_to_self::SendTabToSelfSubMenuModel>
-      stts_submenu_model_;
 };
 
 }  // namespace share
diff --git a/chrome/browser/site_isolation/chrome_site_isolation_policy_unittest.cc b/chrome/browser/site_isolation/chrome_site_isolation_policy_unittest.cc
index 2f982e9..67794bc 100644
--- a/chrome/browser/site_isolation/chrome_site_isolation_policy_unittest.cc
+++ b/chrome/browser/site_isolation/chrome_site_isolation_policy_unittest.cc
@@ -59,11 +59,13 @@
     mode_feature_.InitAndEnableFeature(features::kSitePerProcess);
   }
 
+  // Note that this only sets the memory threshold for strict site isolation,
+  // which is the only mode this test currently cares about.
   void SetMemoryThreshold(const std::string& threshold) {
     threshold_feature_.InitAndEnableFeatureWithParameters(
-        site_isolation::features::kSitePerProcessOnlyForHighMemoryClients,
+        site_isolation::features::kSiteIsolationMemoryThresholds,
         {{site_isolation::features::
-              kSitePerProcessOnlyForHighMemoryClientsParamName,
+              kStrictSiteIsolationMemoryThresholdParamName,
           threshold}});
   }
 
diff --git a/chrome/browser/ssl/connection_help_tab_helper.cc b/chrome/browser/ssl/connection_help_tab_helper.cc
index f75f693..c98bdb1 100644
--- a/chrome/browser/ssl/connection_help_tab_helper.cc
+++ b/chrome/browser/ssl/connection_help_tab_helper.cc
@@ -33,9 +33,7 @@
 
 void ConnectionHelpTabHelper::DidFinishNavigation(
     content::NavigationHandle* navigation_handle) {
-  // TODO(https://crbug.com/1218946): With MPArch there may be multiple main
-  // frames. This caller was converted automatically to the primary main frame
-  // to preserve its semantics. Follow up to confirm correctness.
+  // Ignore pre-rendering navigations.
   if (navigation_handle->IsInPrimaryMainFrame() &&
       (web_contents()->GetURL().EqualsIgnoringRef(GetHelpCenterURL()) ||
        web_contents()->GetURL().EqualsIgnoringRef(GURL(kSymantecSupportUrl))) &&
diff --git a/chrome/browser/sync/test/integration/sync_app_list_helper.cc b/chrome/browser/sync/test/integration/sync_app_list_helper.cc
index a81ec1e..bd763d77 100644
--- a/chrome/browser/sync/test/integration/sync_app_list_helper.cc
+++ b/chrome/browser/sync/test/integration/sync_app_list_helper.cc
@@ -123,7 +123,7 @@
                                         const std::string& folder_id) {
   AppListSyncableService* service =
       AppListSyncableServiceFactory::GetForProfile(profile);
-  service->GetModelUpdater()->MoveItemToFolder(id, folder_id);
+  service->GetModelUpdater()->SetItemFolderId(id, folder_id);
 }
 
 void SyncAppListHelper::MoveAppFromFolder(Profile* profile,
@@ -137,7 +137,7 @@
     LOG(ERROR) << "Folder not found: " << folder_id;
     return;
   }
-  service->GetModelUpdater()->MoveItemToFolder(id, "");
+  service->GetModelUpdater()->SetItemFolderId(id, "");
 }
 
 void SyncAppListHelper::PrintAppList(Profile* profile) {
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index fcb01dc2..3becd710 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -3677,6 +3677,10 @@
       "autofill/edit_address_profile_dialog_controller.h",
       "autofill/edit_address_profile_dialog_controller_impl.cc",
       "autofill/edit_address_profile_dialog_controller_impl.h",
+      "autofill/payments/card_unmask_authentication_selection_dialog_controller.h",
+      "autofill/payments/card_unmask_authentication_selection_dialog_controller_impl.cc",
+      "autofill/payments/card_unmask_authentication_selection_dialog_controller_impl.h",
+      "autofill/payments/card_unmask_authentication_selection_dialog_view.h",
       "autofill/payments/local_card_migration_bubble_controller_impl.cc",
       "autofill/payments/local_card_migration_bubble_controller_impl.h",
       "autofill/payments/local_card_migration_controller_observer.h",
@@ -3773,6 +3777,8 @@
       "views/autofill/edit_address_profile_view.h",
       "views/autofill/payments/autofill_error_dialog_view_native_views.cc",
       "views/autofill/payments/autofill_error_dialog_view_native_views.h",
+      "views/autofill/payments/card_unmask_authentication_selection_dialog_view_impl.cc",
+      "views/autofill/payments/card_unmask_authentication_selection_dialog_view_impl.h",
       "views/autofill/payments/card_unmask_prompt_views.cc",
       "views/autofill/payments/card_unmask_prompt_views.h",
       "views/autofill/payments/dialog_view_ids.h",
@@ -4357,6 +4363,8 @@
       "views/sharing_hub/screenshot/screenshot_captured_bubble.h",
       "views/sharing_hub/sharing_hub_bubble_action_button.cc",
       "views/sharing_hub/sharing_hub_bubble_action_button.h",
+      "views/sharing_hub/sharing_hub_bubble_util.cc",
+      "views/sharing_hub/sharing_hub_bubble_util.h",
       "views/sharing_hub/sharing_hub_bubble_view_impl.cc",
       "views/sharing_hub/sharing_hub_bubble_view_impl.h",
       "views/sharing_hub/sharing_hub_icon_view.cc",
diff --git a/chrome/browser/ui/android/multiwindow/BUILD.gn b/chrome/browser/ui/android/multiwindow/BUILD.gn
index 94909b5e..fcf61739 100644
--- a/chrome/browser/ui/android/multiwindow/BUILD.gn
+++ b/chrome/browser/ui/android/multiwindow/BUILD.gn
@@ -18,6 +18,7 @@
   deps = [
     ":java_resources",
     "//base:base_java",
+    "//chrome/browser/preferences:java",
     "//chrome/browser/profiles/android:java",
     "//chrome/browser/ui/android/favicon:java",
     "//components/browser_ui/modaldialog/android:java",
@@ -49,6 +50,7 @@
     "//chrome/browser/ui/android/favicon:java_resources",
     "//chrome/browser/ui/android/strings:ui_strings_grd",
     "//chrome/browser/ui/android/toolbar:java_resources",
+    "//components/browser_ui/modaldialog/android:java_resources",
     "//components/browser_ui/styles/android:java_resources",
     "//components/browser_ui/widget/android:java_resources",
   ]
@@ -93,6 +95,7 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//chrome/browser/flags:java",
+    "//chrome/browser/preferences:java",
     "//chrome/test/android:chrome_java_test_support",
     "//components/browser_ui/modaldialog/android:java",
     "//components/browser_ui/settings/android:java",
diff --git a/chrome/browser/ui/android/multiwindow/java/res/layout/instance_switcher_dialog.xml b/chrome/browser/ui/android/multiwindow/java/res/layout/instance_switcher_dialog.xml
index b3c69cd..6e8457d5 100644
--- a/chrome/browser/ui/android/multiwindow/java/res/layout/instance_switcher_dialog.xml
+++ b/chrome/browser/ui/android/multiwindow/java/res/layout/instance_switcher_dialog.xml
@@ -12,7 +12,7 @@
 
     <include layout="@layout/instance_switcher_list"/>
 
-    <FrameLayout
+    <RelativeLayout
         android:id="@+id/close_confirm"
         android:visibility="gone"
         android:layout_width="match_parent"
@@ -21,10 +21,24 @@
             android:id="@+id/message"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_marginHorizontal="16dp"
+            android:layout_marginStart="24dp"
             android:layout_marginVertical="16dp"
-            android:gravity="center_horizontal"
-            android:layout_gravity="center"
+            android:layout_alignParentTop="true"
             android:textAppearance="@style/TextAppearance.TextLarge.Primary" />
-    </FrameLayout>
+        <CheckBox
+            android:id="@+id/no_more_check"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="18dp"
+            android:layout_marginBottom="12dp"
+            android:layout_below="@id/message" />
+        <TextView
+            android:id="@+id/no_more"
+            android:text="@string/dont_ask_again"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_toEndOf="@id/no_more_check"
+            android:layout_alignBaseline="@id/no_more_check"
+            android:textAppearance="@style/TextAppearance.TextLarge.Secondary" />
+    </RelativeLayout>
 </FrameLayout>
diff --git a/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/InstanceSwitcherCoordinator.java b/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/InstanceSwitcherCoordinator.java
index f024897d..a96dc30 100644
--- a/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/InstanceSwitcherCoordinator.java
+++ b/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/InstanceSwitcherCoordinator.java
@@ -12,6 +12,7 @@
 import android.graphics.drawable.Drawable;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.widget.CheckBox;
 import android.widget.ListView;
 import android.widget.TextView;
 
@@ -20,6 +21,8 @@
 
 import org.chromium.base.Callback;
 import org.chromium.base.metrics.RecordUserAction;
+import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
+import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
 import org.chromium.components.browser_ui.widget.listmenu.BasicListMenu;
 import org.chromium.components.browser_ui.widget.listmenu.ListMenu;
 import org.chromium.components.browser_ui.widget.listmenu.ListMenuItemProperties;
@@ -154,12 +157,19 @@
                     case ModalDialogProperties.ButtonType.POSITIVE:
                         assert mIsShowingConfirmationMessage;
                         assert mItemToDelete != null;
+                        CheckBox skipConfirm =
+                                (CheckBox) mDialogView.findViewById(R.id.no_more_check);
+                        if (skipConfirm.isChecked()) setSkipCloseConfirmation();
                         hideConfirmationMessage();
                         removeInstance(mItemToDelete);
                         break;
                     case ModalDialogProperties.ButtonType.NEGATIVE:
                         dismissDialog(DialogDismissalCause.NEGATIVE_BUTTON_CLICKED);
                         break;
+                    case ModalDialogProperties.ButtonType.TITLE_ICON:
+                        assert mIsShowingConfirmationMessage;
+                        hideConfirmationMessage();
+                        break;
                 }
             }
         };
@@ -216,7 +226,7 @@
         ListMenu.Delegate moreMenuDelegate = (model) -> {
             int textId = model.get(ListMenuItemProperties.TITLE_ID);
             if (textId == R.string.instance_switcher_close_window) {
-                if (UiUtils.totalTabCount(item) == 0 && item.type == InstanceInfo.Type.OTHER) {
+                if (canSkipConfirm(item)) {
                     removeInstance(item);
                 } else {
                     showConfirmationMessage(item);
@@ -261,6 +271,19 @@
         enableNewWindowCommand(true);
     }
 
+    private static boolean canSkipConfirm(InstanceInfo item) {
+        // Unrestorable, invisible instance can be deleted without confirmation.
+        if (UiUtils.totalTabCount(item) == 0 && item.type == InstanceInfo.Type.OTHER) return true;
+        return SharedPreferencesManager.getInstance().readBoolean(
+                ChromePreferenceKeys.MULTI_INSTANCE_CLOSE_WINDOW_SKIP_CONFIRM, false);
+    }
+
+    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+    static void setSkipCloseConfirmation() {
+        SharedPreferencesManager.getInstance().writeBoolean(
+                ChromePreferenceKeys.MULTI_INSTANCE_CLOSE_WINDOW_SKIP_CONFIRM, true);
+    }
+
     private void showConfirmationMessage(InstanceInfo item) {
         mItemToDelete = item;
         Resources res = mContext.getResources();
@@ -295,4 +318,9 @@
                                          .getListMenu();
         moreMenu.onItemClick(null, null, menuIndex, 0);
     }
+
+    @VisibleForTesting
+    boolean isShowingConfirmationDialogForTesting() {
+        return mIsShowingConfirmationMessage;
+    }
 }
diff --git a/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/InstanceSwitcherCoordinatorTest.java b/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/InstanceSwitcherCoordinatorTest.java
index 6a3f9d4..4b61ebf 100644
--- a/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/InstanceSwitcherCoordinatorTest.java
+++ b/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/InstanceSwitcherCoordinatorTest.java
@@ -15,10 +15,14 @@
 import static androidx.test.espresso.matcher.ViewMatchers.withId;
 import static androidx.test.espresso.matcher.ViewMatchers.withText;
 
+import static org.hamcrest.Matchers.allOf;
 import static org.hamcrest.Matchers.anything;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
 import androidx.test.filters.SmallTest;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -27,6 +31,8 @@
 import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
+import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
+import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.DummyUiChromeActivityTestCase;
 import org.chromium.components.browser_ui.modaldialog.AppModalPresenter;
@@ -67,13 +73,19 @@
         };
     }
 
+    @After
+    public void tearDown() throws Exception {
+        SharedPreferencesManager.getInstance().writeBoolean(
+                ChromePreferenceKeys.MULTI_INSTANCE_CLOSE_WINDOW_SKIP_CONFIRM, false);
+    }
+
     @Test
     @SmallTest
     public void testOpenWindow() throws Exception {
         InstanceInfo[] instances = new InstanceInfo[] {
                 new InstanceInfo(0, 57, InstanceInfo.Type.CURRENT, "url0", "title0", 1, 0, false),
                 new InstanceInfo(1, 58, InstanceInfo.Type.OTHER, "ur11", "title1", 2, 0, false),
-                new InstanceInfo(2, 59, InstanceInfo.Type.OTHER, "url2", "title2", 1, 1, false)};
+                new InstanceInfo(2, 59, InstanceInfo.Type.OTHER, "url2", "title2", 0, 0, false)};
         final CallbackHelper itemClickCallbackHelper = new CallbackHelper();
         final int itemClickCount = itemClickCallbackHelper.getCallCount();
         Callback<InstanceInfo> openCallback = (item) -> itemClickCallbackHelper.notifyCalled();
@@ -91,7 +103,7 @@
         InstanceInfo[] instances = new InstanceInfo[] {
                 new InstanceInfo(0, 57, InstanceInfo.Type.CURRENT, "url0", "title0", 1, 0, false),
                 new InstanceInfo(1, 58, InstanceInfo.Type.OTHER, "ur11", "title1", 2, 0, false),
-                new InstanceInfo(2, 59, InstanceInfo.Type.OTHER, "url2", "title2", 1, 1, false)};
+                new InstanceInfo(2, 59, InstanceInfo.Type.OTHER, "url2", "title2", 0, 0, false)};
         final CallbackHelper itemClickCallbackHelper = new CallbackHelper();
         final int itemClickCount = itemClickCallbackHelper.getCallCount();
         TestThreadUtils.runOnUiThreadBlocking(() -> {
@@ -122,8 +134,7 @@
         });
 
         // Verify that we have only [cancel] button.
-        onView(withId(org.chromium.components.browser_ui.modaldialog.R.id.positive_button))
-                .check(matches(withEffectiveVisibility(GONE)));
+        onView(withId(R.id.positive_button)).check(matches(withEffectiveVisibility(GONE)));
         onView(withText(R.string.cancel)).check(matches(withEffectiveVisibility(VISIBLE)));
 
         final int itemIndex = 2; // Index of the instance entry to close
@@ -163,4 +174,56 @@
                 .onChildView(withText(R.string.max_number_of_windows))
                 .check(matches(isDisplayed()));
     }
+
+    @Test
+    @SmallTest
+    public void testSkipCloseConfirmation() throws Exception {
+        InstanceInfo[] instances = new InstanceInfo[] {
+                new InstanceInfo(0, 57, InstanceInfo.Type.CURRENT, "url0", "title0", 1, 0, false),
+                new InstanceInfo(1, 58, InstanceInfo.Type.OTHER, "ur11", "title1", 2, 0, false),
+                new InstanceInfo(2, 59, InstanceInfo.Type.OTHER, "url2", "title2", 0, 0, false)};
+        final CallbackHelper closeCallbackHelper = new CallbackHelper();
+        int itemClickCount = closeCallbackHelper.getCallCount();
+        Callback<InstanceInfo> closeCallback = (item) -> closeCallbackHelper.notifyCalled();
+        InstanceSwitcherCoordinator coordinator = TestThreadUtils.runOnUiThreadBlocking(() -> {
+            InstanceSwitcherCoordinator ic = new InstanceSwitcherCoordinator(
+                    getActivity(), mModalDialogManager, mIconBridge, null, closeCallback, null);
+            ic.show(Arrays.asList(instances), true);
+            return ic;
+        });
+
+        // Closing a hidden, tab-less instance skips the confirmation.
+        onData(anything()).atPosition(2).onChildView(withId(R.id.more)).perform(click());
+        TestThreadUtils.runOnUiThreadBlocking(() -> coordinator.clickMoreMenuItemForTesting(2, 0));
+        closeCallbackHelper.waitForCallback(itemClickCount);
+
+        // Verify that the close callback skips the confirmation when the skip checkbox
+        // was ticked on.
+        InstanceSwitcherCoordinator.setSkipCloseConfirmation();
+        itemClickCount = closeCallbackHelper.getCallCount();
+        onData(anything()).atPosition(1).onChildView(withId(R.id.more)).perform(click());
+        TestThreadUtils.runOnUiThreadBlocking(() -> coordinator.clickMoreMenuItemForTesting(1, 0));
+        closeCallbackHelper.waitForCallback(itemClickCount);
+    }
+
+    @Test
+    @SmallTest
+    public void testBackOnConfirmDialog() throws Exception {
+        InstanceInfo[] instances = new InstanceInfo[] {
+                new InstanceInfo(0, 57, InstanceInfo.Type.CURRENT, "url0", "title0", 1, 0, false),
+                new InstanceInfo(1, 58, InstanceInfo.Type.OTHER, "ur11", "title1", 2, 0, false),
+                new InstanceInfo(2, 59, InstanceInfo.Type.OTHER, "url2", "title2", 1, 1, false)};
+        InstanceSwitcherCoordinator coordinator = TestThreadUtils.runOnUiThreadBlocking(() -> {
+            InstanceSwitcherCoordinator ic = new InstanceSwitcherCoordinator(
+                    getActivity(), mModalDialogManager, mIconBridge, null, null, null);
+            ic.show(Arrays.asList(instances), true);
+            return ic;
+        });
+
+        onData(anything()).atPosition(2).onChildView(withId(R.id.more)).perform(click());
+        TestThreadUtils.runOnUiThreadBlocking(() -> coordinator.clickMoreMenuItemForTesting(2, 0));
+        assertTrue(coordinator.isShowingConfirmationDialogForTesting());
+        onView(allOf(withId(R.id.title_icon), withEffectiveVisibility(VISIBLE))).perform(click());
+        assertFalse(coordinator.isShowingConfirmationDialogForTesting());
+    }
 }
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd
index ccf5a6d..2a37d00 100644
--- a/chrome/browser/ui/android/strings/android_chrome_strings.grd
+++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -748,19 +748,19 @@
 Touch &amp; hold any word to search. To refine your search, select more or fewer words. To edit your search, open the panel, tap the icon to open in a new tab, and make your changes in the search box.
       </message>
       <message name="IDS_CONTEXTUAL_SEARCH_DESCRIPTION_REVISED" desc="Description for Contextual Search preference">
-        Learn about a topic without leaving the page. Select one or more words on the page to search for them. To edit your search, look at the results and open them in a new tab.
+        Learn about topics on websites without leaving the page. Select one or more words on the page to search for them.
       </message>
       <message name="IDS_CONTEXTUAL_SEARCH_SHORT_DESCRIPTION" desc="A promo message shown to users with Touch to Search to explain the new behavior and provide an option to opt in or out">
         Touch to Search sends the selected word and the current page as context to Google Search. You can turn it off in <ph name="BEGIN_LINK">&lt;link&gt;</ph>Settings<ph name="END_LINK">&lt;/link&gt;</ph>.
       </message>
       <message name="IDS_CONTEXTUAL_SEARCH_PROMO_TITLE" desc="The title of the promo message for the contextual search.">
-        Get more relevant info
+        Include surrounding text in Google searches?
       </message>
       <message name="IDS_CONTEXTUAL_SEARCH_PROMO_DESCRIPTION" desc="A promo message shown to users with Touch to Search to explain the new behavior and provide an option to opt in or out">
-        See better results for the words you highlight by letting Google consider some of the page's text. You can always change your <ph name="BEGIN_LINK">&lt;link&gt;</ph>Settings<ph name="END_LINK">&lt;/link&gt;</ph>.
+        By including more of a page’s text, you might see better results when using Touch to Search. You can always visit <ph name="BEGIN_LINK">&lt;link&gt;</ph>settings<ph name="END_LINK">&lt;/link&gt;</ph> to change this.
       </message>
-      <message name="IDS_CONTEXTUAL_SEARCH_TURN_ON_BUTTON" desc="A button to confirm and dismiss opt in promo">
-        Turn on
+      <message name="IDS_CONTEXTUAL_SEARCH_INCLUDE_BUTTON" desc="A button to confirm and dismiss opt in promo">
+        Include
       </message>
       <message name="IDS_CONTEXTUAL_SEARCH_ALLOW_BUTTON" desc="A button to confirm and dismiss opt out promo">
         Allow
@@ -778,10 +778,10 @@
         Tap to see search results
       </message>
       <message name="IDS_CONTEXTUAL_SEARCH_SEE_BETTER_RESULTS_TITLE" desc="Title for the see better results switch in Contextual Search preference.">
-        See better results
+        Include surrounding text in Google searches
       </message>
       <message name="IDS_CONTEXTUAL_SEARCH_SEE_BETTER_RESULTS_SUMMARY" desc="Summary for the see better results switch in Contextual Search preference.">
-        Let Google also consider some of the page’s text
+        By including more of a page’s text, you might see better results
       </message>
       <message name="IDS_DO_NOT_TRACK_TITLE" desc="Title for 'Do Not Track' preference">
         “Do Not Track”
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTUAL_SEARCH_DESCRIPTION_REVISED.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTUAL_SEARCH_DESCRIPTION_REVISED.png.sha1
index 2f810698..088ccce 100644
--- a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTUAL_SEARCH_DESCRIPTION_REVISED.png.sha1
+++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTUAL_SEARCH_DESCRIPTION_REVISED.png.sha1
@@ -1 +1 @@
-165b8646a0f42ae5a12f89ad2685f7fccffeae84
\ No newline at end of file
+7a9ff6cf847d62c9454fd93f371d35934d9271db
\ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTUAL_SEARCH_INCLUDE_BUTTON.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTUAL_SEARCH_INCLUDE_BUTTON.png.sha1
new file mode 100644
index 0000000..007544b
--- /dev/null
+++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTUAL_SEARCH_INCLUDE_BUTTON.png.sha1
@@ -0,0 +1 @@
+d1e73588eaeb56ae6a6d55b40745b2102d651325
\ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTUAL_SEARCH_PROMO_DESCRIPTION.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTUAL_SEARCH_PROMO_DESCRIPTION.png.sha1
index 8d131fb..007544b 100644
--- a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTUAL_SEARCH_PROMO_DESCRIPTION.png.sha1
+++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTUAL_SEARCH_PROMO_DESCRIPTION.png.sha1
@@ -1 +1 @@
-56891588c2c1bf8f7f779af57cc1850c9863638c
\ No newline at end of file
+d1e73588eaeb56ae6a6d55b40745b2102d651325
\ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTUAL_SEARCH_PROMO_TITLE.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTUAL_SEARCH_PROMO_TITLE.png.sha1
index 8d131fb..007544b 100644
--- a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTUAL_SEARCH_PROMO_TITLE.png.sha1
+++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTUAL_SEARCH_PROMO_TITLE.png.sha1
@@ -1 +1 @@
-56891588c2c1bf8f7f779af57cc1850c9863638c
\ No newline at end of file
+d1e73588eaeb56ae6a6d55b40745b2102d651325
\ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTUAL_SEARCH_SEE_BETTER_RESULTS_SUMMARY.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTUAL_SEARCH_SEE_BETTER_RESULTS_SUMMARY.png.sha1
index 2f810698..abb0c25 100644
--- a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTUAL_SEARCH_SEE_BETTER_RESULTS_SUMMARY.png.sha1
+++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTUAL_SEARCH_SEE_BETTER_RESULTS_SUMMARY.png.sha1
@@ -1 +1 @@
-165b8646a0f42ae5a12f89ad2685f7fccffeae84
\ No newline at end of file
+8d0315ebf9ce4b9647fadc775bb6f802f34ef15d
\ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTUAL_SEARCH_SEE_BETTER_RESULTS_TITLE.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTUAL_SEARCH_SEE_BETTER_RESULTS_TITLE.png.sha1
index 51006b1..abb0c25 100644
--- a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTUAL_SEARCH_SEE_BETTER_RESULTS_TITLE.png.sha1
+++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTUAL_SEARCH_SEE_BETTER_RESULTS_TITLE.png.sha1
@@ -1 +1 @@
-c4edee7a48fc45d96fd547f85e0de802713c3cae
\ No newline at end of file
+8d0315ebf9ce4b9647fadc775bb6f802f34ef15d
\ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTUAL_SEARCH_TURN_ON_BUTTON.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTUAL_SEARCH_TURN_ON_BUTTON.png.sha1
deleted file mode 100644
index 8d131fb..0000000
--- a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTUAL_SEARCH_TURN_ON_BUTTON.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-56891588c2c1bf8f7f779af57cc1850c9863638c
\ No newline at end of file
diff --git a/chrome/browser/ui/app_list/app_list_model_updater.h b/chrome/browser/ui/app_list/app_list_model_updater.h
index 34ecad7..3133d5d 100644
--- a/chrome/browser/ui/app_list/app_list_model_updater.h
+++ b/chrome/browser/ui/app_list/app_list_model_updater.h
@@ -55,8 +55,6 @@
                                const std::string& folder_id) {}
   virtual void RemoveItem(const std::string& id) {}
   virtual void RemoveUninstalledItem(const std::string& id) {}
-  virtual void MoveItemToFolder(const std::string& id,
-                                const std::string& folder_id) {}
   virtual void SetStatus(ash::AppListModelStatus status) {}
   // For SearchModel:
   virtual void SetSearchEngineIsGoogle(bool is_google) {}
diff --git a/chrome/browser/ui/app_list/app_list_syncable_service.cc b/chrome/browser/ui/app_list/app_list_syncable_service.cc
index b6105d0..da056ab 100644
--- a/chrome/browser/ui/app_list/app_list_syncable_service.cc
+++ b/chrome/browser/ui/app_list/app_list_syncable_service.cc
@@ -901,9 +901,9 @@
   // Check to see if the item needs to be moved to/from the OEM folder.
   bool is_oem = AppIsOem(app_item->id());
   if (!is_oem && app_item->folder_id() == ash::kOemFolderId)
-    model_updater_->MoveItemToFolder(app_item->id(), "");
+    model_updater_->SetItemFolderId(app_item->id(), "");
   else if (is_oem && app_item->folder_id() != ash::kOemFolderId)
-    model_updater_->MoveItemToFolder(app_item->id(), ash::kOemFolderId);
+    model_updater_->SetItemFolderId(app_item->id(), ash::kOemFolderId);
 }
 
 void AppListSyncableService::RemoveSyncItem(const std::string& id) {
diff --git a/chrome/browser/ui/app_list/app_list_syncable_service_unittest.cc b/chrome/browser/ui/app_list/app_list_syncable_service_unittest.cc
index 33a72100..76b77edd 100644
--- a/chrome/browser/ui/app_list/app_list_syncable_service_unittest.cc
+++ b/chrome/browser/ui/app_list/app_list_syncable_service_unittest.cc
@@ -1371,7 +1371,7 @@
   // Modify Webstore app with non-default attributes.
   model_updater()->SetItemPosition(extensions::kWebStoreAppId,
                                    syncer::StringOrdinal("position"));
-  model_updater()->MoveItemToFolder(extensions::kWebStoreAppId, "folderid");
+  model_updater()->SetItemFolderId(extensions::kWebStoreAppId, "folderid");
   app_list_syncable_service()->SetPinPosition(extensions::kWebStoreAppId,
                                               syncer::StringOrdinal("pin"));
 
diff --git a/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc b/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc
index 37931726..a79edaf 100644
--- a/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc
+++ b/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc
@@ -116,14 +116,6 @@
     app_list_controller_->RemoveUninstalledItem(id_copy);
 }
 
-void ChromeAppListModelUpdater::MoveItemToFolder(const std::string& id,
-                                                 const std::string& folder_id) {
-  if (app_list_controller_)
-    app_list_controller_->MoveItemToFolder(id, folder_id);
-  else
-    MoveChromeItemToFolder(id, folder_id);
-}
-
 void ChromeAppListModelUpdater::SetStatus(ash::AppListModelStatus status) {
   if (!app_list_controller_)
     return;
@@ -191,15 +183,6 @@
   items_.erase(id);
 }
 
-void ChromeAppListModelUpdater::MoveChromeItemToFolder(
-    const std::string& id,
-    const std::string& folder_id) {
-  ChromeAppListItem* item = FindItem(id);
-  if (!item)
-    return;
-  item->SetChromeFolderId(folder_id);
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // Methods only used by ChromeAppListItem that talk to ash directly.
 
@@ -284,11 +267,15 @@
 
 void ChromeAppListModelUpdater::SetItemFolderId(const std::string& id,
                                                 const std::string& folder_id) {
-  if (!app_list_controller_)
-    return;
   ChromeAppListItem* item = FindItem(id);
   if (!item)
     return;
+
+  if (!app_list_controller_) {
+    item->SetChromeFolderId(folder_id);
+    return;
+  }
+
   std::unique_ptr<ash::AppListItemMetadata> data = item->CloneMetadata();
   data->folder_id = folder_id;
   app_list_controller_->SetItemMetadata(id, std::move(data));
@@ -490,7 +477,7 @@
   if (update_folder && chrome_item->folder_id() != sync_item->parent_id) {
     VLOG(2) << " Moving Item To Folder: " << sync_item->parent_id;
     // This updates the folder in both chrome and ash:
-    MoveItemToFolder(chrome_item->id(), sync_item->parent_id);
+    SetItemFolderId(chrome_item->id(), sync_item->parent_id);
   }
 }
 
diff --git a/chrome/browser/ui/app_list/chrome_app_list_model_updater.h b/chrome/browser/ui/app_list/chrome_app_list_model_updater.h
index 72b1d17..a33ecd0 100644
--- a/chrome/browser/ui/app_list/chrome_app_list_model_updater.h
+++ b/chrome/browser/ui/app_list/chrome_app_list_model_updater.h
@@ -36,8 +36,6 @@
                        const std::string& folder_id) override;
   void RemoveItem(const std::string& id) override;
   void RemoveUninstalledItem(const std::string& id) override;
-  void MoveItemToFolder(const std::string& id,
-                        const std::string& folder_id) override;
   void SetStatus(ash::AppListModelStatus status) override;
   void SetSearchEngineIsGoogle(bool is_google) override;
   void UpdateSearchBox(const std::u16string& text,
@@ -73,8 +71,6 @@
   // Methods only for visiting Chrome items that never talk to ash.
   ChromeAppListItem* AddChromeItem(std::unique_ptr<ChromeAppListItem> app_item);
   void RemoveChromeItem(const std::string& id);
-  void MoveChromeItemToFolder(const std::string& id,
-                              const std::string& folder_id);
 
   // Methods for item querying.
   ChromeAppListItem* FindItem(const std::string& id) override;
diff --git a/chrome/browser/ui/app_list/search/ranking/persistent_proto.h b/chrome/browser/ui/app_list/search/ranking/persistent_proto.h
index 9e72044..9f836b7 100644
--- a/chrome/browser/ui/app_list/search/ranking/persistent_proto.h
+++ b/chrome/browser/ui/app_list/search/ranking/persistent_proto.h
@@ -81,7 +81,7 @@
 
 }  // namespace
 
-// PersistentProto wraps a proto class and persists it to disk. Usage summary.
+// PersistentProto wraps a proto class and persists it to disk. Usage summary:
 //  - Init is asynchronous, usage before |on_read| is called will crash.
 //  - pproto->Method() will call Method on the underlying proto.
 //  - Call QueueWrite() to write to disk.
diff --git a/chrome/browser/ui/app_list/search/ranking/persistent_proto_unittest.cc b/chrome/browser/ui/app_list/search/ranking/persistent_proto_unittest.cc
index a6f1c77..45d81bbf 100644
--- a/chrome/browser/ui/app_list/search/ranking/persistent_proto_unittest.cc
+++ b/chrome/browser/ui/app_list/search/ranking/persistent_proto_unittest.cc
@@ -106,7 +106,9 @@
   PersistentProto<TestProto> pproto;
   pproto.Init(GetPath(), WriteDelay(), ReadCallback(), WriteCallback());
   EXPECT_EQ(pproto.get(), nullptr);
+  EXPECT_FALSE(pproto.initialized());
   Wait();
+  EXPECT_TRUE(pproto.initialized());
   EXPECT_NE(pproto.get(), nullptr);
 }
 
@@ -136,8 +138,37 @@
   EXPECT_EQ(val.value(), 1);
 }
 
-// Test that the pproto correctly saves the in-memory proto to disk.
+// Test that the pproto correctly loads an on-disk proto into memory.
 TEST_F(PersistentProtoTest, Read) {
+  const auto test_proto = MakeTestProto();
+  WriteToDisk(test_proto);
+
+  PersistentProto<TestProto> pproto;
+  pproto.Init(GetPath(), WriteDelay(), ReadCallback(), WriteCallback());
+  EXPECT_EQ(pproto.get(), nullptr);
+
+  Wait();
+  EXPECT_EQ(read_status_, ReadStatus::kOk);
+  EXPECT_EQ(read_count_, 1);
+  EXPECT_EQ(write_count_, 0);
+  EXPECT_NE(pproto.get(), nullptr);
+  EXPECT_TRUE(ProtoEquals(pproto.get(), &test_proto));
+}
+
+// Test that invalid files on disk are handled correctly.
+TEST_F(PersistentProtoTest, ReadInvalidProto) {
+  ASSERT_TRUE(base::WriteFile(GetPath(), "this isn't a valid proto"));
+
+  PersistentProto<TestProto> pproto;
+  pproto.Init(GetPath(), WriteDelay(), ReadCallback(), WriteCallback());
+  Wait();
+  EXPECT_EQ(read_status_, ReadStatus::kParseError);
+  EXPECT_EQ(read_count_, 1);
+  EXPECT_EQ(write_count_, 1);
+}
+
+// Test that the pproto correctly saves the in-memory proto to disk.
+TEST_F(PersistentProtoTest, Write) {
   PersistentProto<TestProto> pproto;
   pproto.Init(GetPath(), WriteDelay(), ReadCallback(), WriteCallback());
   // Underlying proto should be nullptr until read is complete.
@@ -157,35 +188,6 @@
   EXPECT_TRUE(ProtoEquals(&written, pproto.get()));
 }
 
-// Test that invalid files on disk are handled correctly.
-TEST_F(PersistentProtoTest, ReadInvalidProto) {
-  ASSERT_TRUE(base::WriteFile(GetPath(), "this isn't a valid proto"));
-
-  PersistentProto<TestProto> pproto;
-  pproto.Init(GetPath(), WriteDelay(), ReadCallback(), WriteCallback());
-  Wait();
-  EXPECT_EQ(read_status_, ReadStatus::kParseError);
-  EXPECT_EQ(read_count_, 1);
-  EXPECT_EQ(write_count_, 1);
-}
-
-// Test that the pproto correctly loads an on-disk proto into memory.
-TEST_F(PersistentProtoTest, Write) {
-  const auto test_proto = MakeTestProto();
-  WriteToDisk(test_proto);
-
-  PersistentProto<TestProto> pproto;
-  pproto.Init(GetPath(), WriteDelay(), ReadCallback(), WriteCallback());
-  EXPECT_EQ(pproto.get(), nullptr);
-
-  Wait();
-  EXPECT_EQ(read_status_, ReadStatus::kOk);
-  EXPECT_EQ(read_count_, 1);
-  EXPECT_EQ(write_count_, 0);
-  EXPECT_NE(pproto.get(), nullptr);
-  EXPECT_TRUE(ProtoEquals(pproto.get(), &test_proto));
-}
-
 // Test that several saves all happen correctly.
 TEST_F(PersistentProtoTest, MultipleWrites) {
   PersistentProto<TestProto> pproto;
@@ -229,4 +231,28 @@
   EXPECT_EQ(write_count_, 1);
 }
 
+// Test that a call to Purge deletes a proto from memory and disk.
+TEST_F(PersistentProtoTest, Purge) {
+  WriteToDisk(MakeTestProto());
+
+  PersistentProto<TestProto> pproto;
+  pproto.Init(GetPath(), WriteDelay(), ReadCallback(), WriteCallback());
+  Wait();
+
+  // Values read from disk.
+  EXPECT_TRUE(pproto);
+  EXPECT_EQ(pproto->value(), 12345);
+
+  pproto.Purge();
+
+  // The backing proto should now be initialized but blank.
+  EXPECT_TRUE(pproto);
+  EXPECT_FALSE(pproto->has_value());
+
+  // The on-disk proto should have also been replaced with a blank copy after
+  // writes have been completed.
+  Wait();
+  EXPECT_FALSE(ReadFromDisk().has_value());
+}
+
 }  // namespace app_list
diff --git a/chrome/browser/ui/app_list/test/fake_app_list_model_updater.cc b/chrome/browser/ui/app_list/test/fake_app_list_model_updater.cc
index 61016ff2..aa351e590 100644
--- a/chrome/browser/ui/app_list/test/fake_app_list_model_updater.cc
+++ b/chrome/browser/ui/app_list/test/fake_app_list_model_updater.cc
@@ -54,18 +54,6 @@
   RemoveItem(id);
 }
 
-void FakeAppListModelUpdater::MoveItemToFolder(const std::string& id,
-                                               const std::string& folder_id) {
-  size_t index;
-  if (FindItemIndexForTest(id, &index)) {
-    ChromeAppListItem* item = items_[index].get();
-    ChromeAppListItem::TestApi test_api(item);
-    test_api.SetFolderId(folder_id);
-    for (AppListModelUpdaterObserver& observer : observers_)
-      observer.OnAppListItemUpdated(item);
-  }
-}
-
 void FakeAppListModelUpdater::SetItemIcon(const std::string& id,
                                           const gfx::ImageSkia& icon) {
   ++update_image_count_;
@@ -77,7 +65,10 @@
 
 void FakeAppListModelUpdater::SetItemFolderId(const std::string& id,
                                               const std::string& folder_id) {
-  FindItem(id)->SetFolderId(folder_id);
+  ChromeAppListItem* item = FindItem(id);
+  item->SetFolderId(folder_id);
+  for (AppListModelUpdaterObserver& observer : observers_)
+    observer.OnAppListItemUpdated(item);
 }
 
 void FakeAppListModelUpdater::SetSearchEngineIsGoogle(bool is_google) {
@@ -228,7 +219,7 @@
   if (update_folder && chrome_item->folder_id() != sync_item->parent_id) {
     VLOG(2) << " Moving Item To Folder: " << sync_item->parent_id;
     // This updates the folder in both chrome and ash:
-    MoveItemToFolder(chrome_item->id(), sync_item->parent_id);
+    SetItemFolderId(chrome_item->id(), sync_item->parent_id);
   }
 }
 
diff --git a/chrome/browser/ui/app_list/test/fake_app_list_model_updater.h b/chrome/browser/ui/app_list/test/fake_app_list_model_updater.h
index 7098e16..a3d668f 100644
--- a/chrome/browser/ui/app_list/test/fake_app_list_model_updater.h
+++ b/chrome/browser/ui/app_list/test/fake_app_list_model_updater.h
@@ -38,8 +38,6 @@
       bool update_folder) override;
   void RemoveItem(const std::string& id) override;
   void RemoveUninstalledItem(const std::string& id) override;
-  void MoveItemToFolder(const std::string& id,
-                        const std::string& folder_id) override;
   void SetItemIcon(const std::string& id, const gfx::ImageSkia& icon) override;
   void SetItemFolderId(const std::string& id,
                        const std::string& folder_id) override;
diff --git a/chrome/browser/ui/ash/capture_mode/chrome_capture_mode_delegate.cc b/chrome/browser/ui/ash/capture_mode/chrome_capture_mode_delegate.cc
index 5cadfe6..ea606c74 100644
--- a/chrome/browser/ui/ash/capture_mode/chrome_capture_mode_delegate.cc
+++ b/chrome/browser/ui/ash/capture_mode/chrome_capture_mode_delegate.cc
@@ -27,6 +27,7 @@
 #include "chromeos/login/login_state/login_state.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/audio_service.h"
+#include "content/public/browser/download_manager.h"
 #include "content/public/browser/service_process_host.h"
 #include "ui/aura/window.h"
 #include "ui/base/window_open_disposition.h"
@@ -76,22 +77,27 @@
     std::move(interrupt_video_recording_callback_).Run();
 }
 
-base::FilePath ChromeCaptureModeDelegate::GetScreenCaptureDir() const {
-  if (chromeos::LoginState::Get()->IsUserLoggedIn()) {
-    DownloadPrefs* download_prefs = DownloadPrefs::FromBrowserContext(
-        ProfileManager::GetActiveUserProfile());
-    // We use the default downloads directory instead of the one that can be
-    // configured from the browser's settings, since it can point to an invalid
-    // location, which the browser handles by prompting the user to select
-    // another one when accessed, but Capture Mode doesn't have this capability.
-    // We also decided that this browser setting should not affect when the OS
-    // saves the captured files. https://crbug.com/1192406.
-    return download_prefs->GetDefaultDownloadDirectoryForProfile();
+base::FilePath ChromeCaptureModeDelegate::GetUserDefaultDownloadsFolder()
+    const {
+  DCHECK(chromeos::LoginState::Get()->IsUserLoggedIn());
+
+  auto* profile = ProfileManager::GetActiveUserProfile();
+  DCHECK(profile);
+  if (!profile->GetDownloadManager()->GetBrowserContext()) {
+    // Some browser tests use a |content::MockDownloadManager| which doesn't
+    // have a browser context. In this case, just return an empty path.
+    return base::FilePath();
   }
-  base::FilePath tmp_dir;
-  if (!base::GetTempDir(&tmp_dir))
-    LOG(ERROR) << "Failed to find temporary directory.";
-  return tmp_dir;
+
+  DownloadPrefs* download_prefs =
+      DownloadPrefs::FromBrowserContext(ProfileManager::GetActiveUserProfile());
+  // We use the default downloads directory instead of the one that can be
+  // configured from the browser's settings, since it can point to an invalid
+  // location, which the browser handles by prompting the user to select
+  // another one when accessed, but Capture Mode doesn't have this capability.
+  // We also decided that this browser setting should not affect where the OS
+  // saves the captured files. https://crbug.com/1192406.
+  return download_prefs->GetDefaultDownloadDirectoryForProfile();
 }
 
 void ChromeCaptureModeDelegate::ShowScreenCaptureItemInFolder(
diff --git a/chrome/browser/ui/ash/capture_mode/chrome_capture_mode_delegate.h b/chrome/browser/ui/ash/capture_mode/chrome_capture_mode_delegate.h
index 4b171f5..50927ea 100644
--- a/chrome/browser/ui/ash/capture_mode/chrome_capture_mode_delegate.h
+++ b/chrome/browser/ui/ash/capture_mode/chrome_capture_mode_delegate.h
@@ -31,7 +31,7 @@
   void InterruptVideoRecordingIfAny();
 
   // ash::CaptureModeDelegate:
-  base::FilePath GetScreenCaptureDir() const override;
+  base::FilePath GetUserDefaultDownloadsFolder() const override;
   void ShowScreenCaptureItemInFolder(const base::FilePath& file_path) override;
   void OpenScreenshotInImageEditor(const base::FilePath& file_path) override;
   bool Uses24HourFormat() const override;
diff --git a/chrome/browser/ui/ash/capture_mode/recording_service_browsertest.cc b/chrome/browser/ui/ash/capture_mode/recording_service_browsertest.cc
index 637fe09..a702e21 100644
--- a/chrome/browser/ui/ash/capture_mode/recording_service_browsertest.cc
+++ b/chrome/browser/ui/ash/capture_mode/recording_service_browsertest.cc
@@ -321,7 +321,7 @@
   // by Capture Mode.
   EXPECT_EQ(invalid_path, download_prefs->DownloadPath());
   EXPECT_NE(invalid_path,
-            ChromeCaptureModeDelegate::Get()->GetScreenCaptureDir());
+            ChromeCaptureModeDelegate::Get()->GetUserDefaultDownloadsFolder());
   ash::CaptureModeTestApi test_api;
   test_api.StartForFullscreen(/*for_video=*/true);
   FinishVideoRecordingTest(&test_api);
diff --git a/chrome/browser/ui/ash/ime_controller_client_impl.cc b/chrome/browser/ui/ash/ime_controller_client_impl.cc
index 48375d7..f9990a5 100644
--- a/chrome/browser/ui/ash/ime_controller_client_impl.cc
+++ b/chrome/browser/ui/ash/ime_controller_client_impl.cc
@@ -225,9 +225,9 @@
   const std::string current_ime_id = state->GetCurrentInputMethod().id();
 
   std::vector<ash::ImeInfo> available_imes;
-  std::unique_ptr<std::vector<InputMethodDescriptor>>
-      available_ime_descriptors = state->GetActiveInputMethods();
-  for (const InputMethodDescriptor& descriptor : *available_ime_descriptors) {
+  std::unique_ptr<std::vector<InputMethodDescriptor>> enabled_ime_descriptors =
+      state->GetEnabledInputMethods();
+  for (const InputMethodDescriptor& descriptor : *enabled_ime_descriptors) {
     ash::ImeInfo info = GetAshImeInfo(descriptor);
     available_imes.push_back(std::move(info));
   }
diff --git a/chrome/browser/ui/ash/ime_controller_client_impl_unittest.cc b/chrome/browser/ui/ash/ime_controller_client_impl_unittest.cc
index d60a8e9..0eecd729 100644
--- a/chrome/browser/ui/ash/ime_controller_client_impl_unittest.cc
+++ b/chrome/browser/ui/ash/ime_controller_client_impl_unittest.cc
@@ -65,7 +65,7 @@
       current_ime_id_ = input_method_id;
       last_show_message_ = show_message;
     }
-    std::unique_ptr<std::vector<InputMethodDescriptor>> GetActiveInputMethods()
+    std::unique_ptr<std::vector<InputMethodDescriptor>> GetEnabledInputMethods()
         const override {
       return std::make_unique<std::vector<InputMethodDescriptor>>(
           input_methods_);
diff --git a/chrome/browser/ui/ash/shelf/app_service/app_service_app_window_arc_tracker.cc b/chrome/browser/ui/ash/shelf/app_service/app_service_app_window_arc_tracker.cc
index 5936714..d45f76ea 100644
--- a/chrome/browser/ui/ash/shelf/app_service/app_service_app_window_arc_tracker.cc
+++ b/chrome/browser/ui/ash/shelf/app_service/app_service_app_window_arc_tracker.cc
@@ -18,8 +18,8 @@
 #include "chrome/browser/apps/app_service/app_icon_factory.h"
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
+#include "chrome/browser/ash/app_restore/app_restore_arc_task_handler.h"
 #include "chrome/browser/ash/app_restore/arc_window_handler.h"
-#include "chrome/browser/ash/app_restore/full_restore_arc_task_handler.h"
 #include "chrome/browser/ash/arc/arc_optin_uma.h"
 #include "chrome/browser/ash/arc/arc_util.h"
 #include "chrome/browser/ash/arc/session/arc_session_manager.h"
@@ -64,9 +64,8 @@
   if (arc_session_manager)
     arc_session_manager->AddObserver(this);
 
-  auto* arc_handler =
-      ash::full_restore::FullRestoreArcTaskHandler::GetForProfile(
-          observed_profile_);
+  auto* arc_handler = ash::app_restore::AppRestoreArcTaskHandler::GetForProfile(
+      observed_profile_);
   if (arc_handler)
     arc_handler->OnShelfReady();
 }
@@ -693,9 +692,8 @@
   session_id_to_arc_app_window_info_.erase(session_id);
 
   // Close the ghost window.
-  auto* arc_handler =
-      ash::full_restore::FullRestoreArcTaskHandler::GetForProfile(
-          observed_profile_);
+  auto* arc_handler = ash::app_restore::AppRestoreArcTaskHandler::GetForProfile(
+      observed_profile_);
   if (arc_handler && arc_handler->window_handler())
     arc_handler->window_handler()->CloseWindow(session_id);
 }
diff --git a/chrome/browser/ui/ash/shelf/arc_shelf_spinner_item_controller.cc b/chrome/browser/ui/ash/shelf/arc_shelf_spinner_item_controller.cc
index b4bcce5..de44e306 100644
--- a/chrome/browser/ui/ash/shelf/arc_shelf_spinner_item_controller.cc
+++ b/chrome/browser/ui/ash/shelf/arc_shelf_spinner_item_controller.cc
@@ -4,8 +4,8 @@
 
 #include "chrome/browser/ui/ash/shelf/arc_shelf_spinner_item_controller.h"
 
+#include "chrome/browser/ash/app_restore/app_restore_arc_task_handler.h"
 #include "chrome/browser/ash/app_restore/arc_app_launch_handler.h"
-#include "chrome/browser/ash/app_restore/full_restore_arc_task_handler.h"
 #include "chrome/browser/ash/arc/session/arc_session_manager.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
@@ -55,8 +55,7 @@
   if (window_info_ &&
       window_info_->window_id >
           full_restore::kArcSessionIdOffsetForRestoredLaunching) {
-    ash::full_restore::FullRestoreArcTaskHandler::GetForProfile(
-        observed_profile_)
+    ash::app_restore::AppRestoreArcTaskHandler::GetForProfile(observed_profile_)
         ->arc_app_launch_handler()
         ->LaunchApp(app_id());
     std::move(callback).Run(ash::SHELF_ACTION_NEW_WINDOW_CREATED, {});
@@ -103,7 +102,7 @@
   // this item when timeout.
   if (IsCreatedByFullRestore() && !close_timer_) {
     close_timer_ = std::make_unique<base::OneShotTimer>();
-    close_timer_->Start(FROM_HERE, ash::full_restore::kStopRestoreDelay,
+    close_timer_->Start(FROM_HERE, ash::app_restore::kStopRestoreDelay,
                         base::BindOnce(&ArcShelfSpinnerItemController::Close,
                                        weak_ptr_factory_.GetWeakPtr()));
   }
diff --git a/chrome/browser/ui/autofill/payments/card_unmask_authentication_selection_dialog_controller.h b/chrome/browser/ui/autofill/payments/card_unmask_authentication_selection_dialog_controller.h
new file mode 100644
index 0000000..448113b
--- /dev/null
+++ b/chrome/browser/ui/autofill/payments/card_unmask_authentication_selection_dialog_controller.h
@@ -0,0 +1,60 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_CARD_UNMASK_AUTHENTICATION_SELECTION_DIALOG_CONTROLLER_H_
+#define CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_CARD_UNMASK_AUTHENTICATION_SELECTION_DIALOG_CONTROLLER_H_
+
+#include <string>
+
+#include "components/autofill/core/browser/payments/card_unmask_challenge_option.h"
+#include "content/public/browser/web_contents.h"
+#include "ui/views/controls/image_view.h"
+
+namespace autofill {
+
+class CardUnmaskAuthenticationSelectionDialogController {
+ public:
+  CardUnmaskAuthenticationSelectionDialogController() = default;
+  virtual ~CardUnmaskAuthenticationSelectionDialogController() = default;
+  CardUnmaskAuthenticationSelectionDialogController(
+      const CardUnmaskAuthenticationSelectionDialogController&) = delete;
+  CardUnmaskAuthenticationSelectionDialogController& operator=(
+      const CardUnmaskAuthenticationSelectionDialogController&) = delete;
+
+  // Called whenever the dialog is closed, and it sets the dialog_view_
+  // variable in this class to nullptr.
+  virtual void OnDialogClosed() = 0;
+
+  virtual std::u16string GetWindowTitle() const = 0;
+
+  virtual std::u16string GetContentHeaderText() const = 0;
+
+  // Returns the vector of challenge options for authentication
+  // (text, email, etc...). Each CardUnmaskChallengeOption* in the vector
+  // points to a struct that has the challenge option type, as well as the
+  // relevant data to send the authentication to (such as a
+  // masked phone number or masked email).
+  virtual const std::vector<CardUnmaskChallengeOption>& GetChallengeOptions()
+      const = 0;
+
+  // Returns the corresponding authentication mode icon for the given challenge
+  // option.
+  virtual ui::ImageModel GetAuthenticationModeIcon(
+      const CardUnmaskChallengeOption& challenge_option) const = 0;
+
+  // Returns the text that describes the authentication mode choice, for
+  // example: text message, email.
+  virtual std::u16string GetAuthenticationModeLabel(
+      const CardUnmaskChallengeOption& challenge_options) const = 0;
+
+  virtual std::u16string GetContentFooterText() const = 0;
+
+  virtual std::u16string GetOkButtonLabel() const = 0;
+
+  virtual content::WebContents* GetWebContents() = 0;
+};
+
+}  // namespace autofill
+
+#endif  // CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_CARD_UNMASK_AUTHENTICATION_SELECTION_DIALOG_CONTROLLER_H_
diff --git a/chrome/browser/ui/autofill/payments/card_unmask_authentication_selection_dialog_controller_impl.cc b/chrome/browser/ui/autofill/payments/card_unmask_authentication_selection_dialog_controller_impl.cc
new file mode 100644
index 0000000..3dffbf8
--- /dev/null
+++ b/chrome/browser/ui/autofill/payments/card_unmask_authentication_selection_dialog_controller_impl.cc
@@ -0,0 +1,122 @@
+// 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 "chrome/browser/ui/autofill/payments/card_unmask_authentication_selection_dialog_controller_impl.h"
+
+#include <string>
+
+#include "chrome/browser/ui/autofill/payments/card_unmask_authentication_selection_dialog_view.h"
+#include "components/autofill/core/browser/payments/card_unmask_challenge_option.h"
+#include "components/strings/grit/components_strings.h"
+#include "components/vector_icons/vector_icons.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "content/public/browser/web_contents_user_data.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/views/controls/image_view.h"
+
+namespace autofill {
+
+CardUnmaskAuthenticationSelectionDialogControllerImpl::
+    ~CardUnmaskAuthenticationSelectionDialogControllerImpl() {
+  // This part of code is executed only if browser window is closed when the
+  // dialog is visible. In this case the controller is destroyed before
+  // CardUnmaskAuthenticationSelectionDialogViewImpl::dtor() is called,
+  // but the reference to controller is not reset. Need to reset via
+  // CardUnmaskAuthenticationSelectionDialogView::CloseDialog() to avoid a
+  // crash.
+  if (dialog_view_)
+    dialog_view_->OnControllerDestroying();
+}
+
+CardUnmaskAuthenticationSelectionDialogView*
+CardUnmaskAuthenticationSelectionDialogControllerImpl::GetDialogView() {
+  return dialog_view_;
+}
+
+void CardUnmaskAuthenticationSelectionDialogControllerImpl::ShowDialog(
+    const std::vector<CardUnmaskChallengeOption>& challenge_options) {
+  if (dialog_view_)
+    return;
+
+  challenge_options_ = challenge_options;
+  dialog_view_ =
+      CardUnmaskAuthenticationSelectionDialogView::CreateAndShow(this);
+}
+
+void CardUnmaskAuthenticationSelectionDialogControllerImpl::OnDialogClosed() {
+  dialog_view_ = nullptr;
+}
+
+std::u16string
+CardUnmaskAuthenticationSelectionDialogControllerImpl::GetWindowTitle() const {
+  return l10n_util::GetStringUTF16(IDS_AUTOFILL_CARD_UNMASK_PROMPT_TITLE_V2);
+}
+
+std::u16string
+CardUnmaskAuthenticationSelectionDialogControllerImpl::GetContentHeaderText()
+    const {
+  return l10n_util::GetStringUTF16(
+      IDS_AUTOFILL_CARD_UNMASK_AUTHENTICATION_SELECTION_DIALOG_ISSUER_CONFIRMATION_TEXT);
+}
+
+const std::vector<CardUnmaskChallengeOption>&
+CardUnmaskAuthenticationSelectionDialogControllerImpl::GetChallengeOptions()
+    const {
+  return challenge_options_;
+}
+
+ui::ImageModel CardUnmaskAuthenticationSelectionDialogControllerImpl::
+    GetAuthenticationModeIcon(
+        const CardUnmaskChallengeOption& challenge_option) const {
+  switch (challenge_option.type) {
+    case CardUnmaskChallengeOptionType::kSmsOtp:
+      return ui::ImageModel::FromVectorIcon(vector_icons::kSmsIcon);
+    case CardUnmaskChallengeOptionType::kUnknownType:
+      NOTREACHED();
+      return ui::ImageModel();
+  };
+}
+
+std::u16string CardUnmaskAuthenticationSelectionDialogControllerImpl::
+    GetAuthenticationModeLabel(
+        const CardUnmaskChallengeOption& challenge_option) const {
+  switch (challenge_option.type) {
+    case CardUnmaskChallengeOptionType::kSmsOtp:
+      return l10n_util::GetStringUTF16(
+          IDS_AUTOFILL_AUTHENTICATION_MODE_TEXT_MESSAGE_LABEL);
+    case CardUnmaskChallengeOptionType::kUnknownType:
+      NOTREACHED();
+      return std::u16string();
+  }
+}
+
+std::u16string
+CardUnmaskAuthenticationSelectionDialogControllerImpl::GetContentFooterText()
+    const {
+  return l10n_util::GetStringUTF16(
+      IDS_AUTOFILL_CARD_UNMASK_AUTHENTICATION_SELECTION_DIALOG_CURRENT_INFO_NOT_SEEN_TEXT);
+}
+
+std::u16string
+CardUnmaskAuthenticationSelectionDialogControllerImpl::GetOkButtonLabel()
+    const {
+  return l10n_util::GetStringUTF16(
+      IDS_AUTOFILL_CARD_UNMASK_AUTHENTICATION_SELECTION_DIALOG_OK_BUTTON_LABEL);
+}
+
+content::WebContents*
+CardUnmaskAuthenticationSelectionDialogControllerImpl::GetWebContents() {
+  return web_contents();
+}
+
+CardUnmaskAuthenticationSelectionDialogControllerImpl::
+    CardUnmaskAuthenticationSelectionDialogControllerImpl(
+        content::WebContents* web_contents)
+    : content::WebContentsObserver(web_contents) {}
+
+WEB_CONTENTS_USER_DATA_KEY_IMPL(
+    CardUnmaskAuthenticationSelectionDialogControllerImpl)
+
+}  // namespace autofill
diff --git a/chrome/browser/ui/autofill/payments/card_unmask_authentication_selection_dialog_controller_impl.h b/chrome/browser/ui/autofill/payments/card_unmask_authentication_selection_dialog_controller_impl.h
new file mode 100644
index 0000000..f88e67f
--- /dev/null
+++ b/chrome/browser/ui/autofill/payments/card_unmask_authentication_selection_dialog_controller_impl.h
@@ -0,0 +1,68 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_CARD_UNMASK_AUTHENTICATION_SELECTION_DIALOG_CONTROLLER_IMPL_H_
+#define CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_CARD_UNMASK_AUTHENTICATION_SELECTION_DIALOG_CONTROLLER_IMPL_H_
+
+#include <string>
+
+#include "chrome/browser/ui/autofill/payments/card_unmask_authentication_selection_dialog_controller.h"
+#include "chrome/browser/ui/autofill/payments/card_unmask_authentication_selection_dialog_view.h"
+#include "components/autofill/core/browser/payments/card_unmask_challenge_option.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "content/public/browser/web_contents_user_data.h"
+
+namespace autofill {
+
+class CardUnmaskAuthenticationSelectionDialogControllerImpl
+    : public CardUnmaskAuthenticationSelectionDialogController,
+      public content::WebContentsObserver,
+      public content::WebContentsUserData<
+          CardUnmaskAuthenticationSelectionDialogControllerImpl> {
+ public:
+  CardUnmaskAuthenticationSelectionDialogControllerImpl(
+      const CardUnmaskAuthenticationSelectionDialogControllerImpl&) = delete;
+  CardUnmaskAuthenticationSelectionDialogControllerImpl& operator=(
+      const CardUnmaskAuthenticationSelectionDialogControllerImpl&) = delete;
+  ~CardUnmaskAuthenticationSelectionDialogControllerImpl() override;
+
+  CardUnmaskAuthenticationSelectionDialogView* GetDialogView();
+
+  void ShowDialog(
+      const std::vector<CardUnmaskChallengeOption>& challenge_options);
+
+  // CardUnmaskAuthenticationSelectionDialogController:
+  void OnDialogClosed() override;
+  std::u16string GetWindowTitle() const override;
+  std::u16string GetContentHeaderText() const override;
+  const std::vector<CardUnmaskChallengeOption>& GetChallengeOptions()
+      const override;
+  ui::ImageModel GetAuthenticationModeIcon(
+      const CardUnmaskChallengeOption& challenge_option) const override;
+  std::u16string GetAuthenticationModeLabel(
+      const CardUnmaskChallengeOption& challenge_option) const override;
+  std::u16string GetContentFooterText() const override;
+  std::u16string GetOkButtonLabel() const override;
+  content::WebContents* GetWebContents() override;
+
+ protected:
+  explicit CardUnmaskAuthenticationSelectionDialogControllerImpl(
+      content::WebContents* web_contents);
+
+ private:
+  friend class content::WebContentsUserData<
+      CardUnmaskAuthenticationSelectionDialogControllerImpl>;
+
+  // Contains all of the challenge options an issuer has for the user.
+  std::vector<CardUnmaskChallengeOption> challenge_options_;
+
+  CardUnmaskAuthenticationSelectionDialogView* dialog_view_ = nullptr;
+
+  WEB_CONTENTS_USER_DATA_KEY_DECL();
+};
+
+}  // namespace autofill
+
+#endif  // CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_CARD_UNMASK_AUTHENTICATION_SELECTION_DIALOG_CONTROLLER_IMPL_H_
diff --git a/chrome/browser/ui/autofill/payments/card_unmask_authentication_selection_dialog_view.h b/chrome/browser/ui/autofill/payments/card_unmask_authentication_selection_dialog_view.h
new file mode 100644
index 0000000..036c5bf
--- /dev/null
+++ b/chrome/browser/ui/autofill/payments/card_unmask_authentication_selection_dialog_view.h
@@ -0,0 +1,26 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_CARD_UNMASK_AUTHENTICATION_SELECTION_DIALOG_VIEW_H_
+#define CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_CARD_UNMASK_AUTHENTICATION_SELECTION_DIALOG_VIEW_H_
+
+namespace autofill {
+
+class CardUnmaskAuthenticationSelectionDialogController;
+
+class CardUnmaskAuthenticationSelectionDialogView {
+ public:
+  // Creates a dialog and displays it as a modal on top of the web contents of
+  // CardUnmaskAuthenticationSelectionDialogController.
+  static CardUnmaskAuthenticationSelectionDialogView* CreateAndShow(
+      CardUnmaskAuthenticationSelectionDialogController* controller);
+
+  // Method to safely close this dialog when the controller is destroyed by
+  // unlinking the controller and closing the widget that owns this dialog view.
+  virtual void OnControllerDestroying() = 0;
+};
+
+}  // namespace autofill
+
+#endif  // CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_CARD_UNMASK_AUTHENTICATION_SELECTION_DIALOG_VIEW_H_
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h
index 7649c59..599a8223 100644
--- a/chrome/browser/ui/browser.h
+++ b/chrome/browser/ui/browser.h
@@ -679,6 +679,9 @@
   void MediaWatchTimeChanged(
       const content::MediaPlayerWatchTime& watch_time) override;
   base::WeakPtr<content::WebContentsDelegate> GetDelegateWeakPtr() override;
+  std::unique_ptr<content::EyeDropper> OpenEyeDropper(
+      content::RenderFrameHost* frame,
+      content::EyeDropperListener* listener) override;
 
   bool is_type_normal() const { return type_ == TYPE_NORMAL; }
   bool is_type_popup() const { return type_ == TYPE_POPUP; }
@@ -840,9 +843,6 @@
   content::JavaScriptDialogManager* GetJavaScriptDialogManager(
       content::WebContents* source) override;
   bool GuestSaveFrame(content::WebContents* guest_web_contents) override;
-  std::unique_ptr<content::EyeDropper> OpenEyeDropper(
-      content::RenderFrameHost* frame,
-      content::EyeDropperListener* listener) override;
   void RunFileChooser(content::RenderFrameHost* render_frame_host,
                       scoped_refptr<content::FileSelectListener> listener,
                       const blink::mojom::FileChooserParams& params) override;
diff --git a/chrome/browser/ui/browser_window.h b/chrome/browser/ui/browser_window.h
index 68019b2..904f7d8 100644
--- a/chrome/browser/ui/browser_window.h
+++ b/chrome/browser/ui/browser_window.h
@@ -404,7 +404,8 @@
   ShowQRCodeGeneratorBubble(
       content::WebContents* contents,
       qrcode_generator::QRCodeGeneratorBubbleController* controller,
-      const GURL& url) = 0;
+      const GURL& url,
+      bool show_back_button) = 0;
 
   // Shows the "send tab to self" bubble.
   virtual send_tab_to_self::SendTabToSelfBubbleView* ShowSendTabToSelfBubble(
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller_interactive_browsertest.cc b/chrome/browser/ui/exclusive_access/fullscreen_controller_interactive_browsertest.cc
index c362031..fe49cd7 100644
--- a/chrome/browser/ui/exclusive_access/fullscreen_controller_interactive_browsertest.cc
+++ b/chrome/browser/ui/exclusive_access/fullscreen_controller_interactive_browsertest.cc
@@ -197,9 +197,15 @@
   ASSERT_NO_FATAL_FAILURE(ToggleTabFullscreen(false));
 }
 
+// Test is flaky on Lacros: https://crbug.com/1250091
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+#define MAYBE_BrowserFullscreenExit DISABLED_BrowserFullscreenExit
+#else
+#define MAYBE_BrowserFullscreenExit BrowserFullscreenExit
+#endif
 // Tests Fullscreen entered in Browser, then Tab mode, then exited via Browser.
 IN_PROC_BROWSER_TEST_F(FullscreenControllerInteractiveTest,
-                       BrowserFullscreenExit) {
+                       MAYBE_BrowserFullscreenExit) {
   // Enter browser fullscreen.
   ASSERT_NO_FATAL_FAILURE(ToggleBrowserFullscreen(true));
 
@@ -212,9 +218,16 @@
   ASSERT_FALSE(browser()->window()->IsFullscreen());
 }
 
+// Test is flaky on Lacros: https://crbug.com/1250092
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+#define MAYBE_BrowserFullscreenAfterTabFSExit \
+  DISABLED_BrowserFullscreenAfterTabFSExit
+#else
+#define MAYBE_BrowserFullscreenAfterTabFSExit BrowserFullscreenAfterTabFSExit
+#endif
 // Tests Browser Fullscreen remains active after Tab mode entered and exited.
 IN_PROC_BROWSER_TEST_F(FullscreenControllerInteractiveTest,
-                       BrowserFullscreenAfterTabFSExit) {
+                       MAYBE_BrowserFullscreenAfterTabFSExit) {
   // Enter browser fullscreen.
   ASSERT_NO_FATAL_FAILURE(ToggleBrowserFullscreen(true));
 
@@ -301,8 +314,8 @@
   ASSERT_FALSE(IsWindowFullscreenForTabOrPending());
 }
 
-// TODO(crbug.com/1230771) Flaky on Linux-ozone
-#if defined(OS_LINUX) && defined(USE_OZONE)
+// TODO(crbug.com/1230771) Flaky on Linux-ozone and Lacros
+#if (defined(OS_LINUX) && defined(USE_OZONE)) || BUILDFLAG(IS_CHROMEOS_LACROS)
 #define MAYBE_TabEntersPresentationModeFromWindowed \
   DISABLED_TabEntersPresentationModeFromWindowed
 #else
@@ -998,8 +1011,7 @@
       };
     })();
   )";
-  EXPECT_TRUE(ExecJs(tab, request_fullscreen_script,
-                     content::EXECUTE_SCRIPT_NO_USER_GESTURE));
+  EXPECT_TRUE(ExecJs(tab, request_fullscreen_script));
   EXPECT_FALSE(browser()->window()->IsFullscreen());
   WaitForUserActivationExpiry();
 
@@ -1024,25 +1036,29 @@
 #if defined(OS_WIN)
 #define MAYBE_FullscreenOnPermissionGrant DISABLED_FullscreenOnPermissionGrant
 #else
-// TODO(crbug.com/1246649): flakes on other bots.
-#define MAYBE_FullscreenOnPermissionGrant DISABLED_FullscreenOnPermissionGrant
+#define MAYBE_FullscreenOnPermissionGrant FullscreenOnPermissionGrant
 #endif
-// Test requesting fullscreen using the permission grant's transient affordance.
+// Test requesting fullscreen using the permission grant's transient activation.
 IN_PROC_BROWSER_TEST_F(ExperimentalFullscreenControllerInteractiveTest,
                        MAYBE_FullscreenOnPermissionGrant) {
-  SetUpTestScreenAndWindowPlacementTab();
+  EXPECT_TRUE(embedded_test_server()->Start());
+  const GURL url(embedded_test_server()->GetURL("/simple.html"));
+  AddTabAtIndex(1, url, PAGE_TRANSITION_TYPED);
+  auto* tab = browser()->tab_strip_model()->GetActiveWebContents();
 
-  // Request and auto-accept the Window Placement permission, this should grant
-  // a transient affordance that can be used to request fullscreen.
+  permissions::PermissionRequestManager* permission_request_manager =
+      permissions::PermissionRequestManager::FromWebContents(tab);
+
+  // Request the Window Placement permission and accept the prompt after user
+  // activation expires; accepting should grant a new transient activation
+  // signal that can be used to request fullscreen, without another gesture.
+  ExecuteScriptAsync(tab, "getScreens()");
+  WaitForUserActivationExpiry();
+  ASSERT_TRUE(permission_request_manager->IsRequestInProgress());
+  permission_request_manager->Accept();
   const std::string request_fullscreen_from_prompt_script = R"(
     (async () => {
-      if (navigator.userActivation.isActive)
-        return false;
-      window.screensInterface = await window.getScreens();
-      if (!navigator.userActivation.isActive || !!document.fullscreenElement)
-        return false;
-      const options = { screen: window.screensInterface.screens[1] };
-      await document.body.requestFullscreen(options);
+      await document.body.requestFullscreen();
       return !!document.fullscreenElement;
     })();
   )";
diff --git a/chrome/browser/ui/qrcode_generator/qrcode_generator_bubble_controller.cc b/chrome/browser/ui/qrcode_generator/qrcode_generator_bubble_controller.cc
index 7b2424d3..006c34d 100644
--- a/chrome/browser/ui/qrcode_generator/qrcode_generator_bubble_controller.cc
+++ b/chrome/browser/ui/qrcode_generator/qrcode_generator_bubble_controller.cc
@@ -10,6 +10,7 @@
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/qrcode_generator/qrcode_generator_bubble_view.h"
+#include "chrome/browser/ui/sharing_hub/sharing_hub_bubble_controller.h"
 #include "chrome/grit/generated_resources.h"
 #include "content/public/browser/web_contents.h"
 #include "url/gurl.h"
@@ -37,11 +38,12 @@
   return controller;
 }
 
-void QRCodeGeneratorBubbleController::ShowBubble(const GURL& url) {
+void QRCodeGeneratorBubbleController::ShowBubble(const GURL& url,
+                                                 bool show_back_button) {
   bubble_shown_ = true;
   Browser* browser = chrome::FindBrowserWithWebContents(web_contents_);
-  qrcode_generator_bubble_ =
-      browser->window()->ShowQRCodeGeneratorBubble(web_contents_, this, url);
+  qrcode_generator_bubble_ = browser->window()->ShowQRCodeGeneratorBubble(
+      web_contents_, this, url, show_back_button);
 
   UpdateIcon();
 }
@@ -68,6 +70,13 @@
   }
 }
 
+void QRCodeGeneratorBubbleController::OnBackButtonPressed() {
+  sharing_hub::SharingHubBubbleController* controller =
+      sharing_hub::SharingHubBubbleController::CreateOrGetFromWebContents(
+          web_contents_);
+  controller->ShowBubble();
+}
+
 void QRCodeGeneratorBubbleController::UpdateIcon() {
   Browser* browser = chrome::FindBrowserWithWebContents(web_contents_);
   // UpdateIcon() can be called during browser teardown.
diff --git a/chrome/browser/ui/qrcode_generator/qrcode_generator_bubble_controller.h b/chrome/browser/ui/qrcode_generator/qrcode_generator_bubble_controller.h
index 62dd71c..7e0f6ca0 100644
--- a/chrome/browser/ui/qrcode_generator/qrcode_generator_bubble_controller.h
+++ b/chrome/browser/ui/qrcode_generator/qrcode_generator_bubble_controller.h
@@ -37,7 +37,7 @@
       content::WebContents* web_contents);
 
   // Displays the QR Code Generator bubble.
-  void ShowBubble(const GURL& url);
+  void ShowBubble(const GURL& url, bool show_back_button = false);
 
   // Hides the QR Code Generator bubble.
   void HideBubble();
@@ -50,6 +50,8 @@
   // Handler for when the bubble is dismissed.
   void OnBubbleClosed();
 
+  void OnBackButtonPressed();
+
  protected:
   explicit QRCodeGeneratorBubbleController(content::WebContents* web_contents);
 
diff --git a/chrome/browser/ui/send_tab_to_self/send_tab_to_self_bubble_controller.cc b/chrome/browser/ui/send_tab_to_self/send_tab_to_self_bubble_controller.cc
index 8fe2650..2b59baa 100644
--- a/chrome/browser/ui/send_tab_to_self/send_tab_to_self_bubble_controller.cc
+++ b/chrome/browser/ui/send_tab_to_self/send_tab_to_self_bubble_controller.cc
@@ -16,6 +16,7 @@
 #include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/send_tab_to_self/send_tab_to_self_bubble_view.h"
+#include "chrome/browser/ui/sharing_hub/sharing_hub_bubble_controller.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/pref_registry/pref_registry_syncable.h"
@@ -56,7 +57,8 @@
   }
 }
 
-void SendTabToSelfBubbleController::ShowBubble() {
+void SendTabToSelfBubbleController::ShowBubble(bool show_back_button) {
+  show_back_button_ = show_back_button;
   bubble_shown_ = true;
   Browser* browser = chrome::FindBrowserWithWebContents(web_contents_);
   send_tab_to_self_bubble_view_ =
@@ -129,6 +131,15 @@
   }
 }
 
+void SendTabToSelfBubbleController::OnBackButtonPressed() {
+  sharing_hub::SharingHubBubbleController* controller =
+      sharing_hub::SharingHubBubbleController::CreateOrGetFromWebContents(
+          web_contents_);
+  controller->ShowBubble();
+
+  UpdateIcon();
+}
+
 void SendTabToSelfBubbleController::ShowConfirmationMessage() {
   show_message_ = true;
   UpdateIcon();
diff --git a/chrome/browser/ui/send_tab_to_self/send_tab_to_self_bubble_controller.h b/chrome/browser/ui/send_tab_to_self/send_tab_to_self_bubble_controller.h
index c3ff4d6..7c47ad7 100644
--- a/chrome/browser/ui/send_tab_to_self/send_tab_to_self_bubble_controller.h
+++ b/chrome/browser/ui/send_tab_to_self/send_tab_to_self_bubble_controller.h
@@ -48,7 +48,7 @@
   // Hides send tab to self bubble.
   void HideBubble();
   // Displays send tab to self bubble.
-  void ShowBubble();
+  void ShowBubble(bool show_back_button = false);
 
   bool IsBubbleShown() { return bubble_shown_; }
 
@@ -68,9 +68,12 @@
   // Handler for when user clicks the link to manage their available devices.
   void OnManageDevicesClicked(const ui::Event& event);
 
-  // Close the bubble when the user click on the close button.
+  // Close the bubble when the user clicks on the close button.
   void OnBubbleClosed();
 
+  // Close the bubble when the user clicks on the back button.
+  void OnBackButtonPressed();
+
   // Shows the confirmation message in the omnibox.
   void ShowConfirmationMessage();
 
@@ -79,6 +82,7 @@
   bool InitialSendAnimationShown() const;
   void SetInitialSendAnimationShown(bool shown);
 
+  bool show_back_button() const { return show_back_button_; }
   bool show_message() const { return show_message_; }
   void set_show_message(bool show_message) { show_message_ = show_message; }
 
@@ -104,6 +108,8 @@
   content::WebContents* web_contents_;
   // Weak reference. Will be nullptr if no bubble is currently shown.
   SendTabToSelfBubbleView* send_tab_to_self_bubble_view_ = nullptr;
+  // True if the back button is currently shown.
+  bool show_back_button_ = false;
   // True if a confirmation message should be shown in the omnibox.
   bool show_message_ = false;
   // True if the bubble is currently shown.
diff --git a/chrome/browser/ui/sharing_hub/sharing_hub_bubble_controller.cc b/chrome/browser/ui/sharing_hub/sharing_hub_bubble_controller.cc
index 885ff33..a56c4e4 100644
--- a/chrome/browser/ui/sharing_hub/sharing_hub_bubble_controller.cc
+++ b/chrome/browser/ui/sharing_hub/sharing_hub_bubble_controller.cc
@@ -7,6 +7,7 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
 #include "base/strings/utf_string_conversions.h"
+#include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sharesheet/sharesheet_metrics.h"
 #include "chrome/browser/sharesheet/sharesheet_service.h"
@@ -19,6 +20,8 @@
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/qrcode_generator/qrcode_generator_bubble_controller.h"
+#include "chrome/browser/ui/send_tab_to_self/send_tab_to_self_bubble_controller.h"
 #include "chrome/browser/ui/sharing_hub/sharing_hub_bubble_view.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/grit/generated_resources.h"
@@ -183,7 +186,21 @@
 
   if (is_first_party) {
     base::RecordComputedAction(feature_name_for_metrics);
-    chrome::ExecuteCommand(browser, command_id);
+
+    // Show a back button for 1P dialogs anchored to the sharing hub icon.
+    if (command_id == IDC_QRCODE_GENERATOR) {
+      qrcode_generator::QRCodeGeneratorBubbleController* qrcode_controller =
+          qrcode_generator::QRCodeGeneratorBubbleController::Get(web_contents_);
+      qrcode_controller->ShowBubble(web_contents_->GetURL(), true);
+    } else if (command_id == IDC_SEND_TAB_TO_SELF) {
+      send_tab_to_self::SendTabToSelfBubbleController*
+          send_tab_to_self_controller =
+              send_tab_to_self::SendTabToSelfBubbleController::
+                  CreateOrGetFromWebContents(web_contents_);
+      send_tab_to_self_controller->ShowBubble(true);
+    } else {
+      chrome::ExecuteCommand(browser, command_id);
+    }
   } else {
     SharingHubModel* model = GetSharingHubModel();
     DCHECK(model);
diff --git a/chrome/browser/ui/side_search/side_search_side_contents_helper.cc b/chrome/browser/ui/side_search/side_search_side_contents_helper.cc
index 3dbbdfb..982f214 100644
--- a/chrome/browser/ui/side_search/side_search_side_contents_helper.cc
+++ b/chrome/browser/ui/side_search/side_search_side_contents_helper.cc
@@ -68,7 +68,22 @@
 
 }  // namespace
 
-SideSearchSideContentsHelper::~SideSearchSideContentsHelper() = default;
+bool SideSearchSideContentsHelper::Delegate::HandleKeyboardEvent(
+    content::WebContents* source,
+    const content::NativeWebKeyboardEvent& event) {
+  return false;
+}
+
+content::WebContents* SideSearchSideContentsHelper::Delegate::OpenURLFromTab(
+    content::WebContents* source,
+    const content::OpenURLParams& params) {
+  return nullptr;
+}
+
+SideSearchSideContentsHelper::~SideSearchSideContentsHelper() {
+  if (web_contents())
+    web_contents()->SetDelegate(nullptr);
+}
 
 std::unique_ptr<content::NavigationThrottle>
 SideSearchSideContentsHelper::MaybeCreateThrottleFor(
@@ -97,6 +112,27 @@
   delegate_->LastSearchURLUpdated(url);
 }
 
+bool SideSearchSideContentsHelper::CanDragEnter(
+    content::WebContents* source,
+    const content::DropData& data,
+    blink::DragOperationsMask operations_allowed) {
+  return false;
+}
+
+bool SideSearchSideContentsHelper::HandleKeyboardEvent(
+    content::WebContents* source,
+    const content::NativeWebKeyboardEvent& event) {
+  DCHECK(delegate_);
+  return delegate_->HandleKeyboardEvent(source, event);
+}
+
+content::WebContents* SideSearchSideContentsHelper::OpenURLFromTab(
+    content::WebContents* source,
+    const content::OpenURLParams& params) {
+  DCHECK(delegate_);
+  return delegate_->OpenURLFromTab(source, params);
+}
+
 void SideSearchSideContentsHelper::NavigateInTabContents(
     const content::OpenURLParams& params) {
   DCHECK(delegate_);
@@ -141,6 +177,8 @@
   web_contents->SetRendererInitiatedUserAgentOverrideOption(
       content::NavigationController::UA_OVERRIDE_TRUE);
 #endif  // !defined(OS_CHROMEOS)
+
+  web_contents->SetDelegate(this);
 }
 
 WEB_CONTENTS_USER_DATA_KEY_IMPL(SideSearchSideContentsHelper)
diff --git a/chrome/browser/ui/side_search/side_search_side_contents_helper.h b/chrome/browser/ui/side_search/side_search_side_contents_helper.h
index d4dec40c..1b7cb413 100644
--- a/chrome/browser/ui/side_search/side_search_side_contents_helper.h
+++ b/chrome/browser/ui/side_search/side_search_side_contents_helper.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_UI_SIDE_SEARCH_SIDE_SEARCH_SIDE_CONTENTS_HELPER_H_
 #define CHROME_BROWSER_UI_SIDE_SEARCH_SIDE_SEARCH_SIDE_CONTENTS_HELPER_H_
 
+#include "content/public/browser/web_contents_delegate.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/browser/web_contents_user_data.h"
 
@@ -19,6 +20,7 @@
 // Side Search helper for the WebContents hosted in the side panel.
 class SideSearchSideContentsHelper
     : public content::WebContentsObserver,
+      public content::WebContentsDelegate,
       public content::WebContentsUserData<SideSearchSideContentsHelper> {
  public:
   class Delegate {
@@ -31,6 +33,16 @@
     // Called when the last search URL encountered by the side panel has been
     // updated.
     virtual void LastSearchURLUpdated(const GURL& url) = 0;
+
+    // Passthrough for the side content's WebContentsDelegate.
+    virtual bool HandleKeyboardEvent(
+        content::WebContents* source,
+        const content::NativeWebKeyboardEvent& event);
+
+    // Passthrough for the side content's WebContentsDelegate.
+    virtual content::WebContents* OpenURLFromTab(
+        content::WebContents* source,
+        const content::OpenURLParams& params);
   };
 
   ~SideSearchSideContentsHelper() override;
@@ -43,6 +55,17 @@
   void DidFinishNavigation(
       content::NavigationHandle* navigation_handle) override;
 
+  // content::WebContentsDelegate:
+  bool CanDragEnter(content::WebContents* source,
+                    const content::DropData& data,
+                    blink::DragOperationsMask operations_allowed) override;
+  bool HandleKeyboardEvent(
+      content::WebContents* source,
+      const content::NativeWebKeyboardEvent& event) override;
+  content::WebContents* OpenURLFromTab(
+      content::WebContents* source,
+      const content::OpenURLParams& params) override;
+
   // Navigates the associated tab contents to `url`.
   void NavigateInTabContents(const content::OpenURLParams& params);
 
diff --git a/chrome/browser/ui/side_search/side_search_tab_contents_helper.cc b/chrome/browser/ui/side_search/side_search_tab_contents_helper.cc
index 611365a..26f82d21 100644
--- a/chrome/browser/ui/side_search/side_search_tab_contents_helper.cc
+++ b/chrome/browser/ui/side_search/side_search_tab_contents_helper.cc
@@ -24,6 +24,18 @@
   last_search_url_ = url;
 }
 
+bool SideSearchTabContentsHelper::HandleKeyboardEvent(
+    content::WebContents* source,
+    const content::NativeWebKeyboardEvent& event) {
+  return delegate_ ? delegate_->HandleKeyboardEvent(source, event) : false;
+}
+
+content::WebContents* SideSearchTabContentsHelper::OpenURLFromTab(
+    content::WebContents* source,
+    const content::OpenURLParams& params) {
+  return delegate_ ? delegate_->OpenURLFromTab(source, params) : nullptr;
+}
+
 void SideSearchTabContentsHelper::DidFinishNavigation(
     content::NavigationHandle* navigation_handle) {
   if (!navigation_handle->IsInPrimaryMainFrame() ||
@@ -66,6 +78,11 @@
          url.spec() != chrome::kChromeUINewTabURL;
 }
 
+void SideSearchTabContentsHelper::SetDelegate(
+    base::WeakPtr<Delegate> delegate) {
+  delegate_ = std::move(delegate);
+}
+
 void SideSearchTabContentsHelper::SetSidePanelContentsForTesting(
     std::unique_ptr<content::WebContents> side_panel_contents) {
   side_panel_contents_ = std::move(side_panel_contents);
diff --git a/chrome/browser/ui/side_search/side_search_tab_contents_helper.h b/chrome/browser/ui/side_search/side_search_tab_contents_helper.h
index 21a1ba8a..d1356e94 100644
--- a/chrome/browser/ui/side_search/side_search_tab_contents_helper.h
+++ b/chrome/browser/ui/side_search/side_search_tab_contents_helper.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_UI_SIDE_SEARCH_SIDE_SEARCH_TAB_CONTENTS_HELPER_H_
 #define CHROME_BROWSER_UI_SIDE_SEARCH_SIDE_SEARCH_TAB_CONTENTS_HELPER_H_
 
+#include "base/memory/weak_ptr.h"
 #include "chrome/browser/ui/side_search/side_search_side_contents_helper.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/browser/web_contents_user_data.h"
@@ -22,11 +23,28 @@
       public content::WebContentsObserver,
       public content::WebContentsUserData<SideSearchTabContentsHelper> {
  public:
+  class Delegate {
+   public:
+    virtual bool HandleKeyboardEvent(
+        content::WebContents* source,
+        const content::NativeWebKeyboardEvent& event) = 0;
+
+    virtual content::WebContents* OpenURLFromTab(
+        content::WebContents* source,
+        const content::OpenURLParams& params) = 0;
+  };
+
   ~SideSearchTabContentsHelper() override;
 
   // SideContentsWrapper::Delegate:
   void NavigateInTabContents(const content::OpenURLParams& params) override;
   void LastSearchURLUpdated(const GURL& url) override;
+  bool HandleKeyboardEvent(
+      content::WebContents* source,
+      const content::NativeWebKeyboardEvent& event) override;
+  content::WebContents* OpenURLFromTab(
+      content::WebContents* source,
+      const content::OpenURLParams& params) override;
 
   // content::WebContentsObserver:
   void DidFinishNavigation(
@@ -45,6 +63,8 @@
   // navigation entry.
   bool CanShowSidePanelForCommittedNavigation();
 
+  void SetDelegate(base::WeakPtr<Delegate> delegate);
+
   bool toggled_open() const { return toggled_open_; }
   void set_toggled_open(bool toggled_open) { toggled_open_ = toggled_open; }
 
@@ -74,6 +94,10 @@
   // contents.
   void CreateSidePanelContents();
 
+  // Use a weak ptr for the delegate to avoid issues whereby the tab contents
+  // could outlive the delegate.
+  base::WeakPtr<Delegate> delegate_;
+
   // The last Google search URL encountered by this tab contents.
   absl::optional<GURL> last_search_url_;
 
diff --git a/chrome/browser/ui/views/autofill/payments/card_unmask_authentication_selection_dialog_browsertest.cc b/chrome/browser/ui/views/autofill/payments/card_unmask_authentication_selection_dialog_browsertest.cc
new file mode 100644
index 0000000..b45260cb
--- /dev/null
+++ b/chrome/browser/ui/views/autofill/payments/card_unmask_authentication_selection_dialog_browsertest.cc
@@ -0,0 +1,95 @@
+// 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 "chrome/browser/ui/autofill/payments/card_unmask_authentication_selection_dialog_controller_impl.h"
+#include "chrome/browser/ui/autofill/payments/card_unmask_authentication_selection_dialog_view.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/test/test_browser_dialog.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "content/public/test/browser_test.h"
+
+namespace autofill {
+
+class CardUnmaskAuthenticationSelectionDialogBrowserTest
+    : public DialogBrowserTest {
+ public:
+  CardUnmaskAuthenticationSelectionDialogBrowserTest() = default;
+  CardUnmaskAuthenticationSelectionDialogBrowserTest(
+      const CardUnmaskAuthenticationSelectionDialogBrowserTest&) = delete;
+  CardUnmaskAuthenticationSelectionDialogBrowserTest& operator=(
+      const CardUnmaskAuthenticationSelectionDialogBrowserTest&) = delete;
+
+  // DialogBrowserTest:
+  void ShowUi(const std::string& name) override {
+    content::WebContents* web_contents =
+        browser()->tab_strip_model()->GetActiveWebContents();
+
+    // Do lazy initialization of controller.
+    CardUnmaskAuthenticationSelectionDialogControllerImpl::CreateForWebContents(
+        web_contents);
+    controller()->ShowDialog(challenge_options_list_);
+  }
+
+  CardUnmaskAuthenticationSelectionDialogView* GetDialog() {
+    if (!controller())
+      return nullptr;
+
+    CardUnmaskAuthenticationSelectionDialogView* dialog_view =
+        controller()->GetDialogView();
+    if (!dialog_view)
+      return nullptr;
+
+    return static_cast<CardUnmaskAuthenticationSelectionDialogView*>(
+        dialog_view);
+  }
+
+  CardUnmaskAuthenticationSelectionDialogControllerImpl* controller() {
+    if (!browser() || !browser()->tab_strip_model() ||
+        !browser()->tab_strip_model()->GetActiveWebContents()) {
+      return nullptr;
+    }
+    return CardUnmaskAuthenticationSelectionDialogControllerImpl::
+        FromWebContents(browser()->tab_strip_model()->GetActiveWebContents());
+  }
+
+  void InitChallengeOptions() {
+    CardUnmaskChallengeOption card_unmask_challenge_option;
+    card_unmask_challenge_option.type = CardUnmaskChallengeOptionType::kSmsOtp;
+    card_unmask_challenge_option.challenge_info = u"xxx-xxx-3547";
+    challenge_options_list_ = {card_unmask_challenge_option};
+  }
+
+ private:
+  std::vector<CardUnmaskChallengeOption> challenge_options_list_;
+};
+
+// Ensures the UI can be shown.
+IN_PROC_BROWSER_TEST_F(CardUnmaskAuthenticationSelectionDialogBrowserTest,
+                       InvokeUi_CardUnmaskAuthSelectionDialogDisplays) {
+  InitChallengeOptions();
+  ShowAndVerifyUi();
+}
+
+// Ensures closing tab while dialog being visible is correctly handled.
+IN_PROC_BROWSER_TEST_F(CardUnmaskAuthenticationSelectionDialogBrowserTest,
+                       CanCloseTabWhileDialogShowing) {
+  InitChallengeOptions();
+  ShowUi("");
+  VerifyUi();
+  browser()->tab_strip_model()->GetActiveWebContents()->Close();
+  base::RunLoop().RunUntilIdle();
+}
+
+// Ensures closing browser while dialog being visible is correctly handled.
+IN_PROC_BROWSER_TEST_F(CardUnmaskAuthenticationSelectionDialogBrowserTest,
+                       CanCloseBrowserWhileDialogShowing) {
+  InitChallengeOptions();
+  ShowUi("");
+  VerifyUi();
+  browser()->window()->Close();
+  base::RunLoop().RunUntilIdle();
+}
+
+}  // namespace autofill
diff --git a/chrome/browser/ui/views/autofill/payments/card_unmask_authentication_selection_dialog_view_impl.cc b/chrome/browser/ui/views/autofill/payments/card_unmask_authentication_selection_dialog_view_impl.cc
new file mode 100644
index 0000000..cfbfb8f
--- /dev/null
+++ b/chrome/browser/ui/views/autofill/payments/card_unmask_authentication_selection_dialog_view_impl.cc
@@ -0,0 +1,141 @@
+// 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 "chrome/browser/ui/views/autofill/payments/card_unmask_authentication_selection_dialog_view_impl.h"
+
+#include "chrome/browser/ui/autofill/payments/card_unmask_authentication_selection_dialog_controller.h"
+#include "chrome/browser/ui/views/autofill/payments/payments_view_util.h"
+#include "chrome/browser/ui/views/chrome_layout_provider.h"
+#include "chrome/browser/ui/views/chrome_typography.h"
+#include "components/autofill/core/browser/payments/card_unmask_challenge_option.h"
+#include "components/constrained_window/constrained_window_views.h"
+#include "ui/views/border.h"
+#include "ui/views/bubble/bubble_frame_view.h"
+#include "ui/views/controls/image_view.h"
+#include "ui/views/controls/label.h"
+#include "ui/views/layout/box_layout.h"
+#include "ui/views/layout/box_layout_view.h"
+#include "ui/views/style/typography.h"
+
+namespace autofill {
+
+CardUnmaskAuthenticationSelectionDialogViewImpl::
+    CardUnmaskAuthenticationSelectionDialogViewImpl(
+        CardUnmaskAuthenticationSelectionDialogController* controller)
+    : controller_(controller) {
+  SetShowTitle(true);
+  SetButtonLabel(ui::DIALOG_BUTTON_OK, controller_->GetOkButtonLabel());
+  SetButtonLabel(ui::DIALOG_BUTTON_CANCEL,
+                 GetDialogButtonLabel(ui::DIALOG_BUTTON_CANCEL));
+  SetModalType(ui::MODAL_TYPE_CHILD);
+  SetShowCloseButton(false);
+  set_fixed_width(ChromeLayoutProvider::Get()->GetDistanceMetric(
+      ChromeDistanceMetric::DISTANCE_LARGE_MODAL_DIALOG_PREFERRED_WIDTH));
+  set_margins(ChromeLayoutProvider::Get()->GetDialogInsetsForContentType(
+      views::DialogContentType::kText, views::DialogContentType::kControl));
+  InitViews();
+}
+
+CardUnmaskAuthenticationSelectionDialogViewImpl::
+    ~CardUnmaskAuthenticationSelectionDialogViewImpl() {
+  if (controller_)
+    controller_->OnDialogClosed();
+}
+
+// static
+CardUnmaskAuthenticationSelectionDialogView*
+CardUnmaskAuthenticationSelectionDialogView::CreateAndShow(
+    CardUnmaskAuthenticationSelectionDialogController* controller) {
+  CardUnmaskAuthenticationSelectionDialogViewImpl* dialog_view =
+      new CardUnmaskAuthenticationSelectionDialogViewImpl(controller);
+  constrained_window::ShowWebModalDialogViews(dialog_view,
+                                              controller->GetWebContents());
+  return dialog_view;
+}
+
+void CardUnmaskAuthenticationSelectionDialogViewImpl::OnControllerDestroying() {
+  controller_ = nullptr;
+  GetWidget()->Close();
+}
+
+std::u16string CardUnmaskAuthenticationSelectionDialogViewImpl::GetWindowTitle()
+    const {
+  return controller_->GetWindowTitle();
+}
+
+void CardUnmaskAuthenticationSelectionDialogViewImpl::AddedToWidget() {
+  GetBubbleFrameView()->SetTitleView(
+      std::make_unique<TitleWithIconAndSeparatorView>(GetWindowTitle()));
+}
+
+void CardUnmaskAuthenticationSelectionDialogViewImpl::InitViews() {
+  DCHECK(children().empty());
+  // Sets the layout manager for the top level view.
+  SetLayoutManager(std::make_unique<views::BoxLayout>(
+      views::BoxLayout::Orientation::kVertical, gfx::Insets(),
+      ChromeLayoutProvider::Get()->GetDistanceMetric(
+          views::DISTANCE_UNRELATED_CONTROL_VERTICAL)));
+  // Adds the header.
+  AddHeaderText();
+  // Adds the list of challenge options.
+  AddChallengeOptionsViews();
+  // Adds the footer.
+  AddFooterText();
+}
+
+void CardUnmaskAuthenticationSelectionDialogViewImpl::AddHeaderText() {
+  auto* content = AddChildView(std::make_unique<views::Label>(
+      controller_->GetContentHeaderText(),
+      views::style::CONTEXT_DIALOG_BODY_TEXT, views::style::STYLE_SECONDARY));
+  content->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+}
+
+void CardUnmaskAuthenticationSelectionDialogViewImpl::
+    AddChallengeOptionsViews() {
+  for (const CardUnmaskChallengeOption& challenge_option :
+       controller_->GetChallengeOptions()) {
+    // Initializes the current challenge option.
+    auto challenge_option_container = std::make_unique<views::BoxLayoutView>();
+    challenge_option_container->SetOrientation(
+        views::BoxLayout::Orientation::kHorizontal);
+    challenge_option_container->SetBetweenChildSpacing(
+        ChromeLayoutProvider::Get()->GetDistanceMetric(
+            DISTANCE_RELATED_CONTROL_HORIZONTAL_SMALL));
+
+    // Creates the left side image of the challenge option and adds it to the
+    // current challenge option.
+    challenge_option_container->AddChildView(std::make_unique<views::ImageView>(
+        controller_->GetAuthenticationModeIcon(challenge_option)));
+
+    // Creates the right side of the challenge option (label and information
+    // such as masked phone number, masked email, etc...) and adds it to the
+    // current challenge option.
+    auto challenge_option_details = std::make_unique<views::BoxLayoutView>();
+    challenge_option_details->SetOrientation(
+        views::BoxLayout::Orientation::kVertical);
+    challenge_option_details->AddChildView(std::make_unique<views::Label>(
+        controller_->GetAuthenticationModeLabel(challenge_option),
+        ChromeTextContext::CONTEXT_DIALOG_BODY_TEXT_SMALL,
+        views::style::STYLE_PRIMARY));
+    challenge_option_details->AddChildView(std::make_unique<views::Label>(
+        challenge_option.challenge_info,
+        ChromeTextContext::CONTEXT_DIALOG_BODY_TEXT_SMALL,
+        views::style::STYLE_SECONDARY));
+    challenge_option_container->AddChildView(
+        std::move(challenge_option_details));
+
+    // Adds the current challenge option to the top level view.
+    AddChildView(std::move(challenge_option_container));
+  }
+}
+
+void CardUnmaskAuthenticationSelectionDialogViewImpl::AddFooterText() {
+  auto* content = AddChildView(std::make_unique<views::Label>(
+      controller_->GetContentFooterText(),
+      ChromeTextContext::CONTEXT_DIALOG_BODY_TEXT_SMALL,
+      views::style::STYLE_SECONDARY));
+  content->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+}
+
+}  // namespace autofill
diff --git a/chrome/browser/ui/views/autofill/payments/card_unmask_authentication_selection_dialog_view_impl.h b/chrome/browser/ui/views/autofill/payments/card_unmask_authentication_selection_dialog_view_impl.h
new file mode 100644
index 0000000..70ed543
--- /dev/null
+++ b/chrome/browser/ui/views/autofill/payments/card_unmask_authentication_selection_dialog_view_impl.h
@@ -0,0 +1,56 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_AUTOFILL_PAYMENTS_CARD_UNMASK_AUTHENTICATION_SELECTION_DIALOG_VIEW_IMPL_H_
+#define CHROME_BROWSER_UI_VIEWS_AUTOFILL_PAYMENTS_CARD_UNMASK_AUTHENTICATION_SELECTION_DIALOG_VIEW_IMPL_H_
+
+#include <string>
+
+#include "chrome/browser/ui/autofill/payments/card_unmask_authentication_selection_dialog_view.h"
+#include "components/autofill/core/browser/payments/card_unmask_challenge_option.h"
+#include "ui/views/controls/image_view.h"
+#include "ui/views/window/dialog_delegate.h"
+
+namespace autofill {
+
+class CardUnmaskAuthenticationSelectionDialogController;
+
+class CardUnmaskAuthenticationSelectionDialogViewImpl
+    : public CardUnmaskAuthenticationSelectionDialogView,
+      public views::DialogDelegateView {
+ public:
+  explicit CardUnmaskAuthenticationSelectionDialogViewImpl(
+      CardUnmaskAuthenticationSelectionDialogController* controller);
+  CardUnmaskAuthenticationSelectionDialogViewImpl(
+      const CardUnmaskAuthenticationSelectionDialogViewImpl&) = delete;
+  CardUnmaskAuthenticationSelectionDialogViewImpl& operator=(
+      const CardUnmaskAuthenticationSelectionDialogViewImpl&) = delete;
+  ~CardUnmaskAuthenticationSelectionDialogViewImpl() override;
+
+  // CardUnmaskAuthenticationSelectionDialogView:
+  void OnControllerDestroying() override;
+
+  // views::DialogDelegateView:
+  std::u16string GetWindowTitle() const override;
+  void AddedToWidget() override;
+
+ private:
+  // Initializes the contents of the view and all of its child views.
+  void InitViews();
+
+  void AddHeaderText();
+
+  // Adds all of the challenge options to the dialog. Each challenge option
+  // is an option that can be selected to authenticate a user, such
+  // as a text message or a phone number.
+  void AddChallengeOptionsViews();
+
+  void AddFooterText();
+
+  CardUnmaskAuthenticationSelectionDialogController* controller_ = nullptr;
+};
+
+}  // namespace autofill
+
+#endif  // CHROME_BROWSER_UI_VIEWS_AUTOFILL_PAYMENTS_CARD_UNMASK_AUTHENTICATION_SELECTION_DIALOG_VIEW_IMPL_H_
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index eec803de..8f384c1 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -1938,12 +1938,21 @@
 BrowserView::ShowQRCodeGeneratorBubble(
     content::WebContents* contents,
     qrcode_generator::QRCodeGeneratorBubbleController* controller,
-    const GURL& url) {
+    const GURL& url,
+    bool show_back_button) {
   base::OnceClosure on_closing = base::BindOnce(
       &qrcode_generator::QRCodeGeneratorBubbleController::OnBubbleClosed,
       // Unretained is safe: controller is a WebContentsUserData, owned by
       // WebContents, and the bubble can't outlive the WebContents.
       base::Unretained(controller));
+  base::OnceClosure on_back_button_pressed;
+  if (show_back_button) {
+    on_back_button_pressed = base::BindOnce(
+        &qrcode_generator::QRCodeGeneratorBubbleController::OnBackButtonPressed,
+        // Unretained is safe: controller is a WebContentsUserData, owned by
+        // WebContents, and the bubble can't outlive the WebContents.
+        base::Unretained(controller));
+  }
 
   PageActionIconType icon_type =
       sharing_hub::SharingHubOmniboxEnabled(contents->GetBrowserContext())
@@ -1953,7 +1962,7 @@
   qrcode_generator::QRCodeGeneratorBubble* bubble =
       new qrcode_generator::QRCodeGeneratorBubble(
           toolbar_button_provider()->GetAnchorView(icon_type), contents,
-          std::move(on_closing), url);
+          std::move(on_closing), std::move(on_back_button_pressed), url);
 
   PageActionIconView* icon_view =
       toolbar_button_provider()->GetPageActionIconView(icon_type);
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h
index b087e28a..17bd4e7 100644
--- a/chrome/browser/ui/views/frame/browser_view.h
+++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -485,7 +485,8 @@
   qrcode_generator::QRCodeGeneratorBubbleView* ShowQRCodeGeneratorBubble(
       content::WebContents* contents,
       qrcode_generator::QRCodeGeneratorBubbleController* controller,
-      const GURL& url) override;
+      const GURL& url,
+      bool show_back_button) override;
   send_tab_to_self::SendTabToSelfBubbleView* ShowSendTabToSelfBubble(
       content::WebContents* contents,
       send_tab_to_self::SendTabToSelfBubbleController* controller,
diff --git a/chrome/browser/ui/views/omnibox/omnibox_suggestion_button_row_view.cc b/chrome/browser/ui/views/omnibox/omnibox_suggestion_button_row_view.cc
index 42471a8..26c0343 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_suggestion_button_row_view.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_suggestion_button_row_view.cc
@@ -47,7 +47,8 @@
       : MdTextButton(std::move(callback), text, CONTEXT_OMNIBOX_PRIMARY),
         icon_(&icon),
         popup_contents_view_(popup_contents_view),
-        selection_(selection) {
+        selection_(selection),
+        icon_color_(SK_ColorTRANSPARENT) {
     views::InstallPillHighlightPathGenerator(this);
     SetImageLabelSpacing(ChromeLayoutProvider::Get()->GetDistanceMetric(
         DISTANCE_RELATED_LABEL_HORIZONTAL_LIST));
@@ -90,8 +91,10 @@
     // We can't use colors from NativeTheme as the omnibox theme might be
     // different (for example, if the NTP colors are customized).
     SkColor icon_color =
-        GetOmniboxColor(GetThemeProvider(), OmniboxPart::RESULTS_ICON,
-                        OmniboxPartState::NORMAL);
+        icon_color_ != SK_ColorTRANSPARENT
+            ? icon_color_
+            : GetOmniboxColor(GetThemeProvider(), OmniboxPart::RESULTS_ICON,
+                              OmniboxPartState::NORMAL);
     SetImage(
         views::Button::STATE_NORMAL,
         gfx::CreateVectorIcon(*icon_, GetLayoutConstant(LOCATION_BAR_ICON_SIZE),
@@ -120,9 +123,11 @@
     node_data->role = ax::mojom::Role::kListBoxOption;
   }
 
-  void SetIcon(const gfx::VectorIcon& icon) {
-    if (icon_ != &icon) {
+  void SetIcon(const gfx::VectorIcon& icon,
+               SkColor icon_color = SK_ColorTRANSPARENT) {
+    if (icon_ != &icon || icon_color != icon_color_) {
       icon_ = &icon;
+      icon_color_ = icon_color;
       OnThemeChanged();
     }
   }
@@ -132,6 +137,7 @@
   OmniboxPopupContentsView* popup_contents_view_;
   OmniboxPopupSelection selection_;
   absl::optional<SkColor> omnibox_bg_color_;
+  SkColor icon_color_;
 };
 
 BEGIN_METADATA(OmniboxSuggestionRowButton, views::MdTextButton)
@@ -217,7 +223,8 @@
     pedal_button_->SetText(pedal_strings.hint);
     pedal_button_->SetTooltipText(pedal_strings.suggestion_contents);
     pedal_button_->SetAccessibleName(pedal_strings.accessibility_hint);
-    pedal_button_->SetIcon(match().action->GetVectorIcon());
+    pedal_button_->SetIcon(match().action->GetVectorIcon(),
+                           match().action->GetVectorIconColor());
   }
 
   bool is_any_button_visible = keyword_button_->GetVisible() ||
diff --git a/chrome/browser/ui/views/qrcode_generator/qrcode_generator_bubble.cc b/chrome/browser/ui/views/qrcode_generator/qrcode_generator_bubble.cc
index 9ccfee5..0dcc26c 100644
--- a/chrome/browser/ui/views/qrcode_generator/qrcode_generator_bubble.cc
+++ b/chrome/browser/ui/views/qrcode_generator/qrcode_generator_bubble.cc
@@ -19,6 +19,7 @@
 #include "chrome/browser/ui/views/chrome_typography.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/frame/top_container_view.h"
+#include "chrome/browser/ui/views/sharing_hub/sharing_hub_bubble_util.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/services/qrcode_generator/public/cpp/qrcode_generator_service.h"
 #include "chrome/services/qrcode_generator/public/mojom/qrcode_generator.mojom.h"
@@ -92,13 +93,16 @@
 
 namespace qrcode_generator {
 
-QRCodeGeneratorBubble::QRCodeGeneratorBubble(views::View* anchor_view,
-                                             content::WebContents* web_contents,
-                                             base::OnceClosure on_closing,
-                                             const GURL& url)
+QRCodeGeneratorBubble::QRCodeGeneratorBubble(
+    views::View* anchor_view,
+    content::WebContents* web_contents,
+    base::OnceClosure on_closing,
+    base::OnceClosure on_back_button_pressed,
+    const GURL& url)
     : LocationBarBubbleDelegateView(anchor_view, nullptr),
       url_(url),
       on_closing_(std::move(on_closing)),
+      on_back_button_pressed_(std::move(on_back_button_pressed)),
       web_contents_(web_contents) {
   DCHECK(on_closing_);
 
@@ -356,6 +360,18 @@
     qr_code_service_remote_ = qrcode_generator::LaunchQRCodeGeneratorService();
 }
 
+void QRCodeGeneratorBubble::AddedToWidget() {
+  if (!on_back_button_pressed_)
+    return;
+
+  // Adding a title view will replace the default title.
+  GetBubbleFrameView()->SetTitleView(
+      std::make_unique<sharing_hub::TitleWithBackButtonView>(
+          base::BindRepeating(&QRCodeGeneratorBubble::BackButtonPressed,
+                              base::Unretained(this)),
+          GetWindowTitle()));
+}
+
 void QRCodeGeneratorBubble::ContentsChanged(
     views::Textfield* sender,
     const std::u16string& new_contents) {
@@ -469,6 +485,13 @@
   base::RecordAction(base::UserMetricsAction("SharingQRCode.DownloadQRCode"));
 }
 
+void QRCodeGeneratorBubble::BackButtonPressed() {
+  Hide();
+
+  DCHECK(on_back_button_pressed_);
+  std::move(on_back_button_pressed_).Run();
+}
+
 BEGIN_METADATA(QRCodeGeneratorBubble, LocationBarBubbleDelegateView)
 END_METADATA
 
diff --git a/chrome/browser/ui/views/qrcode_generator/qrcode_generator_bubble.h b/chrome/browser/ui/views/qrcode_generator/qrcode_generator_bubble.h
index 2ae69927..751c245 100644
--- a/chrome/browser/ui/views/qrcode_generator/qrcode_generator_bubble.h
+++ b/chrome/browser/ui/views/qrcode_generator/qrcode_generator_bubble.h
@@ -44,6 +44,7 @@
   QRCodeGeneratorBubble(views::View* anchor_view,
                         content::WebContents* web_contents,
                         base::OnceClosure on_closing,
+                        base::OnceClosure on_back_button_pressed,
                         const GURL& url);
   QRCodeGeneratorBubble(const QRCodeGeneratorBubble&) = delete;
   QRCodeGeneratorBubble& operator=(const QRCodeGeneratorBubble&) = delete;
@@ -94,6 +95,7 @@
 
   // views::BubbleDialogDelegateView:
   void Init() override;
+  void AddedToWidget() override;
 
   // TextfieldController:
   void ContentsChanged(views::Textfield* sender,
@@ -105,6 +107,8 @@
 
   void DownloadButtonPressed();
 
+  void BackButtonPressed();
+
   // Callback for the request to the OOP service to generate a new image.
   void OnCodeGeneratorResponse(const mojom::GenerateQRCodeResponsePtr response);
 
@@ -124,6 +128,7 @@
   views::Label* bottom_error_label_ = nullptr;
 
   base::OnceClosure on_closing_;
+  base::OnceClosure on_back_button_pressed_;
   content::WebContents* web_contents_;           // weak.
 };
 
diff --git a/chrome/browser/ui/views/qrcode_generator/qrcode_generator_bubble_unittest.cc b/chrome/browser/ui/views/qrcode_generator/qrcode_generator_bubble_unittest.cc
index b508f1e..2e65723 100644
--- a/chrome/browser/ui/views/qrcode_generator/qrcode_generator_bubble_unittest.cc
+++ b/chrome/browser/ui/views/qrcode_generator/qrcode_generator_bubble_unittest.cc
@@ -123,7 +123,7 @@
         anchor_widget_->SetContentsView(std::make_unique<views::View>());
     CHECK(anchor_view_);
     auto bubble = std::make_unique<QRCodeGeneratorBubble>(
-        anchor_view_, nullptr, base::DoNothing(),
+        anchor_view_, nullptr, base::DoNothing(), base::DoNothing(),
         GURL("https://www.chromium.org/a"));
     bubble->SetQRCodeServiceForTesting(
         mojo::Remote<mojom::QRCodeGeneratorService>(
diff --git a/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_view_impl.cc b/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_view_impl.cc
index 30b2bf4..13029fdf 100644
--- a/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_view_impl.cc
+++ b/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_view_impl.cc
@@ -13,6 +13,7 @@
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/frame/toolbar_button_provider.h"
 #include "chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_device_button.h"
+#include "chrome/browser/ui/views/sharing_hub/sharing_hub_bubble_util.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/send_tab_to_self/features.h"
 #include "components/send_tab_to_self/target_device_info.h"
@@ -94,6 +95,13 @@
   }
 }
 
+void SendTabToSelfBubbleViewImpl::BackButtonPressed() {
+  if (controller_) {
+    controller_->OnBackButtonPressed();
+    Hide();
+  }
+}
+
 void SendTabToSelfBubbleViewImpl::DeviceButtonPressed(
     SendTabToSelfBubbleDeviceButton* device_button) {
   if (!controller_)
@@ -156,6 +164,18 @@
   }
 }
 
+void SendTabToSelfBubbleViewImpl::AddedToWidget() {
+  if (!controller_->show_back_button())
+    return;
+
+  // Adding a title view will replace the default title.
+  GetBubbleFrameView()->SetTitleView(
+      std::make_unique<sharing_hub::TitleWithBackButtonView>(
+          base::BindRepeating(&SendTabToSelfBubbleViewImpl::BackButtonPressed,
+                              base::Unretained(this)),
+          GetWindowTitle()));
+}
+
 void SendTabToSelfBubbleViewImpl::CreateHintTextLabel(
     views::GridLayout* layout) {
   layout->StartRow(1.0f, 0);
diff --git a/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_view_impl.h b/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_view_impl.h
index f2a4d5a..d675734 100644
--- a/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_view_impl.h
+++ b/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_view_impl.h
@@ -55,6 +55,8 @@
   std::u16string GetWindowTitle() const override;
   void WindowClosing() override;
 
+  void BackButtonPressed();
+
   void DeviceButtonPressed(SendTabToSelfBubbleDeviceButton* device_button);
 
   void OnManageDevicesClicked(const ui::Event& event);
@@ -64,6 +66,7 @@
  private:
   // views::BubbleDialogDelegateView:
   void Init() override;
+  void AddedToWidget() override;
 
   // Creates the subtitle / hint text used in V2.
   void CreateHintTextLabel(views::GridLayout* layout);
diff --git a/chrome/browser/ui/views/sharing_hub/sharing_hub_bubble_util.cc b/chrome/browser/ui/views/sharing_hub/sharing_hub_bubble_util.cc
new file mode 100644
index 0000000..f9c910cf
--- /dev/null
+++ b/chrome/browser/ui/views/sharing_hub/sharing_hub_bubble_util.cc
@@ -0,0 +1,74 @@
+// 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 "chrome/browser/ui/views/sharing_hub/sharing_hub_bubble_util.h"
+
+#include "chrome/grit/generated_resources.h"
+#include "components/strings/grit/components_strings.h"
+#include "components/vector_icons/vector_icons.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/views/controls/button/image_button.h"
+#include "ui/views/controls/button/image_button_factory.h"
+#include "ui/views/controls/highlight_path_generator.h"
+#include "ui/views/controls/label.h"
+#include "ui/views/layout/grid_layout.h"
+#include "ui/views/layout/layout_provider.h"
+
+namespace sharing_hub {
+
+namespace {
+
+constexpr int kPaddingColumnWidth = 10;
+
+}  // namespace
+
+TitleWithBackButtonView::TitleWithBackButtonView(
+    views::Button::PressedCallback back_callback,
+    const std::u16string& window_title) {
+  views::GridLayout* layout =
+      SetLayoutManager(std::make_unique<views::GridLayout>());
+  views::ColumnSet* columns = layout->AddColumnSet(0);
+
+  using ColumnSize = views::GridLayout::ColumnSize;
+  // Add columns for the back button, padding, and the title label.
+  columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER,
+                     views::GridLayout::kFixedSize, ColumnSize::kUsePreferred,
+                     0, 0);
+  columns->AddPaddingColumn(views::GridLayout::kFixedSize, kPaddingColumnWidth);
+  columns->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER, 1.f,
+                     ColumnSize::kUsePreferred, 0, 0);
+
+  layout->StartRow(views::GridLayout::kFixedSize, 0);
+
+  auto back_button = views::CreateVectorImageButtonWithNativeTheme(
+      std::move(back_callback), vector_icons::kBackArrowIcon);
+  back_button->SetTooltipText(l10n_util::GetStringUTF16(IDS_TOOLTIP_BACK));
+  back_button->SetAccessibleName(l10n_util::GetStringUTF16(IDS_ACCNAME_BACK));
+  back_button->SizeToPreferredSize();
+  InstallCircleHighlightPathGenerator(back_button.get());
+  layout->AddView(std::move(back_button));
+
+  auto title = std::make_unique<views::Label>(
+      window_title, views::style::CONTEXT_DIALOG_TITLE);
+  title->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+  title->SetCollapseWhenHidden(true);
+  title->SetMultiLine(true);
+  layout->AddView(std::move(title));
+}
+
+TitleWithBackButtonView::~TitleWithBackButtonView() = default;
+
+gfx::Size TitleWithBackButtonView::GetMinimumSize() const {
+  // View::GetMinimum() defaults to GridLayout::GetPreferredSize(), but that
+  // gives a larger frame width, so the dialog will become wider than it should.
+  // To avoid that, just return 0x0.
+  return gfx::Size(0, 0);
+}
+
+BEGIN_METADATA(TitleWithBackButtonView, views::View)
+END_METADATA
+
+}  // namespace sharing_hub
diff --git a/chrome/browser/ui/views/sharing_hub/sharing_hub_bubble_util.h b/chrome/browser/ui/views/sharing_hub/sharing_hub_bubble_util.h
new file mode 100644
index 0000000..45f962ca
--- /dev/null
+++ b/chrome/browser/ui/views/sharing_hub/sharing_hub_bubble_util.h
@@ -0,0 +1,32 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_SHARING_HUB_SHARING_HUB_BUBBLE_UTIL_H_
+#define CHROME_BROWSER_UI_VIEWS_SHARING_HUB_SHARING_HUB_BUBBLE_UTIL_H_
+
+#include <string>
+
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/views/controls/button/button.h"
+#include "ui/views/view.h"
+
+namespace sharing_hub {
+
+// Defines a title view with a back button and a label. Used by first party
+// action dialogs for the sharing hub (e.g. qr code, send tab to self).
+class TitleWithBackButtonView : public views::View {
+ public:
+  METADATA_HEADER(TitleWithBackButtonView);
+  explicit TitleWithBackButtonView(views::Button::PressedCallback callback,
+                                   const std::u16string& window_title);
+  ~TitleWithBackButtonView() override;
+
+ private:
+  // views::View:
+  gfx::Size GetMinimumSize() const override;
+};
+
+}  // namespace sharing_hub
+
+#endif  // CHROME_BROWSER_UI_VIEWS_SHARING_HUB_SHARING_HUB_BUBBLE_UTIL_H_
diff --git a/chrome/browser/ui/views/side_search/side_search_browser_controller.cc b/chrome/browser/ui/views/side_search/side_search_browser_controller.cc
index 594e4f8..a42f8cc 100644
--- a/chrome/browser/ui/views/side_search/side_search_browser_controller.cc
+++ b/chrome/browser/ui/views/side_search/side_search_browser_controller.cc
@@ -179,6 +179,19 @@
   Observe(nullptr);
 }
 
+bool SideSearchBrowserController::HandleKeyboardEvent(
+    content::WebContents* source,
+    const content::NativeWebKeyboardEvent& event) {
+  return unhandled_keyboard_event_handler_.HandleKeyboardEvent(
+      event, browser_view_->GetFocusManager());
+}
+
+content::WebContents* SideSearchBrowserController::OpenURLFromTab(
+    content::WebContents* source,
+    const content::OpenURLParams& params) {
+  return browser_view_->browser()->OpenURL(params);
+}
+
 void SideSearchBrowserController::DidFinishNavigation(
     content::NavigationHandle* navigation_handle) {
   if (!navigation_handle->IsInPrimaryMainFrame() ||
@@ -196,6 +209,17 @@
 void SideSearchBrowserController::UpdateSidePanelForContents(
     content::WebContents* new_contents,
     content::WebContents* old_contents) {
+  // Ensure that the controller acts as the delegate only to the currently
+  // active contents.
+  if (old_contents) {
+    SideSearchTabContentsHelper::FromWebContents(old_contents)
+        ->SetDelegate(nullptr);
+  }
+  if (new_contents) {
+    SideSearchTabContentsHelper::FromWebContents(new_contents)
+        ->SetDelegate(weak_factory_.GetWeakPtr());
+  }
+
   Observe(new_contents);
 
   // Update the state of the side panel to catch cases where we switch to a tab
@@ -240,7 +264,37 @@
 
 void SideSearchBrowserController::SidePanelButtonPressed() {
   // Toggle the side panel visibility.
-  SetSidePanelToggledOpen(!GetSidePanelToggledOpen());
+  const bool new_toggled_state = !GetSidePanelToggledOpen();
+  SetSidePanelToggledOpen(new_toggled_state);
+  if (!new_toggled_state &&
+      base::FeatureList::IsEnabled(features::kSideSearchClearCacheWhenClosed)) {
+    // If per tab state is enabled only clear the side contents for the
+    // currently active tab.
+    base::FeatureList::IsEnabled(features::kSideSearchStatePerTab)
+        ? ClearSideContentsCacheForActiveTab()
+        : ClearSideContentsCacheForBrowser();
+  }
+}
+
+void SideSearchBrowserController::ClearSideContentsCacheForBrowser() {
+  web_view_->SetWebContents(nullptr);
+
+  // Notify the tab helpers that their side panel contentes can be cleared away.
+  TabStripModel* tab_strip_model = browser_view_->browser()->tab_strip_model();
+  for (int i = 0; i < tab_strip_model->count(); ++i) {
+    SideSearchTabContentsHelper::FromWebContents(
+        tab_strip_model->GetWebContentsAt(i))
+        ->ClearSidePanelContents();
+  }
+}
+
+void SideSearchBrowserController::ClearSideContentsCacheForActiveTab() {
+  web_view_->SetWebContents(nullptr);
+
+  if (auto* active_contents = browser_view_->GetActiveWebContents()) {
+    SideSearchTabContentsHelper::FromWebContents(active_contents)
+        ->ClearSidePanelContents();
+  }
 }
 
 void SideSearchBrowserController::SetSidePanelToggledOpen(bool toggled_open) {
diff --git a/chrome/browser/ui/views/side_search/side_search_browser_controller.h b/chrome/browser/ui/views/side_search/side_search_browser_controller.h
index 0d4f372..3b439a7 100644
--- a/chrome/browser/ui/views/side_search/side_search_browser_controller.h
+++ b/chrome/browser/ui/views/side_search/side_search_browser_controller.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_UI_VIEWS_SIDE_SEARCH_SIDE_SEARCH_BROWSER_CONTROLLER_H_
 #define CHROME_BROWSER_UI_VIEWS_SIDE_SEARCH_SIDE_SEARCH_BROWSER_CONTROLLER_H_
 
+#include "base/memory/weak_ptr.h"
 #include "chrome/browser/ui/side_search/side_search_tab_contents_helper.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "ui/views/controls/webview/unhandled_keyboard_event_handler.h"
@@ -19,7 +20,9 @@
 
 // Responsible for managing the WebContents hosted in the browser's side panel
 // for Side Search in addition to managing the state of the side panel itself.
-class SideSearchBrowserController : public content::WebContentsObserver {
+class SideSearchBrowserController
+    : public SideSearchTabContentsHelper::Delegate,
+      public content::WebContentsObserver {
  public:
   enum SideSearchViewID {
     VIEW_ID_NONE = 0,
@@ -32,6 +35,14 @@
       delete;
   ~SideSearchBrowserController() override;
 
+  // SideSearchTabContentsHelper::Delegate:
+  bool HandleKeyboardEvent(
+      content::WebContents* source,
+      const content::NativeWebKeyboardEvent& event) override;
+  content::WebContents* OpenURLFromTab(
+      content::WebContents* source,
+      const content::OpenURLParams& params) override;
+
   // content::WebContentsObserver:
   void DidFinishNavigation(
       content::NavigationHandle* navigation_handle) override;
@@ -53,6 +64,15 @@
   // Toggles panel visibility on button press.
   void SidePanelButtonPressed();
 
+  // Called when the side panel is toggled into the closed state. Clears the
+  // side panel contents for all tabs belonging to the side panel's browser
+  // window.
+  void ClearSideContentsCacheForBrowser();
+
+  // Clears the side contents for the currently active tab in this browser
+  // window.
+  void ClearSideContentsCacheForActiveTab();
+
   // Updates the `side_panel_`'s visibility and updates it to host the side
   // contents associated with the currently active tab for this browser window.
   void UpdateSidePanel();
@@ -65,6 +85,12 @@
   SidePanel* const side_panel_;
   BrowserView* const browser_view_;
   views::WebView* const web_view_;
+
+  // A handler to handle unhandled keyboard messages coming back from the
+  // renderer process.
+  views::UnhandledKeyboardEventHandler unhandled_keyboard_event_handler_;
+
+  base::WeakPtrFactory<SideSearchBrowserController> weak_factory_{this};
 };
 
 #endif  // CHROME_BROWSER_UI_VIEWS_SIDE_SEARCH_SIDE_SEARCH_BROWSER_CONTROLLER_H_
diff --git a/chrome/browser/ui/webui/app_management/app_management_page_handler.cc b/chrome/browser/ui/webui/app_management/app_management_page_handler.cc
index 3ccd73f7..d9a7878e 100644
--- a/chrome/browser/ui/webui/app_management/app_management_page_handler.cc
+++ b/chrome/browser/ui/webui/app_management/app_management_page_handler.cc
@@ -233,18 +233,14 @@
 
 void AppManagementPageHandler::SetPreferredApp(const std::string& app_id,
                                                bool is_preferred_app) {
-  auto intent_filters = GetSupportedLinkIntentFilters(profile_, app_id);
   bool is_preferred_app_for_supported_links =
       preferred_apps_list_.IsPreferredAppForSupportedLinks(app_id);
+  auto* proxy = apps::AppServiceProxyFactory::GetForProfile(profile_);
 
   if (is_preferred_app && !is_preferred_app_for_supported_links) {
-    for (auto& filter : intent_filters) {
-      this->preferred_apps_list_.AddPreferredApp(app_id, filter);
-    }
+    proxy->SetSupportedLinksPreference(app_id);
   } else if (!is_preferred_app && is_preferred_app_for_supported_links) {
-    for (auto& filter : intent_filters) {
-      this->preferred_apps_list_.DeletePreferredApp(app_id, filter);
-    }
+    proxy->RemoveSupportedLinksPreference(app_id);
   }
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/l10n_util.cc b/chrome/browser/ui/webui/chromeos/login/l10n_util.cc
index 4d4c462..d5dee2e 100644
--- a/chrome/browser/ui/webui/chromeos/login/l10n_util.cc
+++ b/chrome/browser/ui/webui/chromeos/login/l10n_util.cc
@@ -516,7 +516,7 @@
   }
 
   std::unique_ptr<input_method::InputMethodDescriptors> input_methods(
-      manager->GetActiveIMEState()->GetActiveInputMethods());
+      manager->GetActiveIMEState()->GetEnabledInputMethods());
   std::set<std::string> input_methods_added;
 
   for (std::vector<std::string>::const_iterator i =
diff --git a/chrome/browser/ui/webui/history/history_ui.cc b/chrome/browser/ui/webui/history/history_ui.cc
index b6840c3..5dbd19d8 100644
--- a/chrome/browser/ui/webui/history/history_ui.cc
+++ b/chrome/browser/ui/webui/history/history_ui.cc
@@ -129,15 +129,22 @@
   source->AddBoolean("isHistoryClustersDebug",
                      base::FeatureList::IsEnabled(history_clusters::kDebug));
 
-  // TODO(crbug.com/1173908): Replace these with localized strings.
-  source->AddString("headerTitle", u"Based on activity related to \"$1\"");
-  source->AddString("historyClustersMenuItem", u"Journeys");
-  source->AddString("relatedSearchesLabel", u"Related:");
-  source->AddString("removeAllFromHistory", u"Remove Journey from history");
-  source->AddString("removeFromHistoryToast", u"Item removed");
-  source->AddString("savedInTabGroup", u"Saved in tab group");
-  source->AddString("toggleButtonLabelLess", u"Show less");
-  source->AddString("toggleButtonLabelMore", u"Show more");
+  // TODO(crbug.com/1173908): Change `historyClustersMenuItem` to
+  // `historyClustersTabLabel` once the UI is updated to tab view.
+  static constexpr webui::LocalizedString kHistoryClustersStrings[] = {
+      {"disableHistoryClusters", IDS_HISTORY_CLUSTERS_DISABLE_MENU_ITEM_LABEL},
+      {"enableHistoryClusters", IDS_HISTORY_CLUSTERS_ENABLE_MENU_ITEM_LABEL},
+      {"headerText", IDS_HISTORY_CLUSTERS_HEADER_TEXT},
+      {"historyClustersMenuItem", IDS_HISTORY_CLUSTERS_JOURNEYS_TAB_LABEL},
+      {"historyListTabLabel", IDS_HISTORY_CLUSTERS_LIST_TAB_LABEL},
+      {"relatedSearchesHeader", IDS_HISTORY_CLUSTERS_RELATED_SEARCHES_HEADER},
+      {"removeAllFromHistory", IDS_HISTORY_CLUSTERS_REMOVE_ALL_ITEMS},
+      {"removeFromHistoryToast", IDS_HISTORY_CLUSTERS_REMOVE_ITEM_TOAST},
+      {"savedInTabGroup", IDS_HISTORY_CLUSTERS_SAVED_IN_TABGROUP_LABEL},
+      {"toggleButtonLabelLess", IDS_HISTORY_CLUSTERS_SHOW_LESS_BUTTON_LABEL},
+      {"toggleButtonLabelMore", IDS_HISTORY_CLUSTERS_SHOW_MORE_BUTTON_LABEL},
+  };
+  source->AddLocalizedStrings(kHistoryClustersStrings);
 
   webui::SetupWebUIDataSource(
       source, base::make_span(kHistoryResources, kHistoryResourcesSize),
diff --git a/chrome/browser/ui/webui/management/management_ui.cc b/chrome/browser/ui/webui/management/management_ui.cc
index 0d2266d..489de5e 100644
--- a/chrome/browser/ui/webui/management/management_ui.cc
+++ b/chrome/browser/ui/webui/management/management_ui.cc
@@ -63,8 +63,8 @@
     {kManagementLogUploadEnabled, IDS_MANAGEMENT_LOG_UPLOAD_ENABLED},
     {kManagementReportActivityTimes,
      IDS_MANAGEMENT_REPORT_DEVICE_ACTIVITY_TIMES},
-    {kManagementReportNetworkInterfaces,
-     IDS_MANAGEMENT_REPORT_DEVICE_NETWORK_INTERFACES},
+    {kManagementReportNetworkData, IDS_MANAGEMENT_REPORT_DEVICE_NETWORK_DATA},
+    {kManagementReportHardwareData, IDS_MANAGEMENT_REPORT_DEVICE_HARDWARE_DATA},
     {kManagementReportUsers, IDS_MANAGEMENT_REPORT_DEVICE_USERS},
     {kManagementReportCrashReports, IDS_MANAGEMENT_REPORT_DEVICE_CRASH_REPORTS},
     {kManagementReportAppInfoAndActivity,
diff --git a/chrome/browser/ui/webui/management/management_ui_handler.cc b/chrome/browser/ui/webui/management/management_ui_handler.cc
index 443c729..60c8424 100644
--- a/chrome/browser/ui/webui/management/management_ui_handler.cc
+++ b/chrome/browser/ui/webui/management/management_ui_handler.cc
@@ -160,8 +160,8 @@
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 const char kManagementLogUploadEnabled[] = "managementLogUploadEnabled";
 const char kManagementReportActivityTimes[] = "managementReportActivityTimes";
-const char kManagementReportNetworkInterfaces[] =
-    "managementReportNetworkInterfaces";
+const char kManagementReportNetworkData[] = "managementReportNetworkData";
+const char kManagementReportHardwareData[] = "managementReportHardwareData";
 const char kManagementReportUsers[] = "managementReportUsers";
 const char kManagementReportCrashReports[] = "managementReportCrashReports";
 const char kManagementReportAppInfoAndActivity[] =
@@ -546,25 +546,28 @@
     return;
 
   // Elements appear on the page in the order they are added.
-  if (collector->ShouldReportActivityTimes()) {
+  if (collector->IsReportingActivityTimes()) {
     AddDeviceReportingElement(report_sources, kManagementReportActivityTimes,
                               DeviceReportingType::kDeviceActivity);
   } else {
-    if (collector->ShouldReportUsers()) {
+    if (collector->IsReportingUsers()) {
       AddDeviceReportingElement(report_sources, kManagementReportUsers,
                                 DeviceReportingType::kSupervisedUser);
     }
   }
-  if (collector->ShouldReportNetworkInterfaces()) {
-    AddDeviceReportingElement(report_sources,
-                              kManagementReportNetworkInterfaces,
+  if (collector->IsReportingNetworkData()) {
+    AddDeviceReportingElement(report_sources, kManagementReportNetworkData,
                               DeviceReportingType::kDevice);
   }
-  if (collector->ShouldReportCrashReportInfo()) {
+  if (collector->IsReportingHardwareData()) {
+    AddDeviceReportingElement(report_sources, kManagementReportHardwareData,
+                              DeviceReportingType::kDeviceStatistics);
+  }
+  if (collector->IsReportingCrashReportInfo()) {
     AddDeviceReportingElement(report_sources, kManagementReportCrashReports,
                               DeviceReportingType::kCrashReport);
   }
-  if (collector->ShouldReportAppInfoAndActivity()) {
+  if (collector->IsReportingAppInfoAndActivity()) {
     AddDeviceReportingElement(report_sources,
                               kManagementReportAppInfoAndActivity,
                               DeviceReportingType::kAppInfoAndActivity);
diff --git a/chrome/browser/ui/webui/management/management_ui_handler.h b/chrome/browser/ui/webui/management/management_ui_handler.h
index 9490409c..450824c 100644
--- a/chrome/browser/ui/webui/management/management_ui_handler.h
+++ b/chrome/browser/ui/webui/management/management_ui_handler.h
@@ -29,7 +29,8 @@
 // load time data.
 extern const char kManagementLogUploadEnabled[];
 extern const char kManagementReportActivityTimes[];
-extern const char kManagementReportNetworkInterfaces[];
+extern const char kManagementReportNetworkData[];
+extern const char kManagementReportHardwareData[];
 extern const char kManagementReportUsers[];
 extern const char kManagementReportCrashReports[];
 extern const char kManagementReportAppInfoAndActivity[];
diff --git a/chrome/browser/ui/webui/management/management_ui_handler_unittest.cc b/chrome/browser/ui/webui/management/management_ui_handler_unittest.cc
index 600a1f14..16d74ade2 100644
--- a/chrome/browser/ui/webui/management/management_ui_handler_unittest.cc
+++ b/chrome/browser/ui/webui/management/management_ui_handler_unittest.cc
@@ -132,26 +132,31 @@
   TestDeviceStatusCollector(PrefService* local_state,
                             bool report_activity_times,
                             bool report_nics,
+                            bool report_hardware_data,
                             bool report_users,
                             bool report_crash_info,
                             bool report_app_info_and_activity)
       : policy::DeviceStatusCollector(local_state, nullptr),
         report_activity_times_(report_activity_times),
         report_nics_(report_nics),
+        report_hardware_data_(report_hardware_data),
         report_users_(report_users),
         report_crash_info_(report_crash_info),
         report_app_info_and_activity_(report_app_info_and_activity) {}
   ~TestDeviceStatusCollector() override = default;
 
-  bool ShouldReportActivityTimes() const override {
+  bool IsReportingActivityTimes() const override {
     return report_activity_times_;
   }
-  bool ShouldReportNetworkInterfaces() const override { return report_nics_; }
-  bool ShouldReportUsers() const override { return report_users_; }
-  bool ShouldReportCrashReportInfo() const override {
+  bool IsReportingNetworkData() const override { return report_nics_; }
+  bool IsReportingHardwareData() const override {
+    return report_hardware_data_;
+  }
+  bool IsReportingUsers() const override { return report_users_; }
+  bool IsReportingCrashReportInfo() const override {
     return report_crash_info_;
   }
-  bool ShouldReportAppInfoAndActivity() const override {
+  bool IsReportingAppInfoAndActivity() const override {
     return report_app_info_and_activity_;
   }
 
@@ -163,6 +168,7 @@
  private:
   bool report_activity_times_;
   bool report_nics_;
+  bool report_hardware_data_;
   bool report_users_;
   bool report_crash_info_;
   bool report_app_info_and_activity_;
@@ -350,6 +356,7 @@
   struct TestConfig {
     bool report_activity_times;
     bool report_nics;
+    bool report_hardware_data;
     bool report_users;
     bool report_crash_info;
     bool report_app_info_and_activity;
@@ -371,6 +378,7 @@
   void ResetTestConfig(bool default_value) {
     setup_config_.report_activity_times = default_value;
     setup_config_.report_nics = default_value;
+    setup_config_.report_hardware_data = default_value;
     setup_config_.report_users = default_value;
     setup_config_.report_crash_info = default_value;
     setup_config_.report_app_info_and_activity = default_value;
@@ -434,8 +442,8 @@
     const TestDeviceStatusCollector* status_collector =
         new TestDeviceStatusCollector(
             &local_state_, GetTestConfig().report_activity_times,
-            GetTestConfig().report_nics, GetTestConfig().report_users,
-            GetTestConfig().report_crash_info,
+            GetTestConfig().report_nics, GetTestConfig().report_hardware_data,
+            GetTestConfig().report_users, GetTestConfig().report_crash_info,
             GetTestConfig().report_app_info_and_activity);
     settings_.device_settings()->SetTrustedStatus(
         chromeos::CrosSettingsProvider::TRUSTED);
@@ -1012,7 +1020,8 @@
   const base::Value info = SetUpForReportingInfo();
   const std::map<std::string, std::string> expected_elements = {
       {kManagementReportActivityTimes, "device activity"},
-      {kManagementReportNetworkInterfaces, "device"},
+      {kManagementReportNetworkData, "device"},
+      {kManagementReportHardwareData, "device statistics"},
       {kManagementReportCrashReports, "crash report"},
       {kManagementReportAppInfoAndActivity, "app info and activity"},
       {kManagementLogUploadEnabled, "logs"},
@@ -1035,7 +1044,8 @@
   const base::Value info = SetUpForReportingInfo();
   const std::map<std::string, std::string> expected_elements = {
       {kManagementReportActivityTimes, "device activity"},
-      {kManagementReportNetworkInterfaces, "device"},
+      {kManagementReportNetworkData, "device"},
+      {kManagementReportHardwareData, "device statistics"},
       {kManagementReportCrashReports, "crash report"},
       {kManagementReportAppInfoAndActivity, "app info and activity"},
       {kManagementLogUploadEnabled, "logs"},
diff --git a/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc b/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc
index 59bff84..32a8a1e 100644
--- a/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc
@@ -245,7 +245,7 @@
   input_method::InputMethodManager* ime_manager =
       input_method::InputMethodManager::Get();
   std::vector<std::string> input_method_ids =
-      ime_manager->GetActiveIMEState()->GetActiveInputMethodIds();
+      ime_manager->GetActiveIMEState()->GetEnabledInputMethodIds();
   std::vector<std::string> ime_languages;
   ime_manager->GetInputMethodUtil()->GetLanguageCodesFromInputMethodIds(
       input_method_ids, &ime_languages);
diff --git a/chrome/browser/ui/webui/settings/site_settings_helper.cc b/chrome/browser/ui/webui/settings/site_settings_helper.cc
index fe84b37d5..2e67f63 100644
--- a/chrome/browser/ui/webui/settings/site_settings_helper.cc
+++ b/chrome/browser/ui/webui/settings/site_settings_helper.cc
@@ -166,6 +166,7 @@
     {ContentSettingsType::FORMFILL_METADATA, nullptr},
     {ContentSettingsType::FEDERATED_IDENTITY_ACTIVE_SESSION, nullptr},
     {ContentSettingsType::AUTO_DARK_WEB_CONTENT, nullptr},
+    {ContentSettingsType::REQUEST_DESKTOP_SITE, nullptr},
 };
 
 static_assert(base::size(kContentSettingsTypeGroupNames) ==
diff --git a/chrome/browser/web_applications/extensions/web_app_policy_manager_unittest.cc b/chrome/browser/web_applications/extensions/web_app_policy_manager_unittest.cc
index 5097458..6ab0c1f 100644
--- a/chrome/browser/web_applications/extensions/web_app_policy_manager_unittest.cc
+++ b/chrome/browser/web_applications/extensions/web_app_policy_manager_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/run_loop.h"
 #include "base/test/bind.h"
 #include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/values.h"
 #include "chrome/browser/prefs/browser_prefs.h"
 #include "chrome/browser/web_applications/external_install_options.h"
@@ -27,6 +28,7 @@
 #include "chrome/browser/web_applications/web_app_helpers.h"
 #include "chrome/browser/web_applications/web_app_install_utils.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
+#include "chrome/common/chrome_features.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "chrome/test/base/scoped_testing_local_state.h"
@@ -229,7 +231,10 @@
 
 }  // namespace
 
-class WebAppPolicyManagerTest : public ChromeRenderViewHostTestHarness {
+enum class TestParam { kLacrosDisabled, kLacrosEnabled };
+
+class WebAppPolicyManagerTest : public ChromeRenderViewHostTestHarness,
+                                public testing::WithParamInterface<TestParam> {
  public:
   WebAppPolicyManagerTest()
       : testing_local_state_(TestingBrowserProcess::GetGlobal()) {}
@@ -238,6 +243,13 @@
   ~WebAppPolicyManagerTest() override = default;
 
   void SetUp() override {
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+    if (GetParam() == TestParam::kLacrosEnabled) {
+      scoped_feature_list_.InitAndEnableFeature(features::kWebAppsCrosapi);
+    } else if (GetParam() == TestParam::kLacrosDisabled) {
+      scoped_feature_list_.InitAndDisableFeature(features::kWebAppsCrosapi);
+    }
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
     ChromeRenderViewHostTestHarness::SetUp();
 
     fake_registry_controller_ =
@@ -330,6 +342,14 @@
   }
 
  protected:
+  bool ShouldSkipPWASpecificTest() {
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+    if (GetParam() == TestParam::kLacrosEnabled)
+      return true;
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+    return false;
+  }
+
   FakeExternallyManagedAppManager& externally_managed_app_manager() {
     return *fake_externally_managed_app_manager_;
   }
@@ -392,9 +412,12 @@
       fake_externally_managed_app_manager_;
   std::unique_ptr<TestSystemWebAppManager> test_system_app_manager_;
   std::unique_ptr<WebAppPolicyManager> web_app_policy_manager_;
+  base::test::ScopedFeatureList scoped_feature_list_;
 };
 
-TEST_F(WebAppPolicyManagerTest, NoPrefValues) {
+TEST_P(WebAppPolicyManagerTest, NoPrefValues) {
+  if (ShouldSkipPWASpecificTest())
+    return;
   policy_manager().Start();
 
   base::RunLoop().RunUntilIdle();
@@ -405,7 +428,9 @@
   ValidateEmptyWebAppSettingsPolicy();
 }
 
-TEST_F(WebAppPolicyManagerTest, NoForceInstalledApps) {
+TEST_P(WebAppPolicyManagerTest, NoForceInstalledApps) {
+  if (ShouldSkipPWASpecificTest())
+    return;
   profile()->GetPrefs()->Set(prefs::kWebAppInstallForceList,
                              base::Value(base::Value::Type::LIST));
 
@@ -417,7 +442,9 @@
   EXPECT_TRUE(install_requests.empty());
 }
 
-TEST_F(WebAppPolicyManagerTest, NoWebAppSettings) {
+TEST_P(WebAppPolicyManagerTest, NoWebAppSettings) {
+  if (ShouldSkipPWASpecificTest())
+    return;
   profile()->GetPrefs()->Set(prefs::kWebAppSettings,
                              base::Value(base::Value::Type::DICTIONARY));
 
@@ -426,7 +453,9 @@
   ValidateEmptyWebAppSettingsPolicy();
 }
 
-TEST_F(WebAppPolicyManagerTest, WebAppSettingsInvalidDefaultConfiguration) {
+TEST_P(WebAppPolicyManagerTest, WebAppSettingsInvalidDefaultConfiguration) {
+  if (ShouldSkipPWASpecificTest())
+    return;
   const char kWebAppSettingInvalidDefaultConfiguration[] = R"({
     "*" : {
       "run_on_os_login": "unsupported_value"
@@ -439,8 +468,10 @@
   ValidateEmptyWebAppSettingsPolicy();
 }
 
-TEST_F(WebAppPolicyManagerTest,
+TEST_P(WebAppPolicyManagerTest,
        WebAppSettingsInvalidDefaultConfigurationWithValidAppPolicy) {
+  if (ShouldSkipPWASpecificTest())
+    return;
   const char kWebAppSettingInvalidDefaultConfiguration[] = R"({
     "https://windowed.example/": {
       "run_on_os_login": "run_windowed"
@@ -464,7 +495,9 @@
       RunOnOsLoginPolicy::kAllowed);
 }
 
-TEST_F(WebAppPolicyManagerTest, WebAppSettingsNoDefaultConfiguration) {
+TEST_P(WebAppPolicyManagerTest, WebAppSettingsNoDefaultConfiguration) {
+  if (ShouldSkipPWASpecificTest())
+    return;
   const char kWebAppSettingNoDefaultConfiguration[] = R"({
     "https://windowed.example/": {
       "run_on_os_login": "run_windowed"
@@ -495,7 +528,9 @@
       RunOnOsLoginPolicy::kAllowed);
 }
 
-TEST_F(WebAppPolicyManagerTest, WebAppSettingsWithDefaultConfiguration) {
+TEST_P(WebAppPolicyManagerTest, WebAppSettingsWithDefaultConfiguration) {
+  if (ShouldSkipPWASpecificTest())
+    return;
   SetWebAppSettingsDictPref(kWebAppSettingWithDefaultConfiguration);
   policy_manager().Start();
   AwaitPolicyManagerRefreshPolicySettings();
@@ -511,7 +546,9 @@
       RunOnOsLoginPolicy::kBlocked);
 }
 
-TEST_F(WebAppPolicyManagerTest, TwoForceInstalledApps) {
+TEST_P(WebAppPolicyManagerTest, TwoForceInstalledApps) {
+  if (ShouldSkipPWASpecificTest())
+    return;
   // Add two sites, one that opens in a window and one that opens in a tab.
   base::Value list(base::Value::Type::LIST);
   list.Append(GetWindowedItem());
@@ -531,7 +568,9 @@
   EXPECT_EQ(install_requests, expected_install_options_list);
 }
 
-TEST_F(WebAppPolicyManagerTest, ForceInstallAppWithNoDefaultLaunchContainer) {
+TEST_P(WebAppPolicyManagerTest, ForceInstallAppWithNoDefaultLaunchContainer) {
+  if (ShouldSkipPWASpecificTest())
+    return;
   base::Value list(base::Value::Type::LIST);
   list.Append(GetNoContainerItem());
   profile()->GetPrefs()->Set(prefs::kWebAppInstallForceList, std::move(list));
@@ -548,8 +587,10 @@
   EXPECT_EQ(install_requests, expected_install_options_list);
 }
 
-TEST_F(WebAppPolicyManagerTest,
+TEST_P(WebAppPolicyManagerTest,
        ForceInstallAppWithDefaultCreateDesktopShortcut) {
+  if (ShouldSkipPWASpecificTest())
+    return;
   base::Value list(base::Value::Type::LIST);
   list.Append(GetCreateDesktopShortcutDefaultItem());
   profile()->GetPrefs()->Set(prefs::kWebAppInstallForceList, std::move(list));
@@ -567,7 +608,9 @@
   EXPECT_EQ(install_requests, expected_install_options_list);
 }
 
-TEST_F(WebAppPolicyManagerTest, ForceInstallAppWithCreateDesktopShortcut) {
+TEST_P(WebAppPolicyManagerTest, ForceInstallAppWithCreateDesktopShortcut) {
+  if (ShouldSkipPWASpecificTest())
+    return;
   base::Value list(base::Value::Type::LIST);
   list.Append(GetCreateDesktopShortcutFalseItem());
   list.Append(GetCreateDesktopShortcutTrueItem());
@@ -588,7 +631,9 @@
   EXPECT_EQ(install_requests, expected_install_options_list);
 }
 
-TEST_F(WebAppPolicyManagerTest, ForceInstallAppWithFallbackAppName) {
+TEST_P(WebAppPolicyManagerTest, ForceInstallAppWithFallbackAppName) {
+  if (ShouldSkipPWASpecificTest())
+    return;
   base::Value list(base::Value::Type::LIST);
   list.Append(GetFallbackAppNameItem());
   profile()->GetPrefs()->Set(prefs::kWebAppInstallForceList, std::move(list));
@@ -605,7 +650,9 @@
   EXPECT_EQ(install_requests, expected_install_options_list);
 }
 
-TEST_F(WebAppPolicyManagerTest, DynamicRefresh) {
+TEST_P(WebAppPolicyManagerTest, DynamicRefresh) {
+  if (ShouldSkipPWASpecificTest())
+    return;
   base::Value first_list(base::Value::Type::LIST);
   first_list.Append(GetWindowedItem());
   profile()->GetPrefs()->Set(prefs::kWebAppInstallForceList,
@@ -634,7 +681,9 @@
   EXPECT_EQ(install_requests, expected_install_options_list);
 }
 
-TEST_F(WebAppPolicyManagerTest, UninstallAppInstalledInPreviousSession) {
+TEST_P(WebAppPolicyManagerTest, UninstallAppInstalledInPreviousSession) {
+  if (ShouldSkipPWASpecificTest())
+    return;
   // Simulate two policy apps and a regular app that were installed in the
   // previous session.
   SimulatePreviouslyInstalledApp(GURL(kWindowedUrl),
@@ -666,7 +715,9 @@
 
 // Tests that we correctly uninstall an app that we installed in the same
 // session.
-TEST_F(WebAppPolicyManagerTest, UninstallAppInstalledInCurrentSession) {
+TEST_P(WebAppPolicyManagerTest, UninstallAppInstalledInCurrentSession) {
+  if (ShouldSkipPWASpecificTest())
+    return;
   policy_manager().Start();
   base::RunLoop().RunUntilIdle();
 
@@ -705,7 +756,9 @@
 }
 
 // Tests that we correctly reinstall a placeholder app.
-TEST_F(WebAppPolicyManagerTest, ReinstallPlaceholderApp) {
+TEST_P(WebAppPolicyManagerTest, ReinstallPlaceholderApp) {
+  if (ShouldSkipPWASpecificTest())
+    return;
   base::Value list(base::Value::Type::LIST);
   list.Append(GetWindowedItem());
   profile()->GetPrefs()->Set(prefs::kWebAppInstallForceList, std::move(list));
@@ -734,7 +787,9 @@
 
 // Tests that we correctly reinstall a placeholder app when the placeholder
 // is using a fallback name.
-TEST_F(WebAppPolicyManagerTest, ReinstallPlaceholderAppWithFallbackAppName) {
+TEST_P(WebAppPolicyManagerTest, ReinstallPlaceholderAppWithFallbackAppName) {
+  if (ShouldSkipPWASpecificTest())
+    return;
   base::Value list(base::Value::Type::LIST);
   list.Append(GetFallbackAppNameItem());
   profile()->GetPrefs()->Set(prefs::kWebAppInstallForceList, std::move(list));
@@ -761,7 +816,9 @@
   EXPECT_EQ(expected_options_list, install_options_list);
 }
 
-TEST_F(WebAppPolicyManagerTest, TryToInexistentPlaceholderApp) {
+TEST_P(WebAppPolicyManagerTest, TryToInexistentPlaceholderApp) {
+  if (ShouldSkipPWASpecificTest())
+    return;
   base::Value list(base::Value::Type::LIST);
   list.Append(GetWindowedItem());
   profile()->GetPrefs()->Set(prefs::kWebAppInstallForceList, std::move(list));
@@ -783,7 +840,9 @@
   EXPECT_EQ(expected_options_list, install_options_list);
 }
 
-TEST_F(WebAppPolicyManagerTest, SayRefreshTwoTimesQuickly) {
+TEST_P(WebAppPolicyManagerTest, SayRefreshTwoTimesQuickly) {
+  if (ShouldSkipPWASpecificTest())
+    return;
   policy_manager().Start();
   base::RunLoop().RunUntilIdle();
   // Add an app.
@@ -819,7 +878,9 @@
     EXPECT_EQ(it.second, GURL(kTabbedUrl));
 }
 
-TEST_F(WebAppPolicyManagerTest, InstallResultHistogram) {
+TEST_P(WebAppPolicyManagerTest, InstallResultHistogram) {
+  if (ShouldSkipPWASpecificTest())
+    return;
   base::HistogramTester histograms;
   policy_manager().Start();
   {
@@ -857,7 +918,7 @@
 }
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-TEST_F(WebAppPolicyManagerTest, DisableWebApps) {
+TEST_P(WebAppPolicyManagerTest, DisableWebApps) {
   policy_manager().Start();
   base::RunLoop().RunUntilIdle();
 
@@ -890,7 +951,9 @@
 }
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
-TEST_F(WebAppPolicyManagerTest, WebAppSettingsDynamicRefresh) {
+TEST_P(WebAppPolicyManagerTest, WebAppSettingsDynamicRefresh) {
+  if (ShouldSkipPWASpecificTest())
+    return;
   const char kWebAppSettingInitialConfiguration[] = R"({
     "https://windowed.example/": {
       "run_on_os_login": "blocked"
@@ -924,8 +987,10 @@
   policy_manager().RemoveObserver(&mock_observer);
 }
 
-TEST_F(WebAppPolicyManagerTest,
+TEST_P(WebAppPolicyManagerTest,
        WebAppSettingsApplyToExistingForceInstalledApp) {
+  if (ShouldSkipPWASpecificTest())
+    return;
   // Add two sites, one that opens in a window and one that opens in a tab.
   base::Value list(base::Value::Type::LIST);
   list.Append(GetWindowedItem());
@@ -968,7 +1033,9 @@
   policy_manager().RemoveObserver(&mock_observer);
 }
 
-TEST_F(WebAppPolicyManagerTest, WebAppSettingsForceInstallNewApps) {
+TEST_P(WebAppPolicyManagerTest, WebAppSettingsForceInstallNewApps) {
+  if (ShouldSkipPWASpecificTest())
+    return;
   // Apply WebAppSettings Policy
   MockWebAppPolicyManagerObserver mock_observer;
   policy_manager().AddObserver(&mock_observer);
@@ -1008,4 +1075,12 @@
   policy_manager().RemoveObserver(&mock_observer);
 }
 
+INSTANTIATE_TEST_SUITE_P(WebAppPolicyManagerTestWithParams,
+                         WebAppPolicyManagerTest,
+                         testing::Values(
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+                             TestParam::kLacrosDisabled,
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+                             TestParam::kLacrosEnabled));
+
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/policy/web_app_policy_manager.cc b/chrome/browser/web_applications/policy/web_app_policy_manager.cc
index f1775e8..115e27cf 100644
--- a/chrome/browser/web_applications/policy/web_app_policy_manager.cc
+++ b/chrome/browser/web_applications/policy/web_app_policy_manager.cc
@@ -11,6 +11,7 @@
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "base/containers/contains.h"
+#include "base/feature_list.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/syslog_logging.h"
@@ -26,6 +27,7 @@
 #include "chrome/browser/web_applications/web_app_install_utils.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/browser/web_applications/web_app_sync_bridge.h"
+#include "chrome/common/chrome_features.h"
 #include "chrome/common/pref_names.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/pref_service.h"
@@ -70,11 +72,19 @@
 }
 
 void WebAppPolicyManager::Start() {
+  // When Lacros is enabled, don't run PWA-specific logic in Ash.
+  // TODO(crbug.com/1251491): Consider factoring out logic that should only run
+  // in Ash into a separate class. This way, when running in Ash, we won't need
+  // to construct a WebAppPolicyManager.
+  bool enable_pwa_support = true;
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  enable_pwa_support = !base::FeatureList::IsEnabled(features::kWebAppsCrosapi);
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
   content::GetUIThreadTaskRunner({base::TaskPriority::BEST_EFFORT})
       ->PostTask(FROM_HERE,
                  base::BindOnce(
                      &WebAppPolicyManager::InitChangeRegistrarAndRefreshPolicy,
-                     weak_ptr_factory_.GetWeakPtr()));
+                     weak_ptr_factory_.GetWeakPtr(), enable_pwa_support));
 }
 
 void WebAppPolicyManager::ReinstallPlaceholderAppIfNecessary(const GURL& url) {
@@ -116,19 +126,22 @@
   registry->RegisterDictionaryPref(prefs::kWebAppSettings);
 }
 
-void WebAppPolicyManager::InitChangeRegistrarAndRefreshPolicy() {
+void WebAppPolicyManager::InitChangeRegistrarAndRefreshPolicy(
+    bool enable_pwa_support) {
   pref_change_registrar_.Init(pref_service_);
-  pref_change_registrar_.Add(
-      prefs::kWebAppInstallForceList,
-      base::BindRepeating(&WebAppPolicyManager::RefreshPolicyInstalledApps,
-                          weak_ptr_factory_.GetWeakPtr()));
-  pref_change_registrar_.Add(
-      prefs::kWebAppSettings,
-      base::BindRepeating(&WebAppPolicyManager::RefreshPolicySettings,
-                          weak_ptr_factory_.GetWeakPtr()));
+  if (enable_pwa_support) {
+    pref_change_registrar_.Add(
+        prefs::kWebAppInstallForceList,
+        base::BindRepeating(&WebAppPolicyManager::RefreshPolicyInstalledApps,
+                            weak_ptr_factory_.GetWeakPtr()));
+    pref_change_registrar_.Add(
+        prefs::kWebAppSettings,
+        base::BindRepeating(&WebAppPolicyManager::RefreshPolicySettings,
+                            weak_ptr_factory_.GetWeakPtr()));
 
-  RefreshPolicySettings();
-  RefreshPolicyInstalledApps();
+    RefreshPolicySettings();
+    RefreshPolicyInstalledApps();
+  }
   ObserveDisabledSystemFeaturesPolicy();
 }
 
diff --git a/chrome/browser/web_applications/policy/web_app_policy_manager.h b/chrome/browser/web_applications/policy/web_app_policy_manager.h
index fc17135a..3f2916d 100644
--- a/chrome/browser/web_applications/policy/web_app_policy_manager.h
+++ b/chrome/browser/web_applications/policy/web_app_policy_manager.h
@@ -125,7 +125,7 @@
     absl::optional<std::vector<blink::Manifest::ImageResource>> icons;
   };
 
-  void InitChangeRegistrarAndRefreshPolicy();
+  void InitChangeRegistrarAndRefreshPolicy(bool enable_pwa_support);
 
   void RefreshPolicyInstalledApps();
   void RefreshPolicySettings();
diff --git a/chrome/browser/window_placement/window_placement_permission_context_browsertest.cc b/chrome/browser/window_placement/window_placement_permission_context_browsertest.cc
index 5a74751..47183d1 100644
--- a/chrome/browser/window_placement/window_placement_permission_context_browsertest.cc
+++ b/chrome/browser/window_placement/window_placement_permission_context_browsertest.cc
@@ -29,7 +29,13 @@
 
 constexpr char kGetScreens[] = R"(
   (async () => {
-    try { const screens = await self.getScreens(); } catch {}
+    try { const screens = await self.getScreens(); } catch { return 'error'; }
+    return (await navigator.permissions.query({name:'window-placement'})).state;
+  })();
+)";
+
+constexpr char kCheckPermission[] = R"(
+  (async () => {
     return (await navigator.permissions.query({name:'window-placement'})).state;
   })();
 )";
@@ -59,6 +65,21 @@
     ASSERT_TRUE(https_test_server_->Start());
   }
 
+  // Awaits expiry of the navigator.userActivation signal on the active tab.
+  void WaitForUserActivationExpiry() {
+    const std::string await_activation_expiry_script = R"(
+      (async () => {
+        while (navigator.userActivation.isActive)
+          await new Promise(resolve => setTimeout(resolve, 1000));
+        return navigator.userActivation.isActive;
+      })();
+    )";
+    auto* tab = browser()->tab_strip_model()->GetActiveWebContents();
+    EXPECT_EQ(false, EvalJs(tab, await_activation_expiry_script,
+                            content::EXECUTE_SCRIPT_NO_USER_GESTURE));
+    EXPECT_FALSE(tab->HasRecentInteractiveInputEvent());
+  }
+
   net::EmbeddedTestServer* https_test_server() {
     return https_test_server_.get();
   }
@@ -101,28 +122,65 @@
   absl::optional<display::test::ScopedScreenOverride> screen_override_;
 };
 
+// Tests gesture requirements (a gesture is only needed to prompt the user).
+IN_PROC_BROWSER_TEST_F(WindowPlacementPermissionContextTest, GestureToPrompt) {
+  const GURL url(https_test_server()->GetURL("a.test", "/empty.html"));
+  EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
+  auto* tab = browser()->tab_strip_model()->GetActiveWebContents();
+
+  // Auto-dismiss the permission request, iff the prompt is shown.
+  permissions::PermissionRequestManager* permission_request_manager =
+      permissions::PermissionRequestManager::FromWebContents(tab);
+  permission_request_manager->set_auto_response_for_test(
+      permissions::PermissionRequestManager::ACCEPT_ALL);
+
+  // Calling getScreens() without a gesture or pre-existing permission will not
+  // prompt the user, and leaves the permission in the default "prompt" state.
+  EXPECT_FALSE(tab->GetMainFrame()->HasTransientUserActivation());
+  EXPECT_EQ("error",
+            EvalJs(tab, kGetScreens, content::EXECUTE_SCRIPT_NO_USER_GESTURE));
+  EXPECT_EQ("prompt", EvalJs(tab, kCheckPermission,
+                             content::EXECUTE_SCRIPT_NO_USER_GESTURE));
+
+  // Calling getScreens() with a gesture will show the prompt, and auto-accept.
+  EXPECT_FALSE(tab->GetMainFrame()->HasTransientUserActivation());
+  EXPECT_EQ("granted", EvalJs(tab, kGetScreens));
+  EXPECT_TRUE(tab->GetMainFrame()->HasTransientUserActivation());
+
+  // Calling getScreens() without a gesture, but with pre-existing permission,
+  // will succeed, since it does not need to prompt the user.
+  WaitForUserActivationExpiry();
+  EXPECT_FALSE(tab->GetMainFrame()->HasTransientUserActivation());
+  EXPECT_EQ("granted",
+            EvalJs(tab, kGetScreens, content::EXECUTE_SCRIPT_NO_USER_GESTURE));
+  EXPECT_FALSE(tab->GetMainFrame()->HasTransientUserActivation());
+}
+
 // Tests user activation after dimissing and denying the permission request.
 IN_PROC_BROWSER_TEST_F(WindowPlacementPermissionContextTest, DismissAndDeny) {
   const GURL url(https_test_server()->GetURL("a.test", "/empty.html"));
   EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
   auto* tab = browser()->tab_strip_model()->GetActiveWebContents();
   EXPECT_FALSE(tab->GetMainFrame()->HasTransientUserActivation());
-
   permissions::PermissionRequestManager* permission_request_manager =
       permissions::PermissionRequestManager::FromWebContents(tab);
 
-  // Auto-dismiss the permission request; user activation should not be granted.
-  permission_request_manager->set_auto_response_for_test(
-      permissions::PermissionRequestManager::DISMISS);
-  EXPECT_EQ("prompt",
-            EvalJs(tab, kGetScreens, content::EXECUTE_SCRIPT_NO_USER_GESTURE));
+  // Dismiss the prompt after activation expires, expect no activation.
+  ExecuteScriptAsync(tab, "getScreens()");
+  WaitForUserActivationExpiry();
+  ASSERT_TRUE(permission_request_manager->IsRequestInProgress());
+  permission_request_manager->Closing();
+  EXPECT_EQ("prompt", EvalJs(tab, kCheckPermission,
+                             content::EXECUTE_SCRIPT_NO_USER_GESTURE));
   EXPECT_FALSE(tab->GetMainFrame()->HasTransientUserActivation());
 
-  // Auto-deny the permission request; user activation should not be granted.
-  permission_request_manager->set_auto_response_for_test(
-      permissions::PermissionRequestManager::DENY_ALL);
-  EXPECT_EQ("denied",
-            EvalJs(tab, kGetScreens, content::EXECUTE_SCRIPT_NO_USER_GESTURE));
+  // Deny the prompt after activation expires, expect no activation.
+  ExecuteScriptAsync(tab, "getScreens()");
+  WaitForUserActivationExpiry();
+  ASSERT_TRUE(permission_request_manager->IsRequestInProgress());
+  permission_request_manager->Deny();
+  EXPECT_EQ("denied", EvalJs(tab, kCheckPermission,
+                             content::EXECUTE_SCRIPT_NO_USER_GESTURE));
   EXPECT_FALSE(tab->GetMainFrame()->HasTransientUserActivation());
 }
 
@@ -132,15 +190,16 @@
   EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
   auto* tab = browser()->tab_strip_model()->GetActiveWebContents();
   EXPECT_FALSE(tab->GetMainFrame()->HasTransientUserActivation());
-
   permissions::PermissionRequestManager* permission_request_manager =
       permissions::PermissionRequestManager::FromWebContents(tab);
 
-  // Auto-accept the permission request; user activation should be granted.
-  permission_request_manager->set_auto_response_for_test(
-      permissions::PermissionRequestManager::ACCEPT_ALL);
-  EXPECT_EQ("granted",
-            EvalJs(tab, kGetScreens, content::EXECUTE_SCRIPT_NO_USER_GESTURE));
+  // Accept the prompt after activation expires, expect an activation signal.
+  ExecuteScriptAsync(tab, "getScreens()");
+  WaitForUserActivationExpiry();
+  ASSERT_TRUE(permission_request_manager->IsRequestInProgress());
+  permission_request_manager->Accept();
+  EXPECT_EQ("granted", EvalJs(tab, kCheckPermission,
+                              content::EXECUTE_SCRIPT_NO_USER_GESTURE));
   EXPECT_TRUE(tab->GetMainFrame()->HasTransientUserActivation());
 }
 
@@ -158,9 +217,12 @@
   permissions::PermissionRequestManager* permission_request_manager =
       permissions::PermissionRequestManager::FromWebContents(tab);
 
-  permission_request_manager->set_auto_response_for_test(
-      permissions::PermissionRequestManager::ACCEPT_ALL);
-  EXPECT_EQ("granted", EvalJs(child, kGetScreens,
+  // Accept the prompt after activation expires, expect an activation signal.
+  ExecuteScriptAsync(child, "getScreens()");
+  WaitForUserActivationExpiry();
+  ASSERT_TRUE(permission_request_manager->IsRequestInProgress());
+  permission_request_manager->Accept();
+  EXPECT_EQ("granted", EvalJs(child, kCheckPermission,
                               content::EXECUTE_SCRIPT_NO_USER_GESTURE));
   EXPECT_TRUE(tab->GetMainFrame()->HasTransientUserActivation());
   EXPECT_TRUE(child->GetMainFrame()->HasTransientUserActivation());
@@ -186,13 +248,12 @@
   // PermissionRequestManager will accept any window placement permission
   // dialogs that appear. However, the window-placement permission is not
   // explicitly allowed on the iframe, so requests made by the child frame will
-  // be automatically denied before a prompt might be issued
+  // be automatically denied before a prompt might be issued.
   permission_request_manager->set_auto_response_for_test(
       permissions::PermissionRequestManager::ACCEPT_ALL);
-  EXPECT_EQ("denied", EvalJs(child, kGetScreens,
+  EXPECT_EQ("error", EvalJs(child, kGetScreens));
+  EXPECT_EQ("denied", EvalJs(child, kCheckPermission,
                              content::EXECUTE_SCRIPT_NO_USER_GESTURE));
-  EXPECT_FALSE(tab->GetMainFrame()->HasTransientUserActivation());
-  EXPECT_FALSE(child->GetMainFrame()->HasTransientUserActivation());
 }
 
 IN_PROC_BROWSER_TEST_F(WindowPlacementPermissionContextTest,
@@ -219,9 +280,12 @@
   permissions::PermissionRequestManager* permission_request_manager =
       permissions::PermissionRequestManager::FromWebContents(tab);
 
-  permission_request_manager->set_auto_response_for_test(
-      permissions::PermissionRequestManager::ACCEPT_ALL);
-  EXPECT_EQ("granted", EvalJs(child, kGetScreens,
+  // Accept the prompt after activation expires, expect an activation signal.
+  ExecuteScriptAsync(child, "getScreens()");
+  WaitForUserActivationExpiry();
+  ASSERT_TRUE(permission_request_manager->IsRequestInProgress());
+  permission_request_manager->Accept();
+  EXPECT_EQ("granted", EvalJs(child, kCheckPermission,
                               content::EXECUTE_SCRIPT_NO_USER_GESTURE));
   EXPECT_TRUE(tab->GetMainFrame()->HasTransientUserActivation());
   EXPECT_TRUE(child->GetMainFrame()->HasTransientUserActivation());
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index 49c3a210..35138b9 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1632419984-678da51b22078c3216dd3c6b35bf961963fd8ebc.profdata
+chrome-linux-main-1632441416-7a8329d97839093c9a4def992490e7bcafb28549.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index f5083da..4da8b7b 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1632419984-2753829d6c68ebb64dc4ba8688838157066c96b3.profdata
+chrome-mac-main-1632441416-cd8ce074cd62eabeea1ffbbb446738b9102d6a29.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index b1ee1694..dfffa0aa 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1632419984-487129f3332d781d1e2c38cec12ebd41e641b498.profdata
+chrome-win32-main-1632441416-a73451890a0e4bd9b30405b06c3d585120e1168b.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 190e410..766ff51 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1632419984-1922ebbc71b8a72ee3eea7730c287394dbd19ca4.profdata
+chrome-win64-main-1632441416-b736a7d5146599d1778a5da93020a143b20da207.profdata
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index 01287f2..a788437 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -768,14 +768,8 @@
     "PredictivePrefetchingAllowedOnAllConnectionTypes",
     base::FEATURE_ENABLED_BY_DEFAULT};
 
-const base::Feature kPrefixWebAppWindowsWithAppName {
-  "PrefixWebAppWindowsWithAppName",
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-      base::FEATURE_ENABLED_BY_DEFAULT
-#else
-      base::FEATURE_DISABLED_BY_DEFAULT
-#endif
-};
+const base::Feature kPrefixWebAppWindowsWithAppName{
+    "PrefixWebAppWindowsWithAppName", base::FEATURE_ENABLED_BY_DEFAULT};
 
 // Allows Chrome to do preconnect when prerender fails.
 const base::Feature kPrerenderFallbackToPreconnect{
@@ -879,7 +873,7 @@
 // TODO(alexmos): Move this and the other site isolation features below to
 // browser_features, as they are only used on the browser side.
 const base::Feature kSitePerProcess {
-  "site-per-process",
+  "SitePerProcess",
 #if defined(OS_ANDROID)
       base::FEATURE_DISABLED_BY_DEFAULT
 #else
diff --git a/chrome/common/extensions/api/scripting.idl b/chrome/common/extensions/api/scripting.idl
index ad370c24..e246b23 100644
--- a/chrome/common/extensions/api/scripting.idl
+++ b/chrome/common/extensions/api/scripting.idl
@@ -136,6 +136,9 @@
     // Specifies when JavaScript files are injected into the web page. The
     // preferred and default value is <code>document_idle</code>.
     extensionTypes.RunAt? runAt;
+    // Specifies if this content script will persist into future sessions. The
+    // default is true.
+    boolean? persistAcrossSessions;
   };
 
   // An object used to filter content scripts for
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index fe10937..844931f6 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -2753,6 +2753,7 @@
         "../browser/ui/media_router/presentation_receiver_window_controller_browsertest.cc",
         "../browser/ui/views/autofill/autofill_popup_base_view_browsertest.cc",
         "../browser/ui/views/autofill/payments/autofill_error_dialog_view_native_views_browsertest.cc",
+        "../browser/ui/views/autofill/payments/card_unmask_authentication_selection_dialog_browsertest.cc",
         "../browser/ui/views/autofill/payments/card_unmask_prompt_view_tester_views.cc",
         "../browser/ui/views/autofill/payments/card_unmask_prompt_view_tester_views.h",
         "../browser/ui/views/autofill/payments/credit_card_access_manager_browsertest.cc",
@@ -6240,6 +6241,7 @@
       "//chrome/browser/share/core:share_targets_unittest",
       "//components/media_router/common:test_support",
       "//components/services/app_service/public/cpp:publisher",
+      "//components/services/app_service/public/cpp:test_support",
       "//components/soda:constants",
       "//services/network:test_support",
     ]
diff --git a/chrome/test/base/test_browser_window.cc b/chrome/test/base/test_browser_window.cc
index 963517d..93e34c4 100644
--- a/chrome/test/base/test_browser_window.cc
+++ b/chrome/test/base/test_browser_window.cc
@@ -222,7 +222,8 @@
 TestBrowserWindow::ShowQRCodeGeneratorBubble(
     content::WebContents* contents,
     qrcode_generator::QRCodeGeneratorBubbleController* controller,
-    const GURL& url) {
+    const GURL& url,
+    bool show_back_button) {
   return nullptr;
 }
 
diff --git a/chrome/test/base/test_browser_window.h b/chrome/test/base/test_browser_window.h
index 63cfe876..f582ce9b 100644
--- a/chrome/test/base/test_browser_window.h
+++ b/chrome/test/base/test_browser_window.h
@@ -143,7 +143,8 @@
   qrcode_generator::QRCodeGeneratorBubbleView* ShowQRCodeGeneratorBubble(
       content::WebContents* contents,
       qrcode_generator::QRCodeGeneratorBubbleController* controller,
-      const GURL& url) override;
+      const GURL& url,
+      bool show_back_button) override;
 #if !defined(OS_ANDROID)
   sharing_hub::ScreenshotCapturedBubble* ShowScreenshotCapturedBubble(
       content::WebContents* contents,
diff --git a/chrome/test/data/extensions/api_test/scripting/dynamic_scripts/worker.js b/chrome/test/data/extensions/api_test/scripting/dynamic_scripts/worker.js
index 0addc653..c2a2683 100644
--- a/chrome/test/data/extensions/api_test/scripting/dynamic_scripts/worker.js
+++ b/chrome/test/data/extensions/api_test/scripting/dynamic_scripts/worker.js
@@ -30,7 +30,8 @@
         id: 'GRS_2',
         matches: ['*://asdfasdf.com/*'],
         js: ['/dynamic_1.js'],
-        runAt: 'document_end'
+        runAt: 'document_end',
+        persistAcrossSessions: false
       }
     ];
 
@@ -44,7 +45,8 @@
         css: ['nothing.css'],
         allFrames: true,
         runAt: 'document_idle',
-        matchOriginAsFallback: false
+        matchOriginAsFallback: false,
+        persistAcrossSessions: true
       },
       {
         id: 'GRS_2',
@@ -52,7 +54,8 @@
         js: ['dynamic_1.js'],
         allFrames: false,
         runAt: 'document_end',
-        matchOriginAsFallback: false
+        matchOriginAsFallback: false,
+        persistAcrossSessions: false
       }
     ];
 
@@ -443,7 +446,8 @@
       matches: ['*://hostperms.com/*'],
       excludeMatches: ['*://def.com/*'],
       js: ['inject_element_2.js'],
-      allFrames: false
+      allFrames: false,
+      persistAcrossSessions: false
     }];
 
     await chrome.scripting.registerContentScripts(scripts);
@@ -477,7 +481,8 @@
       css: ['nothing.css'],
       runAt: 'document_end',
       allFrames: false,
-      matchOriginAsFallback: false
+      matchOriginAsFallback: false,
+      persistAcrossSessions: false
     }];
 
     scripts = await chrome.scripting.getRegisteredContentScripts();
@@ -519,7 +524,8 @@
       js: ['inject_element.js'],
       runAt: 'document_end',
       allFrames: false,
-      matchOriginAsFallback: false
+      matchOriginAsFallback: false,
+      persistAcrossSessions: true
     }];
 
     scripts = await chrome.scripting.getRegisteredContentScripts();
@@ -568,7 +574,8 @@
       js: ['inject_element.js'],
       runAt: 'document_end',
       allFrames: false,
-      matchOriginAsFallback: false
+      matchOriginAsFallback: false,
+      persistAcrossSessions: true
     }];
 
     scripts = await chrome.scripting.getRegisteredContentScripts();
@@ -607,7 +614,8 @@
       js: ['inject_element.js'],
       runAt: 'document_end',
       allFrames: false,
-      matchOriginAsFallback: false
+      matchOriginAsFallback: false,
+      persistAcrossSessions: true
     }];
 
     scripts = await chrome.scripting.getRegisteredContentScripts();
diff --git a/chrome/test/data/extensions/api_test/scripting/persistent_dynamic_scripts/inject_element.js b/chrome/test/data/extensions/api_test/scripting/persistent_dynamic_scripts/inject_element.js
new file mode 100644
index 0000000..dcaf9f2
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/scripting/persistent_dynamic_scripts/inject_element.js
@@ -0,0 +1,7 @@
+// 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.
+
+var div = document.createElement('div');
+div.id = 'injected';
+document.body.appendChild(div);
diff --git a/chrome/test/data/extensions/api_test/scripting/persistent_dynamic_scripts/inject_element_2.js b/chrome/test/data/extensions/api_test/scripting/persistent_dynamic_scripts/inject_element_2.js
new file mode 100644
index 0000000..49b79ac
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/scripting/persistent_dynamic_scripts/inject_element_2.js
@@ -0,0 +1,7 @@
+// 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.
+
+var div = document.createElement('div');
+div.id = 'injected_2';
+document.body.appendChild(div);
diff --git a/chrome/test/data/extensions/api_test/scripting/persistent_dynamic_scripts/manifest.json b/chrome/test/data/extensions/api_test/scripting/persistent_dynamic_scripts/manifest.json
new file mode 100644
index 0000000..c2e9180
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/scripting/persistent_dynamic_scripts/manifest.json
@@ -0,0 +1,12 @@
+{
+  "manifest_version": 3,
+  "name": "Persistent dynamic content script test extension",
+  "version": "0.1",
+  "description": "Tests that dynamic scripts can persist across sessions",
+  "background": {
+    "service_worker": "worker.js",
+    "type": "module"
+  },
+  "permissions": ["scripting", "tabs"],
+  "host_permissions": ["*://hostperms.com/*"]
+}
diff --git a/chrome/test/data/extensions/api_test/scripting/persistent_dynamic_scripts/worker.js b/chrome/test/data/extensions/api_test/scripting/persistent_dynamic_scripts/worker.js
new file mode 100644
index 0000000..d836fef
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/scripting/persistent_dynamic_scripts/worker.js
@@ -0,0 +1,143 @@
+// 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.
+
+import {openTab} from '/_test_resources/test_util/tabs_util.js';
+
+function getInjectedElementIds() {
+  let childIds = [];
+  for (const child of document.body.children)
+    childIds.push(child.id);
+  return childIds.sort();
+};
+
+// For the first session, register one persistent script and one session script.
+async function runFirstSession() {
+  let scripts = [
+    {
+      id: 'inject_element',
+      matches: ['*://*/*'],
+      js: ['inject_element.js'],
+      runAt: 'document_end'
+    },
+    {
+      id: 'inject_element_2',
+      matches: ['*://*/*'],
+      js: ['inject_element_2.js'],
+      runAt: 'document_end',
+      persistAcrossSessions: false
+    }
+  ];
+
+  await chrome.scripting.registerContentScripts(scripts);
+
+  const config = await chrome.test.getConfig();
+  const url = `http://hostperms.com:${config.testServer.port}/simple.html`;
+
+  let tab = await openTab(url);
+  let results = await chrome.scripting.executeScript(
+      {target: {tabId: tab.id}, func: getInjectedElementIds});
+
+  chrome.test.assertEq(1, results.length);
+  chrome.test.assertEq(['injected', 'injected_2'], results[0].result);
+
+  chrome.test.succeed();
+}
+
+// For the second session, verify that the persistent script registered from the
+// first session will still be injected into pages. Then replace the persistent
+// script. We also register a persistent script, then update it to not persist.
+async function runSecondSession() {
+  let scripts = await chrome.scripting.getRegisteredContentScripts();
+
+  const expectedScripts = [{
+    id: 'inject_element',
+    matches: ['*://*/*'],
+    js: ['inject_element.js'],
+    allFrames: false,
+    runAt: 'document_end',
+    matchOriginAsFallback: false,
+    persistAcrossSessions: true
+  }];
+
+  chrome.test.assertEq(expectedScripts, scripts);
+
+  const config = await chrome.test.getConfig();
+  const url = `http://hostperms.com:${config.testServer.port}/simple.html`;
+
+  let tab = await openTab(url);
+  let results = await chrome.scripting.executeScript(
+      {target: {tabId: tab.id}, func: getInjectedElementIds});
+
+  chrome.test.assertEq(1, results.length);
+  chrome.test.assertEq(['injected'], results[0].result);
+
+  await chrome.scripting.unregisterContentScripts();
+
+  scripts = [
+    {
+      id: 'inject_element_2',
+      matches: ['*://*/*'],
+      js: ['inject_element_2.js'],
+      runAt: 'document_end',
+      persistAcrossSessions: false
+    },
+    {id: 'inject_element_3', matches: ['*://*/*'], js: ['inject_element.js']}
+  ];
+
+  await chrome.scripting.registerContentScripts(scripts);
+
+  const updates = [
+    {id: 'inject_element_2', persistAcrossSessions: true},
+    {id: 'inject_element_3', persistAcrossSessions: false}
+  ];
+
+  await chrome.scripting.updateContentScripts(updates);
+  chrome.test.succeed();
+}
+
+// Verify that the removal and addition of a persistent script from the last
+// session is applied into this session, and that updating a script's
+// persistAcrossSessions flag to false will not persist it into this session.
+async function runThirdSession() {
+  let scripts = await chrome.scripting.getRegisteredContentScripts();
+
+  const expectedScripts = [{
+    id: 'inject_element_2',
+    matches: ['*://*/*'],
+    js: ['inject_element_2.js'],
+    allFrames: false,
+    runAt: 'document_end',
+    matchOriginAsFallback: false,
+    persistAcrossSessions: true
+  }];
+
+  chrome.test.assertEq(expectedScripts, scripts);
+
+  const config = await chrome.test.getConfig();
+  const url = `http://hostperms.com:${config.testServer.port}/simple.html`;
+  let tab = await openTab(url);
+  let results = await chrome.scripting.executeScript(
+      {target: {tabId: tab.id}, func: getInjectedElementIds});
+
+  chrome.test.assertEq(1, results.length);
+  chrome.test.assertEq(['injected_2'], results[0].result);
+
+  chrome.test.succeed();
+}
+
+// Attach a dummy listener for onStartup to kick off the service worker on
+// every browser start, so we call chrome.test.sendMessage
+chrome.runtime.onStartup.addListener(async () => {});
+
+chrome.test.getConfig(config => {
+  const testName = config.customArg;
+  if (testName === 'PRE_PRE_PersistentDynamicContentScripts')
+    runFirstSession();
+  else if (testName === 'PRE_PersistentDynamicContentScripts')
+    runSecondSession();
+  else if (testName === 'PersistentDynamicContentScripts')
+    runThirdSession();
+  else
+    chrome.test.fail();
+});
diff --git a/chrome/test/data/webui/chromeos/diagnostics/BUILD.gn b/chrome/test/data/webui/chromeos/diagnostics/BUILD.gn
index cf8ae86..9c4f5197a 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/BUILD.gn
+++ b/chrome/test/data/webui/chromeos/diagnostics/BUILD.gn
@@ -18,6 +18,7 @@
     ":data_point_test",
     ":diagnostics_app_test",
     ":diagnostics_app_unified_test",
+    ":diagnostics_sticky_banner_test",
     ":diagnostics_test_utils",
     ":diagnostics_utils_test",
     ":fake_network_health_provider_test",
@@ -117,6 +118,15 @@
   externs_list = [ "$externs_path/mocha-2.5.js" ]
 }
 
+js_library("diagnostics_sticky_banner_test") {
+  deps = [
+    "../..:chai_assert",
+    "../..:test_util",
+    "//ash/webui/diagnostics_ui/resources:diagnostics_sticky_banner",
+  ]
+  externs_list = [ "$externs_path/mocha-2.5.js" ]
+}
+
 js_library("diagnostics_app_unified_test") {
   deps = []
   externs_list = [ "$externs_path/mocha-2.5.js" ]
diff --git a/chrome/test/data/webui/chromeos/diagnostics/diagnostics_app_test.js b/chrome/test/data/webui/chromeos/diagnostics/diagnostics_app_test.js
index ac65e47b..af21af8 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/diagnostics_app_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/diagnostics_app_test.js
@@ -6,7 +6,7 @@
 
 import {DiagnosticsBrowserProxyImpl} from 'chrome://diagnostics/diagnostics_browser_proxy.js';
 import {BatteryChargeStatus, BatteryHealth, BatteryInfo, CpuUsage, MemoryUsage, SystemInfo} from 'chrome://diagnostics/diagnostics_types.js';
-import {fakeBatteryChargeStatus, fakeBatteryHealth, fakeBatteryInfo, fakeCellularNetwork, fakeCpuUsage, fakeEthernetNetwork, fakeMemoryUsage, fakeNetworkGuidInfoList, fakePowerRoutineResults, fakeRoutineResults, fakeSystemInfo, fakeSystemInfoWithoutBattery, fakeWifiNetwork} from 'chrome://diagnostics/fake_data.js';
+import {fakeBatteryChargeStatus, fakeBatteryHealth, fakeBatteryInfo, fakeCellularNetwork, fakeCpuUsage, fakeEthernetNetwork, fakeMemoryUsage, fakeNetworkGuidInfoList, fakePowerRoutineResults, fakeRoutineResults, fakeSystemInfo, fakeWifiNetwork} from 'chrome://diagnostics/fake_data.js';
 import {FakeNetworkHealthProvider} from 'chrome://diagnostics/fake_network_health_provider.js';
 import {FakeSystemDataProvider} from 'chrome://diagnostics/fake_system_data_provider.js';
 import {FakeSystemRoutineController} from 'chrome://diagnostics/fake_system_routine_controller.js';
@@ -66,6 +66,48 @@
     networkHealthProvider.reset();
   });
 
+  /** @return {!HTMLElement} */
+  function getCautionBanner() {
+    assertTrue(!!page);
+
+    return /** @type {!HTMLElement} */ (page.$$('diagnostics-sticky-banner'));
+  }
+
+  /** @return {!HTMLElement} */
+  function getCautionBannerMessage() {
+    return /** @type {!HTMLElement} */ (
+        getCautionBanner().shadowRoot.querySelector('#bannerMsg'));
+  }
+
+  /**
+   * Triggers 'dismiss-caution-banner' custom event.
+   * @return {!Promise}
+   */
+  function triggerDismissBannerEvent() {
+    window.dispatchEvent(new CustomEvent('dismiss-caution-banner', {
+      bubbles: true,
+      composed: true,
+    }));
+
+    return flushTasks();
+  }
+
+  /**
+   * Triggers 'show-caution-banner' custom event with correctly configured event
+   * detail object based on provided message.
+   * @param {string} message
+   * @return {!Promise}
+   */
+  function triggerShowBannerEvent(message) {
+    window.dispatchEvent(new CustomEvent('show-caution-banner', {
+      bubbles: true,
+      composed: true,
+      detail: {message},
+    }));
+
+    return flushTasks();
+  }
+
   /**
    * @param {!SystemInfo} systemInfo
    * @param {!Array<!BatteryChargeStatus>} batteryChargeStatus
@@ -111,7 +153,28 @@
                 dx_utils.getNavigationViewPanelElement(page, 'system');
             assertTrue(!!systemPage);
             assertTrue(isVisible(systemPage));
+            assertFalse(isVisible(getCautionBanner()));
           });
     });
+
+    test('BannerVisibliblityTogglesWithEvents', () => {
+      const bannerMessage = 'Diagnostics Banner Message';
+      return initializeDiagnosticsApp(
+                 fakeSystemInfo, fakeBatteryChargeStatus, fakeBatteryHealth,
+                 fakeBatteryInfo, fakeCpuUsage, fakeMemoryUsage)
+          .then(() => {
+            assertFalse(isVisible(getCautionBanner()));
+
+            return triggerShowBannerEvent(bannerMessage);
+          })
+          .then(() => {
+            assertTrue(isVisible(getCautionBanner()));
+            dx_utils.assertElementContainsText(
+                getCautionBannerMessage(), bannerMessage);
+
+            return triggerDismissBannerEvent();
+          })
+          .then(() => assertFalse(isVisible(getCautionBanner())));
+    });
   }
 }
diff --git a/chrome/test/data/webui/chromeos/diagnostics/diagnostics_app_unified_test.js b/chrome/test/data/webui/chromeos/diagnostics/diagnostics_app_unified_test.js
index 78446b3..843e4c3 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/diagnostics_app_unified_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/diagnostics_app_unified_test.js
@@ -11,6 +11,7 @@
 import {cpuCardTestSuite} from './cpu_card_test.js';
 import {dataPointTestSuite} from './data_point_test.js';
 import {appTestSuite} from './diagnostics_app_test.js';
+import {diagnosticsStickyBannerTestSuite} from './diagnostics_sticky_banner_test.js';
 import {diagnosticsUtilsTestSuite} from './diagnostics_utils_test.js';
 import {ethernetInfoTestSuite} from './ethernet_info_test.js';
 import {fakeNetworkHealthProviderTestSuite} from './fake_network_health_provider_test.js';
@@ -58,6 +59,7 @@
 runSuite('ConnectivityCard', connectivityCardTestSuite, 'network');
 runSuite('CpuCard', cpuCardTestSuite);
 runSuite('DataPoint', dataPointTestSuite);
+runSuite('DiagnosticsStickyBanner', diagnosticsStickyBannerTestSuite);
 runSuite('DiagnosticsUtils', diagnosticsUtilsTestSuite);
 runSuite('EthernetInfo', ethernetInfoTestSuite, 'network');
 runSuite('FakeMojoInterface', fakeMojoProviderTestSuite);
diff --git a/chrome/test/data/webui/chromeos/diagnostics/diagnostics_browsertest.js b/chrome/test/data/webui/chromeos/diagnostics/diagnostics_browsertest.js
index f5041a0..e0f56a9 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/diagnostics_browsertest.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/diagnostics_browsertest.js
@@ -85,6 +85,7 @@
   'ConnectivityCard',
   'CpuCard',
   'DataPoint',
+  'DiagnosticsStickyBanner',
   'DiagnosticsUtils',
   'EthernetInfo',
   'FakeMojoInterface',
diff --git a/chrome/test/data/webui/chromeos/diagnostics/diagnostics_sticky_banner_test.js b/chrome/test/data/webui/chromeos/diagnostics/diagnostics_sticky_banner_test.js
new file mode 100644
index 0000000..559c1f9
--- /dev/null
+++ b/chrome/test/data/webui/chromeos/diagnostics/diagnostics_sticky_banner_test.js
@@ -0,0 +1,206 @@
+// 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.
+
+import {DiagnosticsStickyBannerElement} from 'chrome://diagnostics/diagnostics_sticky_banner.js';
+
+import {assertEquals, assertFalse, assertNotEquals, assertTrue} from '../../chai_assert.js';
+import {flushTasks, isVisible} from '../../test_util.js';
+
+import * as dx_utils from './diagnostics_test_utils.js';
+
+export function diagnosticsStickyBannerTestSuite() {
+  /** @type {?DiagnosticsStickyBannerElement} */
+  let diagnosticsStickyBannerElement = null;
+
+  setup(() => {
+    document.body.innerHTML = '';
+  });
+
+  teardown(() => {
+    diagnosticsStickyBannerElement.remove();
+    diagnosticsStickyBannerElement = null;
+  });
+
+  /** @return {!Promise} */
+  function initializeDiagnosticsStickyBanner() {
+    assertFalse(!!diagnosticsStickyBannerElement);
+
+    // Add the sticky banner to the DOM.
+    diagnosticsStickyBannerElement =
+        /** @type {!DiagnosticsStickyBannerElement} */ (
+            document.createElement('diagnostics-sticky-banner'));
+    assertTrue(!!diagnosticsStickyBannerElement);
+    document.body.appendChild(diagnosticsStickyBannerElement);
+
+    return flushTasks();
+  }
+
+  /** @return {!Element} */
+  function getBanner() {
+    assertTrue(!!diagnosticsStickyBannerElement);
+
+    return /** @type {!Element} */ (
+        diagnosticsStickyBannerElement.shadowRoot.querySelector('#banner'));
+  }
+
+  /** @return {!Element} */
+  function getBannerMsg() {
+    assertTrue(!!diagnosticsStickyBannerElement);
+
+    return /** @type {!Element} */ (
+        diagnosticsStickyBannerElement.shadowRoot.querySelector('#bannerMsg'));
+  }
+
+  /**
+   * @suppress {visibility}
+   * @return {string}
+   */
+  function getScrollClass_() {
+    return diagnosticsStickyBannerElement.scrollingClass_;
+  }
+
+  /**
+   * @suppress {visibility}
+   * @return {number}
+   */
+  function getScrollTimerId_() {
+    return diagnosticsStickyBannerElement.scrollTimerId_;
+  }
+
+  /**
+   * @param {string} message
+   * @return {!Promise}
+   */
+  function setBannerMessage(message) {
+    assertTrue(!!diagnosticsStickyBannerElement);
+    diagnosticsStickyBannerElement.bannerMessage = message;
+
+    return flushTasks();
+  }
+
+  /**
+   * Triggers 'dismiss-caution-banner' custom event.
+   * @return {!Promise}
+   */
+  function triggerDismissBannerEvent() {
+    window.dispatchEvent(new CustomEvent('dismiss-caution-banner', {
+      bubbles: true,
+      composed: true,
+    }));
+
+    return flushTasks();
+  }
+
+  /**
+   * Triggers 'scroll' event.
+   * @return {!Promise}
+   */
+  function triggerScrollEvent() {
+    window.dispatchEvent(new CustomEvent('scroll', {
+      bubbles: true,
+      composed: true,
+    }));
+
+    return flushTasks();
+  }
+
+  /**
+   * Triggers 'show-caution-banner' custom event with correctly configured event
+   * detail object based on provided message.
+   * @param {string} message
+   * @return {!Promise}
+   */
+  function triggerShowBannerEvent(message) {
+    window.dispatchEvent(new CustomEvent('show-caution-banner', {
+      bubbles: true,
+      composed: true,
+      detail: {message},
+    }));
+
+    return flushTasks();
+  }
+
+  test('BannerInitializedCorrectly', () => {
+    return initializeDiagnosticsStickyBanner().then(() => {
+      assertFalse(isVisible(getBanner()));
+    });
+  });
+
+  test('BannerShowsWhenMessageSetToNonEmptyString', () => {
+    const testMessage = 'Infomational banner';
+    return initializeDiagnosticsStickyBanner()
+        .then(() => setBannerMessage(testMessage))
+        .then(() => {
+          assertTrue(isVisible(getBanner()));
+          dx_utils.assertElementContainsText(getBannerMsg(), testMessage);
+        })
+        .then(() => setBannerMessage(''))
+        .then(() => {
+          assertFalse(isVisible(getBanner()));
+          dx_utils.assertElementDoesNotContainText(getBannerMsg(), testMessage);
+        });
+  });
+
+  test('BannerHandlesShowCautionBannerEvent', () => {
+    const bannerText1 = 'Infomational banner 1';
+    const bannerText2 = 'Infomational banner 2';
+    return initializeDiagnosticsStickyBanner()
+        .then(() => triggerShowBannerEvent(bannerText1))
+        .then(() => {
+          assertEquals(
+              bannerText1, diagnosticsStickyBannerElement.bannerMessage);
+          assertTrue(isVisible(getBanner()));
+          dx_utils.assertElementContainsText(getBannerMsg(), bannerText1);
+        })
+        .then(() => triggerShowBannerEvent(bannerText2))
+        .then(() => {
+          assertEquals(
+              bannerText2, diagnosticsStickyBannerElement.bannerMessage);
+          assertTrue(isVisible(getBanner()));
+          dx_utils.assertElementContainsText(getBannerMsg(), bannerText2);
+        });
+  });
+
+  test('BannerHandlesDismissCautionBannerEvent', () => {
+    const testMessage = 'Infomational banner';
+    return initializeDiagnosticsStickyBanner()
+        .then(() => triggerShowBannerEvent(testMessage))
+        .then(() => {
+          dx_utils.assertElementContainsText(getBannerMsg(), testMessage);
+        })
+        .then(() => triggerDismissBannerEvent())
+        .then(() => {
+          assertEquals('', diagnosticsStickyBannerElement.bannerMessage);
+          assertFalse(isVisible(getBanner()));
+          dx_utils.assertElementDoesNotContainText(getBannerMsg(), testMessage);
+        });
+  });
+
+  test('BannerHandlesScrollEvent', () => {
+    return initializeDiagnosticsStickyBanner()
+        .then(() => {
+          dx_utils.assertTextDoesNotContain(getScrollClass_(), 'elevation-2');
+          assertEquals(-1, getScrollTimerId_());
+        })
+        .then(() => triggerScrollEvent())
+        // Do not update if no banner message is set.
+        .then(() => {
+          dx_utils.assertTextDoesNotContain(getScrollClass_(), 'elevation-2');
+          assertEquals(-1, getScrollTimerId_());
+        })
+        .then(() => setBannerMessage('Test Message'))
+        .then(() => triggerScrollEvent())
+        // First scroll initializes but does not update class.
+        .then(() => {
+          dx_utils.assertTextDoesNotContain(getScrollClass_(), 'elevation-2');
+          assertNotEquals(-1, getScrollTimerId_());
+        })
+        // Subsequent scrolls ensure class name is set.
+        .then(() => triggerScrollEvent())
+        .then(() => {
+          dx_utils.assertTextContains(getScrollClass_(), 'elevation-2');
+          assertNotEquals(-1, getScrollTimerId_());
+        });
+  });
+}
diff --git a/chrome/test/data/webui/chromeos/diagnostics/network_troubleshooting_test.js b/chrome/test/data/webui/chromeos/diagnostics/network_troubleshooting_test.js
index b40a338a..af394e91 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/network_troubleshooting_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/network_troubleshooting_test.js
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TroubleshootingInfo} from 'chrome://diagnostics/diagnostics_types.js';
 import {NetworkTroubleshootingElement} from 'chrome://diagnostics/network_troubleshooting.js';
-import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 
 import {assertFalse, assertTrue} from '../../chai_assert.js';
 import {flushTasks} from '../../test_util.js';
@@ -24,10 +24,10 @@
   });
 
   /**
-   * @param {string} type
+   * @param {!TroubleshootingInfo} info
    * @return {!Promise}
    */
-  function initializeNetworkTroubleshooting(type) {
+  function initializeNetworkTroubleshooting(info) {
     assertFalse(!!networkTroubleshootingElement);
 
     // Add the network troubleshooting element to the DOM.
@@ -35,45 +35,27 @@
         /** @type {!NetworkTroubleshootingElement} */ (
             document.createElement('network-troubleshooting'));
     assertTrue(!!networkTroubleshootingElement);
-    networkTroubleshootingElement.networkType = type;
+    networkTroubleshootingElement.troubleshootingInfo = info;
     document.body.appendChild(networkTroubleshootingElement);
 
     return flushTasks();
   }
 
-  /**
-   * @param {boolean} disabled
-   * @return {!Promise}
-   */
-  function changeDisabledState(disabled) {
-    networkTroubleshootingElement.disabled = disabled;
-    return flushTasks();
-  }
-
-  test('CorrectNetworkTypeDisplayedInMessage', () => {
-    return initializeNetworkTroubleshooting(loadTimeData.getString('wifiLabel'))
+  test('CorrectInfoDisplayedInTroubleshootingElement', () => {
+    return initializeNetworkTroubleshooting({
+             header: 'header',
+             linkText: 'linkText',
+             url: 'https://google.com',
+           })
         .then(() => {
           dx_utils.assertElementContainsText(
               networkTroubleshootingElement.shadowRoot.querySelector(
-                  '#troubleConnectingText'),
-              loadTimeData.getString('wifiLabel'));
-        });
-  });
-
-  test('CorrectLinkTextBasedOnDisabledState', () => {
-    let linkId = '#troubleConnectingLinkText';
-    return initializeNetworkTroubleshooting(loadTimeData.getString('wifiLabel'))
-        .then(() => changeDisabledState(false))
-        .then(() => {
+                  '#troubleshootingText'),
+              'header');
           dx_utils.assertElementContainsText(
-              networkTroubleshootingElement.shadowRoot.querySelector(linkId),
-              loadTimeData.getString('troubleConnecting'));
-        })
-        .then(() => changeDisabledState(true))
-        .then(() => {
-          dx_utils.assertElementContainsText(
-              networkTroubleshootingElement.shadowRoot.querySelector(linkId),
-              loadTimeData.getString('reconnectLinkText'));
+              networkTroubleshootingElement.shadowRoot.querySelector(
+                  '#troubleshootingLinkText'),
+              'linkText');
         });
   });
 }
diff --git a/chrome/test/data/webui/chromeos/diagnostics/routine_result_entry_test.js b/chrome/test/data/webui/chromeos/diagnostics/routine_result_entry_test.js
index a9bc4765..79ccb63 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/routine_result_entry_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/routine_result_entry_test.js
@@ -99,17 +99,6 @@
   }
 
   /**
-   * Returns the span wrapping the link icon.
-   * @return {!HTMLSpanElement}
-   */
-  function getRoutineLinkContainer() {
-    const routineLinkContainer = /** @type{!HTMLSpanElement} */ (
-        routineResultEntryElement.$$('.routineLinkContainer'));
-    assertTrue(!!routineLinkContainer);
-    return routineLinkContainer;
-  }
-
-  /**
    * Returns the span wrapping the failure reason text.
    * @return {!HTMLSpanElement}
    */
@@ -244,29 +233,6 @@
     });
   });
 
-  test('RoutineHasNoLinkTest', () => {
-    const item = createCompletedStatus(
-        RoutineType.kBatteryCharge,
-        /** @type {!RoutineResult} */ ({
-          simpleResult: StandardRoutineResult.kTestPassed
-        }));
-
-    return initializeEntryWithItem(item).then(() => {
-      // Span should be hidden
-      assertFalse(isVisible(getRoutineLinkContainer()));
-    });
-  });
-
-  test('RoutineHasLinkTest', () => {
-    const item = new RoutineGroup(
-        [RoutineType.kLanConnectivity], 'lanConnectivityRoutineText');
-
-    return initializeEntryWithItem(item, true).then(() => {
-      // Span should not be hidden
-      assertTrue(isVisible(getRoutineLinkContainer()));
-    });
-  });
-
   test('NetworkRoutineHasCorrectFailureMessage', () => {
     const item = new RoutineGroup(
         [RoutineType.kLanConnectivity], 'lanConnectivityRoutineText');
diff --git a/chrome/test/data/webui/chromeos/diagnostics/system_page_test.js b/chrome/test/data/webui/chromeos/diagnostics/system_page_test.js
index 1eae319e..fbe2d164 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/system_page_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/system_page_test.js
@@ -285,67 +285,69 @@
         .then(() => assertTrue(isVisible(getSessionLogButton())));
   });
 
-  test('RunningCpuTestsShowsBanner', () => {
-    /** @type {?RoutineSectionElement} */
-    let routineSection;
-    /** @type {!Array<!RoutineType>} */
-    const routines = [
-      ash.diagnostics.mojom.RoutineType.kCpuCache,
-    ];
-    routineController.setFakeStandardRoutineResult(
+  // System page is only responsible for banner display when in stand-alone
+  // view.
+  if (!window.isNetworkEnabled) {
+    test('RunningCpuTestsShowsBanner', () => {
+      /** @type {?RoutineSectionElement} */
+      let routineSection;
+      /** @type {!Array<!RoutineType>} */
+      const routines = [
         ash.diagnostics.mojom.RoutineType.kCpuCache,
-        ash.diagnostics.mojom.StandardRoutineResult.kTestPassed);
-    return initializeSystemPage(
-               fakeSystemInfo, fakeBatteryChargeStatus, fakeBatteryHealth,
-               fakeBatteryInfo, fakeCpuUsage, fakeMemoryUsage)
-        .then(() => {
-          routineSection = dx_utils.getRoutineSection(page.$$('cpu-card'));
-          routineSection.routines = routines;
-          assertFalse(isVisible(getCautionBanner()));
-          return flushTasks();
-        })
-        .then(() => {
-          dx_utils.getRunTestsButtonFromSection(routineSection).click();
-          return flushTasks();
-        })
-        .then(() => {
-          assertTrue(isVisible(getCautionBanner()));
-          return routineController.resolveRoutineForTesting();
-        })
-        .then(() => flushTasks())
-        .then(() => assertFalse(isVisible(getCautionBanner())));
-  });
+      ];
+      routineController.setFakeStandardRoutineResult(
+          ash.diagnostics.mojom.RoutineType.kCpuCache,
+          ash.diagnostics.mojom.StandardRoutineResult.kTestPassed);
+      return initializeSystemPage(
+                 fakeSystemInfo, fakeBatteryChargeStatus, fakeBatteryHealth,
+                 fakeBatteryInfo, fakeCpuUsage, fakeMemoryUsage)
+          .then(() => {
+            routineSection = dx_utils.getRoutineSection(page.$$('cpu-card'));
+            routineSection.routines = routines;
+            assertFalse(isVisible(getCautionBanner()));
+            return flushTasks();
+          })
+          .then(() => {
+            dx_utils.getRunTestsButtonFromSection(routineSection).click();
+            return flushTasks();
+          })
+          .then(() => {
+            assertTrue(isVisible(getCautionBanner()));
+            return routineController.resolveRoutineForTesting();
+          })
+          .then(() => flushTasks())
+          .then(() => assertFalse(isVisible(getCautionBanner())));
+    });
 
-  test('RunningMemoryTestsShowsBanner', () => {
-    /** @type {?RoutineSectionElement} */
-    let routineSection;
-    /** @type {!Array<!RoutineType>} */
-    const routines = [
-      RoutineType.kMemory,
-    ];
-    routineController.setFakeStandardRoutineResult(
-        RoutineType.kMemory, StandardRoutineResult.kTestPassed);
-    return initializeSystemPage(
-               fakeSystemInfo, fakeBatteryChargeStatus, fakeBatteryHealth,
-               fakeBatteryInfo, fakeCpuUsage, fakeMemoryUsage)
-        .then(() => {
-          routineSection = dx_utils.getRoutineSection(page.$$('memory-card'));
-          routineSection.routines = routines;
-          assertFalse(isVisible(getCautionBanner()));
-          return flushTasks();
-        })
-        .then(() => {
-          dx_utils.getRunTestsButtonFromSection(routineSection).click();
-          return flushTasks();
-        })
-        .then(() => {
-          dx_utils.assertElementContainsText(
-              page.$$('#banner > #bannerMsg'),
-              loadTimeData.getString('memoryBannerMessage'));
-          assertTrue(isVisible(getCautionBanner()));
-          return routineController.resolveRoutineForTesting();
-        })
-        .then(() => flushTasks())
-        .then(() => assertFalse(isVisible(getCautionBanner())));
-  });
+    test('RunningMemoryTestsShowsBanner', () => {
+      /** @type {?RoutineSectionElement} */
+      let routineSection;
+      /** @type {!Array<!RoutineType>} */
+      const routines = [RoutineType.kMemory];
+      routineController.setFakeStandardRoutineResult(
+          RoutineType.kMemory, StandardRoutineResult.kTestPassed);
+      return initializeSystemPage(
+                 fakeSystemInfo, fakeBatteryChargeStatus, fakeBatteryHealth,
+                 fakeBatteryInfo, fakeCpuUsage, fakeMemoryUsage)
+          .then(() => {
+            routineSection = dx_utils.getRoutineSection(page.$$('memory-card'));
+            routineSection.routines = routines;
+            assertFalse(isVisible(getCautionBanner()));
+            return flushTasks();
+          })
+          .then(() => {
+            dx_utils.getRunTestsButtonFromSection(routineSection).click();
+            return flushTasks();
+          })
+          .then(() => {
+            dx_utils.assertElementContainsText(
+                page.$$('#banner > #bannerMsg'),
+                loadTimeData.getString('memoryBannerMessage'));
+            assertTrue(isVisible(getCautionBanner()));
+            return routineController.resolveRoutineForTesting();
+          })
+          .then(() => flushTasks())
+          .then(() => assertFalse(isVisible(getCautionBanner())));
+    });
+  }
 }
diff --git a/chrome/test/data/webui/chromeos/shortcut_customization/shortcut_customization_test.js b/chrome/test/data/webui/chromeos/shortcut_customization/shortcut_customization_test.js
index 643fb00..db564d6 100644
--- a/chrome/test/data/webui/chromeos/shortcut_customization/shortcut_customization_test.js
+++ b/chrome/test/data/webui/chromeos/shortcut_customization/shortcut_customization_test.js
@@ -237,6 +237,78 @@
     assertEquals(']', actualAccelerator.key_display);
   });
 
+  test('AddAccelerator', async () => {
+    await flushTasks();
+
+    // Open dialog for first accelerator in View Desk subsection.
+    await openDialogForAcceleratorInSubsection_(/*View Desk*/ 1);
+    let editDialog = page.shadowRoot.querySelector('#editDialog');
+    assertTrue(!!editDialog);
+
+    // Grab the first accelerator from Virtual Desks subsection.
+    let dialogAccels = editDialog.shadowRoot.querySelector('cr-dialog')
+                           .querySelectorAll('accelerator-edit-view');
+    // Expect only 1 accelerator initially.
+    assertEquals(1, dialogAccels.length);
+
+    // Click on add button.
+    editDialog.shadowRoot.querySelector('#addAcceleratorButton').click();
+
+    await flushTasks();
+
+    const editElement =
+        editDialog.shadowRoot.querySelector('#pendingAccelerator');
+
+    // Assert no error has occurred prior to pressing a shortcut.
+    assertFalse(editElement.hasError);
+
+    const viewElement =
+        editElement.shadowRoot.querySelector('#acceleratorItem');
+
+    // Alt + ']' is a conflict, expect the error message to appear.
+    viewElement.dispatchEvent(new KeyboardEvent('keydown', {
+      key: ']',
+      keyCode: '221',
+      code: 'Key]',
+      ctrlKey: false,
+      altKey: true,
+      shiftKey: false,
+      metaKey: false,
+    }));
+
+    await flushTasks();
+
+    assertTrue(editElement.hasError);
+
+    // Press the shortcut again, this time it will add and remove the preexsting
+    // accelerator.
+    viewElement.dispatchEvent(new KeyboardEvent('keydown', {
+      key: ']',
+      keyCode: '221',
+      code: 'Key]',
+      ctrlKey: false,
+      altKey: true,
+      shiftKey: false,
+      metaKey: false,
+    }));
+
+    await flushTasks();
+
+    // Requery all accelerators.
+    dialogAccels = editDialog.shadowRoot.querySelector('cr-dialog')
+                       .querySelectorAll('accelerator-edit-view');
+    // Expect 2 accelerators now.
+    assertEquals(2, dialogAccels.length);
+    const newAccel = dialogAccels[1];
+
+    const actualAccelerator =
+        newAccel.shadowRoot.querySelector('#acceleratorItem')
+            .acceleratorInfo.accelerator;
+    assertEquals(Modifier.ALT, actualAccelerator.modifiers);
+    assertEquals(221, actualAccelerator.key);
+    assertEquals(']', actualAccelerator.key_display);
+  });
+
   suite('FakeMojoProviderTest', () => {
     test('SettingGettingTestProvider', () => {
       // TODO(zentaro): Replace with fake when built.
diff --git a/chrome/test/data/webui/settings/chromeos/switch_access_subpage_tests.js b/chrome/test/data/webui/settings/chromeos/switch_access_subpage_tests.js
index ed0a1482..bf62ff1 100644
--- a/chrome/test/data/webui/settings/chromeos/switch_access_subpage_tests.js
+++ b/chrome/test/data/webui/settings/chromeos/switch_access_subpage_tests.js
@@ -232,7 +232,7 @@
                           .$$('#switchAccessActionAssignmentPane')
                           .$$('#error')
                           .textContent.trim();
-    assertEquals('Keys do not match. Press any key to exit.', errorText);
+    assertEquals('Keys don’t match. Press any key to exit.', errorText);
   });
 
   test('Deep link to auto-scan keyboards', async () => {
diff --git a/chrome/test/nacl/nacl_browsertest_uma.cc b/chrome/test/nacl/nacl_browsertest_uma.cc
index dac4ab0..c9abc73e 100644
--- a/chrome/test/nacl/nacl_browsertest_uma.cc
+++ b/chrome/test/nacl/nacl_browsertest_uma.cc
@@ -129,7 +129,13 @@
 })
 
 // Test that a successful load adds stats to Subzero buckets.
-IN_PROC_BROWSER_TEST_F(NaClBrowserTestPnaclSubzero, SuccessfulLoadUMA) {
+// Test is flaky on Win7 (32).
+#if defined(OS_WIN) && defined(ARCH_CPU_32_BITS)
+#define MAYBE_SuccessfulLoadUMA DISABLED_SuccessfulLoadUMA
+#else
+#define MAYBE_SuccessfulLoadUMA SuccessfulLoadUMA
+#endif
+IN_PROC_BROWSER_TEST_F(NaClBrowserTestPnaclSubzero, MAYBE_SuccessfulLoadUMA) {
   // Only test where Subzero is supported.
   if (!IsSubzeroSupportedForArch())
     return;
diff --git a/chrome/updater/BUILD.gn b/chrome/updater/BUILD.gn
index 982fa15..e1ef3e28 100644
--- a/chrome/updater/BUILD.gn
+++ b/chrome/updater/BUILD.gn
@@ -243,19 +243,9 @@
         "win/install_progress_observer.h",
         "win/installer_api.cc",
         "win/installer_api.h",
-        "win/net/net_util.cc",
-        "win/net/net_util.h",
         "win/net/network.h",
         "win/net/network_fetcher.cc",
         "win/net/network_fetcher.h",
-        "win/net/network_winhttp.cc",
-        "win/net/network_winhttp.h",
-        "win/net/proxy_configuration.cc",
-        "win/net/proxy_configuration.h",
-        "win/net/proxy_info.cc",
-        "win/net/proxy_info.h",
-        "win/net/scoped_hinternet.h",
-        "win/net/scoped_winttp_proxy_info.h",
         "win/scoped_handle.h",
         "win/scoped_impersonation.cc",
         "win/scoped_impersonation.h",
@@ -286,6 +276,7 @@
         "//chrome/updater/app/server/win:updater_legacy_idl_idl",
         "//chrome/updater/win:app_install_controller",
         "//chrome/updater/win/ui",
+        "//components/winhttp",
       ]
 
       configs -= [ "//build/config/win:winver" ]
@@ -299,7 +290,6 @@
       libs = [
         "secur32.lib",
         "taskschd.lib",
-        "winhttp.lib",
       ]
     }
   }
@@ -517,8 +507,6 @@
         "test/integration_tests_win.cc",
         "win/installer_api_unittest.cc",
         "win/net/network_unittest.cc",
-        "win/net/proxy_configuration_unittest.cc",
-        "win/net/proxy_info_unittest.cc",
         "win/setup/setup_util_unittest.cc",
         "win/tag_extractor_unittest.cc",
         "win/task_scheduler_unittest.cc",
diff --git a/chrome/updater/DEPS b/chrome/updater/DEPS
index 7baebde..26d806a2 100644
--- a/chrome/updater/DEPS
+++ b/chrome/updater/DEPS
@@ -9,6 +9,7 @@
   "+components/services/unzip",
   "+components/update_client",
   "+components/version_info",
+  "+components/winhttp",
   "+courgette",
   "+crypto",
   "+third_party/boringssl",
diff --git a/chrome/updater/win/net/network.h b/chrome/updater/win/net/network.h
index 5f2f52d7..b218ff2 100644
--- a/chrome/updater/win/net/network.h
+++ b/chrome/updater/win/net/network.h
@@ -9,12 +9,15 @@
 
 #include "base/memory/scoped_refptr.h"
 #include "base/sequence_checker.h"
-#include "chrome/updater/win/net/scoped_hinternet.h"
 #include "components/update_client/network.h"
+#include "components/winhttp/scoped_hinternet.h"
+
+namespace winhttp {
+class ProxyConfiguration;
+}
 
 namespace updater {
 
-class ProxyConfiguration;
 class PolicyService;
 
 // Network fetcher factory for WinHTTP.
@@ -30,13 +33,11 @@
   ~NetworkFetcherFactory() override;
 
  private:
-  static scoped_hinternet CreateSessionHandle(int proxy_access_type);
-
   SEQUENCE_CHECKER(sequence_checker_);
   // Proxy configuration for WinHTTP should be initialized before
   // the session handle.
-  scoped_refptr<ProxyConfiguration> proxy_configuration_;
-  scoped_hinternet session_handle_;
+  scoped_refptr<winhttp::ProxyConfiguration> proxy_configuration_;
+  winhttp::ScopedHInternet session_handle_;
 };
 
 }  // namespace updater
diff --git a/chrome/updater/win/net/network_fetcher.cc b/chrome/updater/win/net/network_fetcher.cc
index ac6ebe2..c206b30 100644
--- a/chrome/updater/win/net/network_fetcher.cc
+++ b/chrome/updater/win/net/network_fetcher.cc
@@ -4,8 +4,6 @@
 
 #include "chrome/updater/win/net/network_fetcher.h"
 
-#include <versionhelpers.h>
-
 #include <memory>
 #include <utility>
 
@@ -13,24 +11,150 @@
 #include "base/callback.h"
 #include "base/callback_helpers.h"
 #include "base/memory/scoped_refptr.h"
+#include "base/strings/sys_string_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/win/windows_version.h"
 #include "chrome/updater/policy/service.h"
 #include "chrome/updater/win/net/network.h"
-#include "chrome/updater/win/net/network_winhttp.h"
-#include "chrome/updater/win/net/proxy_configuration.h"
+#include "chrome/updater/win/scoped_impersonation.h"
+#include "chrome/updater/win/user_info.h"
+#include "chrome/updater/win/win_util.h"
+#include "components/update_client/network.h"
+#include "components/winhttp/network_fetcher.h"
+#include "components/winhttp/proxy_configuration.h"
 
 namespace updater {
 
-NetworkFetcher::NetworkFetcher(const HINTERNET& session_handle,
-                               scoped_refptr<ProxyConfiguration> proxy_config)
-    : network_fetcher_(
-          base::MakeRefCounted<NetworkFetcherWinHTTP>(session_handle,
-                                                      proxy_config)),
+namespace {
+
+std::wstring FromCharOrEmpty(const wchar_t* str) {
+  return str ? std::wstring(str) : std::wstring();
+}
+
+// Wrapper for WINHTTP_CURRENT_USER_IE_PROXY_CONFIG structure.
+// According to MSDN, callers must free strings with GlobalFree.
+class ScopedIeProxyConfig {
+ public:
+  ScopedIeProxyConfig();
+  ScopedIeProxyConfig(const ScopedIeProxyConfig&) = delete;
+  ScopedIeProxyConfig& operator=(const ScopedIeProxyConfig&) = delete;
+  ~ScopedIeProxyConfig();
+
+  WINHTTP_CURRENT_USER_IE_PROXY_CONFIG* receive() { return &ie_proxy_config_; }
+
+  bool auto_detect() const { return ie_proxy_config_.fAutoDetect; }
+  std::wstring auto_config_url() const {
+    return FromCharOrEmpty(ie_proxy_config_.lpszAutoConfigUrl);
+  }
+  std::wstring proxy() const {
+    return FromCharOrEmpty(ie_proxy_config_.lpszProxy);
+  }
+  std::wstring proxy_bypass() const {
+    return FromCharOrEmpty(ie_proxy_config_.lpszProxyBypass);
+  }
+
+ private:
+  WINHTTP_CURRENT_USER_IE_PROXY_CONFIG ie_proxy_config_ = {};
+};
+
+ScopedIeProxyConfig::ScopedIeProxyConfig() {
+  ie_proxy_config_.fAutoDetect = false;
+  ie_proxy_config_.lpszAutoConfigUrl = nullptr;
+  ie_proxy_config_.lpszProxy = nullptr;
+  ie_proxy_config_.lpszProxyBypass = nullptr;
+}
+
+ScopedIeProxyConfig::~ScopedIeProxyConfig() {
+  if (ie_proxy_config_.lpszAutoConfigUrl)
+    ::GlobalFree(ie_proxy_config_.lpszAutoConfigUrl);
+
+  if (ie_proxy_config_.lpszProxy)
+    ::GlobalFree(ie_proxy_config_.lpszProxy);
+
+  if (ie_proxy_config_.lpszProxyBypass)
+    ::GlobalFree(ie_proxy_config_.lpszProxyBypass);
+}
+
+// Factory method for the proxy configuration strategy.
+scoped_refptr<winhttp::ProxyConfiguration> GetProxyConfiguration(
+    scoped_refptr<PolicyService> policy_service) {
+  std::string policy_proxy_mode;
+  if (policy_service->GetProxyMode(nullptr, &policy_proxy_mode) &&
+      policy_proxy_mode.compare(kProxyModeSystem) != 0) {
+    DVLOG(3) << "Using policy proxy " << policy_proxy_mode;
+    bool auto_detect = false;
+    std::wstring pac_url;
+    std::wstring proxy_url;
+    bool is_policy_config_valid = true;
+
+    if (policy_proxy_mode.compare(kProxyModeFixedServers) == 0) {
+      std::string policy_proxy_url;
+      if (!policy_service->GetProxyServer(nullptr, &policy_proxy_url)) {
+        VLOG(1) << "Fixed server mode proxy has no URL specified.";
+        is_policy_config_valid = false;
+      } else {
+        proxy_url = base::SysUTF8ToWide(policy_proxy_url);
+      }
+    } else if (policy_proxy_mode.compare(kProxyModePacScript) == 0) {
+      std::string policy_pac_url;
+      if (!policy_service->GetProxyServer(nullptr, &policy_pac_url)) {
+        VLOG(1) << "PAC proxy policy has no PAC URL specified.";
+        is_policy_config_valid = false;
+      } else {
+        pac_url = base::SysUTF8ToWide(policy_pac_url);
+      }
+    } else if (policy_proxy_mode.compare(kProxyModeAutoDetect)) {
+      auto_detect = true;
+    }
+
+    if (is_policy_config_valid) {
+      return base::MakeRefCounted<winhttp::ProxyConfiguration>(
+          winhttp::ProxyInfo{auto_detect, pac_url, proxy_url, L""});
+    } else {
+      VLOG(1) << "Configuration set by policy was invalid."
+              << "Proceding with system configuration";
+    }
+  }
+
+  const base::win::OSInfo* os_info = base::win::OSInfo::GetInstance();
+  const bool supports_automatic_proxy =
+      os_info->version() >= base::win::Version::WIN8_1;
+  if (supports_automatic_proxy)
+    return base::MakeRefCounted<winhttp::AutoProxyConfiguration>();
+
+  ScopedImpersonation impersonate_user;
+  if (IsLocalSystemUser()) {
+    DVLOG(3) << "Running as SYSTEM, impersonate the current user.";
+    base::win::ScopedHandle user_token = GetUserTokenFromCurrentSessionId();
+    if (user_token.IsValid()) {
+      impersonate_user.Impersonate(user_token.Get());
+    }
+  }
+
+  ScopedIeProxyConfig ie_proxy_config;
+  if (::WinHttpGetIEProxyConfigForCurrentUser(ie_proxy_config.receive())) {
+    return base::MakeRefCounted<winhttp::ProxyConfiguration>(winhttp::ProxyInfo{
+        ie_proxy_config.auto_detect(), ie_proxy_config.auto_config_url(),
+        ie_proxy_config.proxy(), ie_proxy_config.proxy_bypass()});
+  } else {
+    DPLOG(ERROR) << "Failed to get proxy for current user";
+  }
+
+  return base::MakeRefCounted<winhttp::ProxyConfiguration>();
+}
+
+}  // namespace
+
+NetworkFetcher::NetworkFetcher(
+    const HINTERNET& session_handle,
+    scoped_refptr<winhttp::ProxyConfiguration> proxy_config)
+    : winhttp_network_fetcher_(
+          base::MakeRefCounted<winhttp::NetworkFetcher>(session_handle,
+                                                        proxy_config)),
       main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()) {}
 
 NetworkFetcher::~NetworkFetcher() {
-  network_fetcher_->Close();
+  winhttp_network_fetcher_->Close();
 }
 
 void NetworkFetcher::PostRequest(
@@ -43,7 +167,7 @@
     PostRequestCompleteCallback post_request_complete_callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   post_request_complete_callback_ = std::move(post_request_complete_callback);
-  network_fetcher_->PostRequest(
+  winhttp_network_fetcher_->PostRequest(
       url, post_data, content_type, post_additional_headers,
       std::move(response_started_callback), std::move(progress_callback),
       base::BindOnce(&NetworkFetcher::PostRequestComplete,
@@ -59,7 +183,7 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   download_to_file_complete_callback_ =
       std::move(download_to_file_complete_callback);
-  network_fetcher_->DownloadToFile(
+  winhttp_network_fetcher_->DownloadToFile(
       url, file_path, std::move(response_started_callback),
       std::move(progress_callback),
       base::BindOnce(&NetworkFetcher::DownloadToFileComplete,
@@ -68,46 +192,45 @@
 
 void NetworkFetcher::PostRequestComplete() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  // Attempt to get some response headers.  Not all headers may be present so
+  // this is best effort only.
+  std::wstring x_cup_server_proof;
+  std::wstring etag;
+  int x_retry_after_sec = 0;
+  winhttp_network_fetcher_->QueryHeaderString(
+      base::SysUTF8ToWide(
+          update_client::NetworkFetcher::kHeaderXCupServerProof),
+      &x_cup_server_proof);
+  winhttp_network_fetcher_->QueryHeaderString(
+      base::SysUTF8ToWide(update_client::NetworkFetcher::kHeaderEtag), &etag);
+  winhttp_network_fetcher_->QueryHeaderInt(
+      base::SysUTF8ToWide(update_client::NetworkFetcher::kHeaderXRetryAfter),
+      &x_retry_after_sec);
+
   std::move(post_request_complete_callback_)
-      .Run(std::make_unique<std::string>(network_fetcher_->GetResponseBody()),
-           network_fetcher_->GetNetError(), network_fetcher_->GetHeaderETag(),
-           network_fetcher_->GetHeaderXCupServerProof(),
-           network_fetcher_->GetHeaderXRetryAfterSec());
+      .Run(std::make_unique<std::string>(
+               winhttp_network_fetcher_->GetResponseBody()),
+           winhttp_network_fetcher_->GetNetError(), base::SysWideToUTF8(etag),
+           base::SysWideToUTF8(x_cup_server_proof), x_retry_after_sec);
 }
 
 void NetworkFetcher::DownloadToFileComplete() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   std::move(download_to_file_complete_callback_)
-      .Run(network_fetcher_->GetNetError(), network_fetcher_->GetContentSize());
+      .Run(winhttp_network_fetcher_->GetNetError(),
+           winhttp_network_fetcher_->GetContentSize());
 }
 
 NetworkFetcherFactory::NetworkFetcherFactory(
     scoped_refptr<PolicyService> policy_service)
     : proxy_configuration_(GetProxyConfiguration(policy_service)),
       session_handle_(
-          CreateSessionHandle(proxy_configuration_->access_type())) {}
+          winhttp::CreateSessionHandle(L"Chrome Updater",
+                                       proxy_configuration_->access_type())) {}
 
 NetworkFetcherFactory::~NetworkFetcherFactory() = default;
 
-scoped_hinternet NetworkFetcherFactory::CreateSessionHandle(
-    int proxy_access_type) {
-  scoped_hinternet session_handle(
-      ::WinHttpOpen(L"Chrome Updater", proxy_access_type, WINHTTP_NO_PROXY_NAME,
-                    WINHTTP_NO_PROXY_BYPASS, WINHTTP_FLAG_ASYNC));
-
-  // Allow TLS1.2 on Windows 7 and Windows 8. See KB3140245. TLS 1.2 is enabled
-  // by default on Windows 8.1 and Windows 10.
-  if (session_handle.is_valid() && ::IsWindows7OrGreater() &&
-      !::IsWindows8Point1OrGreater()) {
-    DWORD protocols = WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 |
-                      WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 |
-                      WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2;
-    ::WinHttpSetOption(session_handle.get(), WINHTTP_OPTION_SECURE_PROTOCOLS,
-                       &protocols, sizeof(protocols));
-  }
-  return session_handle;
-}
-
 std::unique_ptr<update_client::NetworkFetcher> NetworkFetcherFactory::Create()
     const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/chrome/updater/win/net/network_fetcher.h b/chrome/updater/win/net/network_fetcher.h
index ca4a5b84..8d82c3f 100644
--- a/chrome/updater/win/net/network_fetcher.h
+++ b/chrome/updater/win/net/network_fetcher.h
@@ -23,10 +23,12 @@
 class SingleThreadTaskRunner;
 }  // namespace base
 
-namespace updater {
-
-class NetworkFetcherWinHTTP;
+namespace winhttp {
+class NetworkFetcher;
 class ProxyConfiguration;
+}  // namespace winhttp
+
+namespace updater {
 
 class NetworkFetcher : public update_client::NetworkFetcher {
  public:
@@ -39,7 +41,7 @@
       update_client::NetworkFetcher::DownloadToFileCompleteCallback;
 
   NetworkFetcher(const HINTERNET& session_handle,
-                 scoped_refptr<ProxyConfiguration> proxy_config);
+                 scoped_refptr<winhttp::ProxyConfiguration> proxy_config);
   ~NetworkFetcher() override;
   NetworkFetcher(const NetworkFetcher&) = delete;
   NetworkFetcher& operator=(const NetworkFetcher&) = delete;
@@ -66,7 +68,7 @@
   void PostRequestComplete();
   void DownloadToFileComplete();
 
-  scoped_refptr<NetworkFetcherWinHTTP> network_fetcher_;
+  scoped_refptr<winhttp::NetworkFetcher> winhttp_network_fetcher_;
   scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
 
   DownloadToFileCompleteCallback download_to_file_complete_callback_;
diff --git a/chrome/updater/win/net/network_unittest.cc b/chrome/updater/win/net/network_unittest.cc
index 2812705..28f4afa 100644
--- a/chrome/updater/win/net/network_unittest.cc
+++ b/chrome/updater/win/net/network_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/test/task_environment.h"
 #include "chrome/updater/policy/manager.h"
 #include "chrome/updater/policy/service.h"
+#include "chrome/updater/win/net/network_fetcher.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace updater {
diff --git a/chrome/updater/win/net/proxy_configuration.cc b/chrome/updater/win/net/proxy_configuration.cc
deleted file mode 100644
index e353f1f..0000000
--- a/chrome/updater/win/net/proxy_configuration.cc
+++ /dev/null
@@ -1,247 +0,0 @@
-// 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 "chrome/updater/win/net/proxy_configuration.h"
-
-#include "base/logging.h"
-#include "base/memory/scoped_refptr.h"
-#include "base/strings/sys_string_conversions.h"
-#include "base/win/scoped_handle.h"
-#include "base/win/windows_version.h"
-#include "chrome/updater/constants.h"
-#include "chrome/updater/policy/service.h"
-#include "chrome/updater/win/net/net_util.h"
-#include "chrome/updater/win/net/proxy_info.h"
-#include "chrome/updater/win/net/scoped_winttp_proxy_info.h"
-#include "chrome/updater/win/scoped_impersonation.h"
-#include "chrome/updater/win/user_info.h"
-#include "url/gurl.h"
-
-namespace updater {
-
-namespace {
-
-std::wstring FromCharOrEmpty(const wchar_t* str) {
-  return str ? std::wstring(str) : L"";
-}
-
-// Wrapper for WINHTTP_CURRENT_USER_IE_PROXY_CONFIG structure.
-// According to MSDN, callers must free strings with GlobalFree.
-class ScopedIeProxyConfig {
- public:
-  ScopedIeProxyConfig();
-  ScopedIeProxyConfig(const ScopedIeProxyConfig&) = delete;
-  ScopedIeProxyConfig& operator=(const ScopedIeProxyConfig&) = delete;
-  ~ScopedIeProxyConfig();
-
-  WINHTTP_CURRENT_USER_IE_PROXY_CONFIG* receive() { return &ie_proxy_config_; }
-
-  bool auto_detect() const { return ie_proxy_config_.fAutoDetect; }
-  std::wstring auto_config_url() const {
-    return FromCharOrEmpty(ie_proxy_config_.lpszAutoConfigUrl);
-  }
-  std::wstring proxy() const {
-    return FromCharOrEmpty(ie_proxy_config_.lpszProxy);
-  }
-  std::wstring proxy_bypass() const {
-    return FromCharOrEmpty(ie_proxy_config_.lpszProxyBypass);
-  }
-
- private:
-  WINHTTP_CURRENT_USER_IE_PROXY_CONFIG ie_proxy_config_ = {};
-};
-
-ScopedIeProxyConfig::ScopedIeProxyConfig() {
-  ie_proxy_config_.fAutoDetect = false;
-  ie_proxy_config_.lpszAutoConfigUrl = nullptr;
-  ie_proxy_config_.lpszProxy = nullptr;
-  ie_proxy_config_.lpszProxyBypass = nullptr;
-}
-
-ScopedIeProxyConfig::~ScopedIeProxyConfig() {
-  if (ie_proxy_config_.lpszAutoConfigUrl)
-    ::GlobalFree(ie_proxy_config_.lpszAutoConfigUrl);
-
-  if (ie_proxy_config_.lpszProxy)
-    ::GlobalFree(ie_proxy_config_.lpszProxy);
-
-  if (ie_proxy_config_.lpszProxyBypass)
-    ::GlobalFree(ie_proxy_config_.lpszProxyBypass);
-}
-
-}  // namespace
-
-ProxyConfiguration::ProxyConfiguration(const ProxyInfo& proxy_info)
-    : proxy_info_(proxy_info) {}
-
-int ProxyConfiguration::access_type() const {
-  return DoGetAccessType();
-}
-
-int ProxyConfiguration::DoGetAccessType() const {
-  const bool is_using_named_proxy = !proxy_info_.auto_detect &&
-                                    proxy_info_.auto_config_url.empty() &&
-                                    !proxy_info_.proxy.empty();
-
-  return is_using_named_proxy ? WINHTTP_ACCESS_TYPE_NAMED_PROXY
-                              : WINHTTP_ACCESS_TYPE_DEFAULT_PROXY;
-}
-
-absl::optional<ScopedWinHttpProxyInfo> ProxyConfiguration::GetProxyForUrl(
-    HINTERNET session_handle,
-    const GURL& url) const {
-  return DoGetProxyForUrl(session_handle, url);
-}
-
-absl::optional<ScopedWinHttpProxyInfo> ProxyConfiguration::DoGetProxyForUrl(
-    HINTERNET session_handle,
-    const GURL& url) const {
-  // Detect proxy settings using Web Proxy Auto Detection (WPAD).
-  WINHTTP_AUTOPROXY_OPTIONS auto_proxy_options = {0};
-
-  // Per MSDN, setting fAutoLogonIfChallenged to false first may work
-  // if Windows cached the proxy config.
-  auto_proxy_options.fAutoLogonIfChallenged = false;
-
-  bool try_auto_proxy = false;
-
-  if (proxy_info_.auto_detect) {
-    auto_proxy_options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
-    auto_proxy_options.dwAutoDetectFlags =
-        WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A;
-    try_auto_proxy = true;
-  }
-
-  // PAC Url was specified, let system auto detect given the PAC url.
-  if (!proxy_info_.auto_config_url.empty()) {
-    auto_proxy_options.dwFlags |= WINHTTP_AUTOPROXY_CONFIG_URL;
-    auto_proxy_options.lpszAutoConfigUrl = proxy_info_.auto_config_url.c_str();
-    try_auto_proxy = true;
-  }
-
-  // Find the proxy server for the url.
-  ScopedWinHttpProxyInfo winhttp_proxy_info = {};
-  if (try_auto_proxy) {
-    const std::wstring url_str = base::SysUTF8ToWide(url.spec());
-    bool success = ::WinHttpGetProxyForUrl(session_handle, url_str.c_str(),
-                                           &auto_proxy_options,
-                                           winhttp_proxy_info.receive());
-    if (!success && ::GetLastError() == ERROR_WINHTTP_LOGIN_FAILURE) {
-      auto_proxy_options.fAutoLogonIfChallenged = true;
-      success = ::WinHttpGetProxyForUrl(session_handle, url_str.c_str(),
-                                        &auto_proxy_options,
-                                        winhttp_proxy_info.receive());
-    }
-
-    if (!success) {
-      PLOG(ERROR) << "Failed to get proxy for url";
-      return {};
-    }
-  } else {
-    winhttp_proxy_info.set_proxy(proxy_info_.proxy);
-    winhttp_proxy_info.set_proxy_bypass(proxy_info_.proxy_bypass);
-  }
-
-  if (!winhttp_proxy_info.IsValid())
-    return {};
-
-  return winhttp_proxy_info;
-}
-
-void SetProxyForRequest(
-    const HINTERNET request_handle,
-    const absl::optional<ScopedWinHttpProxyInfo>& winhttp_proxy_info) {
-  // Set the proxy option on the request handle.
-  if (winhttp_proxy_info.has_value() && winhttp_proxy_info.value().IsValid()) {
-    const ScopedWinHttpProxyInfo& proxy_info = winhttp_proxy_info.value();
-    VLOG(1) << "Setting proxy " << proxy_info.proxy();
-    auto hr = SetOption(request_handle, WINHTTP_OPTION_PROXY,
-                        const_cast<WINHTTP_PROXY_INFO*>(proxy_info.get()));
-    if (FAILED(hr)) {
-      PLOG(ERROR) << "Failed to set WINHTTP_OPTION_PROXY: 0x" << std::hex << hr;
-    }
-  }
-}
-
-scoped_refptr<ProxyConfiguration> GetProxyConfiguration(
-    scoped_refptr<PolicyService> policy_service) {
-  std::string policy_proxy_mode;
-  if (policy_service->GetProxyMode(nullptr, &policy_proxy_mode) &&
-      policy_proxy_mode.compare(kProxyModeSystem) != 0) {
-    DVLOG(3) << "Using policy proxy " << policy_proxy_mode;
-    bool auto_detect = false;
-    std::wstring pac_url;
-    std::wstring proxy_url;
-    bool is_policy_config_valid = true;
-
-    if (policy_proxy_mode.compare(kProxyModeFixedServers) == 0) {
-      std::string policy_proxy_url;
-      if (!policy_service->GetProxyServer(nullptr, &policy_proxy_url)) {
-        VLOG(1) << "Fixed server mode proxy has no URL specified.";
-        is_policy_config_valid = false;
-      } else {
-        proxy_url = base::SysUTF8ToWide(policy_proxy_url);
-      }
-    } else if (policy_proxy_mode.compare(kProxyModePacScript) == 0) {
-      std::string policy_pac_url;
-      if (!policy_service->GetProxyServer(nullptr, &policy_pac_url)) {
-        VLOG(1) << "PAC proxy policy has no PAC URL specified.";
-        is_policy_config_valid = false;
-      } else {
-        pac_url = base::SysUTF8ToWide(policy_pac_url);
-      }
-    } else if (policy_proxy_mode.compare(kProxyModeAutoDetect)) {
-      auto_detect = true;
-    }
-
-    if (is_policy_config_valid) {
-      return base::MakeRefCounted<ProxyConfiguration>(
-          ProxyInfo{auto_detect, pac_url, proxy_url, L""});
-    } else {
-      VLOG(1) << "Configuration set by policy was invalid."
-              << "Proceding with system configuration";
-    }
-  }
-
-  const base::win::OSInfo* os_info = base::win::OSInfo::GetInstance();
-  const bool supports_automatic_proxy =
-      os_info->version() >= base::win::Version::WIN8_1;
-  if (supports_automatic_proxy)
-    return base::MakeRefCounted<AutoProxyConfiguration>();
-
-  ScopedImpersonation impersonate_user;
-  if (IsLocalSystemUser()) {
-    DVLOG(3) << "Running as SYSTEM, impersonate the current user.";
-    base::win::ScopedHandle user_token = GetUserTokenFromCurrentSessionId();
-    if (user_token.IsValid()) {
-      impersonate_user.Impersonate(user_token.Get());
-    }
-  }
-
-  ScopedIeProxyConfig ie_proxy_config;
-  if (::WinHttpGetIEProxyConfigForCurrentUser(ie_proxy_config.receive())) {
-    return base::MakeRefCounted<ProxyConfiguration>(ProxyInfo{
-        ie_proxy_config.auto_detect(), ie_proxy_config.auto_config_url(),
-        ie_proxy_config.proxy(), ie_proxy_config.proxy_bypass()});
-  } else {
-    DPLOG(ERROR) << "Failed to get proxy for current user";
-  }
-
-  return base::MakeRefCounted<ProxyConfiguration>();
-}
-
-int AutoProxyConfiguration::DoGetAccessType() const {
-  return WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY;
-}
-
-absl::optional<ScopedWinHttpProxyInfo> AutoProxyConfiguration::DoGetProxyForUrl(
-    HINTERNET,
-    const GURL&) const {
-  // When using automatic proxy settings, Windows will resolve the proxy
-  // for us.
-  DVLOG(3) << "Auto-proxy: skip getting proxy for a url";
-  return {};
-}
-
-}  // namespace updater
diff --git a/chrome/updater/win/net/scoped_hinternet.h b/chrome/updater/win/net/scoped_hinternet.h
deleted file mode 100644
index 235547e..0000000
--- a/chrome/updater/win/net/scoped_hinternet.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2019 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 CHROME_UPDATER_WIN_NET_SCOPED_HINTERNET_H_
-#define CHROME_UPDATER_WIN_NET_SCOPED_HINTERNET_H_
-
-#include <windows.h>
-#include <winhttp.h>
-
-#include "base/scoped_generic.h"
-
-namespace updater {
-
-namespace internal {
-
-struct ScopedHInternetTraits {
-  static HINTERNET InvalidValue() { return nullptr; }
-  static void Free(HINTERNET handle) {
-    if (handle != InvalidValue())
-      WinHttpCloseHandle(handle);
-  }
-};
-
-}  // namespace internal
-
-// Manages the lifetime of HINTERNET handles allocated by WinHTTP.
-using scoped_hinternet =
-    base::ScopedGeneric<HINTERNET, updater::internal::ScopedHInternetTraits>;
-
-}  // namespace updater
-
-#endif  // CHROME_UPDATER_WIN_NET_SCOPED_HINTERNET_H_
diff --git a/chrome/updater/win/win_util_unittest.cc b/chrome/updater/win/win_util_unittest.cc
index 09ff489..b598ea2 100644
--- a/chrome/updater/win/win_util_unittest.cc
+++ b/chrome/updater/win/win_util_unittest.cc
@@ -24,13 +24,6 @@
 
 }  // namespace
 
-TEST(WinUtil, HRESULTFromLastError) {
-  ::SetLastError(ERROR_ACCESS_DENIED);
-  EXPECT_EQ(E_ACCESSDENIED, HRESULTFromLastError());
-  ::SetLastError(ERROR_SUCCESS);
-  EXPECT_EQ(E_FAIL, HRESULTFromLastError());
-}
-
 TEST(WinUtil, HRESULTFromUpdaterError) {
   EXPECT_EQ(HRESULTFromUpdaterError(0), MakeHRESULT(0xa0430000L));
   EXPECT_EQ(HRESULTFromUpdaterError(ERROR_ACCESS_DENIED),
diff --git a/chromecast/browser/extensions/cast_extension_system.cc b/chromecast/browser/extensions/cast_extension_system.cc
index 7180b19..c082ce1 100644
--- a/chromecast/browser/extensions/cast_extension_system.cc
+++ b/chromecast/browser/extensions/cast_extension_system.cc
@@ -223,6 +223,10 @@
   return nullptr;
 }
 
+StateStore* CastExtensionSystem::dynamic_user_scripts_store() {
+  return nullptr;
+}
+
 scoped_refptr<value_store::ValueStoreFactory>
 CastExtensionSystem::store_factory() {
   return store_factory_;
diff --git a/chromecast/browser/extensions/cast_extension_system.h b/chromecast/browser/extensions/cast_extension_system.h
index 61c6200..d0dec4db 100644
--- a/chromecast/browser/extensions/cast_extension_system.h
+++ b/chromecast/browser/extensions/cast_extension_system.h
@@ -78,6 +78,7 @@
   UserScriptManager* user_script_manager() override;
   StateStore* state_store() override;
   StateStore* rules_store() override;
+  StateStore* dynamic_user_scripts_store() override;
   scoped_refptr<value_store::ValueStoreFactory> store_factory() override;
   InfoMap* info_map() override;
   QuotaService* quota_service() override;
diff --git a/chromeos/chromeos_strings.grd b/chromeos/chromeos_strings.grd
index a248ebe..9afe83ab 100644
--- a/chromeos/chromeos_strings.grd
+++ b/chromeos/chromeos_strings.grd
@@ -1061,6 +1061,12 @@
       <message name="IDS_DIAGNOSTICS_ARC_DNS_RESOLUTION_FAILED_TEXT" desc="The text that displays when the `ARC DNS resolution` test fails." translateable="false">
         Unable to resolve DNS from Android
       </message>
+      <message name="IDS_NETWORK_DIAGNOSTICS_NO_IP_ADDRESS_TEXT" desc="The text shown when a network's IP Address is missing.">
+        Unable to obtain IP address
+      </message>
+      <message name="IDS_NETWORK_DIAGNOSTICS_VISIT_SETTINGS_TO_CONFIGURE_LINK_TEXT" desc="Help text that directs users to settings to configure their network.">
+        Visit settings to configure
+      </message>
 
       <!-- Input diagnostics -->
       <message name="IDS_INPUT_DIAGNOSTICS_RUN_TEST" desc="Text for the button that runs a test for a specific input device">
diff --git a/chromeos/chromeos_strings_grd/IDS_NETWORK_DIAGNOSTICS_NO_IP_ADDRESS_TEXT.png.sha1 b/chromeos/chromeos_strings_grd/IDS_NETWORK_DIAGNOSTICS_NO_IP_ADDRESS_TEXT.png.sha1
new file mode 100644
index 0000000..6a08a142
--- /dev/null
+++ b/chromeos/chromeos_strings_grd/IDS_NETWORK_DIAGNOSTICS_NO_IP_ADDRESS_TEXT.png.sha1
@@ -0,0 +1 @@
+56b002c1ffe8572c90dc532fd18de231a2823ae5
\ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_NETWORK_DIAGNOSTICS_VISIT_SETTINGS_TO_CONFIGURE_LINK_TEXT.png.sha1 b/chromeos/chromeos_strings_grd/IDS_NETWORK_DIAGNOSTICS_VISIT_SETTINGS_TO_CONFIGURE_LINK_TEXT.png.sha1
new file mode 100644
index 0000000..6a08a142
--- /dev/null
+++ b/chromeos/chromeos_strings_grd/IDS_NETWORK_DIAGNOSTICS_VISIT_SETTINGS_TO_CONFIGURE_LINK_TEXT.png.sha1
@@ -0,0 +1 @@
+56b002c1ffe8572c90dc532fd18de231a2823ae5
\ No newline at end of file
diff --git a/chromeos/components/projector_app/resources/communication/projector_app.externs.js b/chromeos/components/projector_app/resources/communication/projector_app.externs.js
index c1e6b82..086ef1d 100644
--- a/chromeos/components/projector_app/resources/communication/projector_app.externs.js
+++ b/chromeos/components/projector_app/resources/communication/projector_app.externs.js
@@ -21,10 +21,6 @@
 
 /**
  * The tool type supported in the Ink Engine.
- *
- * See ANNOTATOR_TOOL_TYPE in
- * chrome/apps/projector/client/api/projector_app_message_types.js.
- *
  * @type {string}
  */
 projectorApp.AnnotatorToolParams.prototype.tool;
@@ -74,14 +70,14 @@
 projectorApp.AnnotatorApi.prototype.addUndoRedoListener = function(listener) {};
 
 /**
- * Structure for Account information..
+ * Structure for Account information.
  * @record
  * @struct
  */
- projectorApp.Account = function() {}
+projectorApp.Account = function() {};
 
 /**
- * The name of user.
+ * The name of the user.
  * @type {string}
  */
 projectorApp.Account.prototype.name;
@@ -110,7 +106,7 @@
  * @record
  * @struct
  */
-projectorApp.OAuthTokenInfo = function() {}
+projectorApp.OAuthTokenInfo = function() {};
 
 /**
  * The OAuth token.
@@ -129,7 +125,7 @@
  * @record
  * @struct
  */
-projectorApp.OAuthToken = function() {}
+projectorApp.OAuthToken = function() {};
 
 /**
  * The email of user associated with the oauth token request.
@@ -138,17 +134,80 @@
 projectorApp.OAuthToken.prototype.email;
 
 /**
- * The OAuthToken information..
+ * The OAuth token information.
  * @type {!projectorApp.OAuthTokenInfo}
  */
 projectorApp.OAuthToken.prototype.oauthTokenInfo;
 
 /**
  * The error message associated with the token fetch request.
- *
- * See ProjectorError in
- * chrome/apps/projector/client/api/projector_app_message_types.js.
- *
  * @type {string}
  */
 projectorApp.OAuthTokenInfo.prototype.error;
+
+/**
+ * The delegate interface that the Projector app can use to make requests to
+ * chrome.
+ * @record
+ * @struct
+ */
+projectorApp.ClientDelegate = function() {};
+
+/**
+ * Gets the list of primary and secondary accounts currently available on the
+ * device.
+ * @return {Promise<Array<!projectorApp.Account>>}
+ */
+projectorApp.ClientDelegate.prototype.getAccounts = function() {};
+
+/**
+ * Checks whether the SWA can trigger a new Projector session.
+ * @return {Promise<boolean>}
+ */
+projectorApp.ClientDelegate.prototype.canStartProjectorSession = function() {};
+
+/**
+ * Starts the Projector session if it is possible. Provides the storage
+ * directory name where projector output artifacts will be saved in.
+ * @param {string} storageDir
+ * @return {Promise<boolean>}
+ */
+projectorApp.ClientDelegate.prototype.startProjectorSession = function(
+    storageDir) {};
+
+/**
+ * Gets the oauth token with the required scopes for the specified account.
+ * @param {string} email user's email
+ * @return {!Promise<!projectorApp.OAuthToken>}
+ */
+projectorApp.ClientDelegate.prototype.getOAuthTokenForAccount = function(
+    email) {};
+
+/**
+ * Sends 'error' message to handler.
+ * The Handler will log the message. If the error is not a recoverable error,
+ * the handler closes the corresponding WebUI.
+ * @param {!Array<string>} msg Error messages.
+ */
+projectorApp.ClientDelegate.prototype.onError = function(msg) {};
+
+/**
+ * The client Api for interacting with the Projector app instance.
+ * @record
+ * @struct
+ */
+projectorApp.AppApi = function() {};
+
+/**
+ * Notifies the Projector app that whether it can start a new session.
+ * @param {boolean} canStart
+ */
+projectorApp.AppApi.prototype.onNewScreencastPreconditionChanged = function(
+    canStart) {};
+
+/**
+ * Sets the delegate that the Projector app can use to call into Chrome
+ * dependent functions.
+ * @param {!projectorApp.ClientDelegate} clientDelegate
+ */
+projectorApp.AppApi.prototype.setClientDelegate = function(clientDelegate) {};
diff --git a/components/BUILD.gn b/components/BUILD.gn
index 747abcec..80f919c 100644
--- a/components/BUILD.gn
+++ b/components/BUILD.gn
@@ -41,7 +41,7 @@
   }
 }
 
-# To add a unit test to this target, make a "unit_test" source_set in your
+# To add a unit test to this target, make a "unit_tests" source_set in your
 # component(it's important to use a source_set instead of a static library or
 # no tests will run) and add a reference here.You can add more than one unit
 # test target if convenient.
@@ -490,7 +490,10 @@
   }
 
   if (is_win) {
-    deps += [ "//components/browser_watcher:unit_tests" ]
+    deps += [
+      "//components/browser_watcher:unit_tests",
+      "//components/winhttp:unit_tests",
+    ]
   }
 
   if (enable_basic_printing) {
diff --git a/components/autofill/core/browser/payments/card_unmask_challenge_option.h b/components/autofill/core/browser/payments/card_unmask_challenge_option.h
index e3bfe995..a97812f9 100644
--- a/components/autofill/core/browser/payments/card_unmask_challenge_option.h
+++ b/components/autofill/core/browser/payments/card_unmask_challenge_option.h
@@ -20,7 +20,10 @@
 // option.
 struct CardUnmaskChallengeOption {
   CardUnmaskChallengeOption() = default;
+  CardUnmaskChallengeOption(const CardUnmaskChallengeOption&) = default;
   ~CardUnmaskChallengeOption() = default;
+  CardUnmaskChallengeOption& operator=(const CardUnmaskChallengeOption&) =
+      default;
 
   // The unique identifier for the challenge option.
   std::string id;
diff --git a/components/autofill_payments_strings.grdp b/components/autofill_payments_strings.grdp
index 3a18b96..842ae0a 100644
--- a/components/autofill_payments_strings.grdp
+++ b/components/autofill_payments_strings.grdp
@@ -507,6 +507,18 @@
     <message name="IDS_AUTOFILL_VIRTUAL_CARD_MANUAL_FALLBACK_BUBBLE_BUTTON_TOOLTIP_CLICKED" desc="The tooltip message for the button that contains the card information in the virtual card manual fallback bubble on Desktop. This message is shown when the button is hovered over and if the button has been recently clicked.">
       Copied
     </message>
+    <message name="IDS_AUTOFILL_CARD_UNMASK_AUTHENTICATION_SELECTION_DIALOG_ISSUER_CONFIRMATION_TEXT" desc="The issuer confirmation text shown in the Autofill card unmask authentication selection dialog on Desktop. This is the header text of the dialog, and it is the text stating that the issuer wants additional authentication. This dialog lets the user choose the method of authentication when unmasking a server card, including a virtual card.">
+      Your bank wants to confirm it's you.
+    </message>
+    <message name="IDS_AUTOFILL_AUTHENTICATION_MODE_TEXT_MESSAGE_LABEL" desc="The label for the text message authentication mode text shown in the Autofill card unmask authentication selection dialog on Desktop. This dialog lets the user choose the method of authentication when unmasking a server card, including a virtual card.">
+      Text message
+    </message>
+    <message name="IDS_AUTOFILL_CARD_UNMASK_AUTHENTICATION_SELECTION_DIALOG_CURRENT_INFO_NOT_SEEN_TEXT" desc="The current info not seen text shown in the Autofill card unmask authentication selection dialog on Desktop. It is the footer text on the dialog, and it instructs the user on what to do if they can not see their most up to date authentication information. This dialog lets the user choose the method of authentication when unmasking a server card, including a virtual card.">
+      Not seeing your current info? Please contact your bank to update it.
+    </message>
+    <message name="IDS_AUTOFILL_CARD_UNMASK_AUTHENTICATION_SELECTION_DIALOG_OK_BUTTON_LABEL" desc="The ok button label shown in the Autofill card unmask authentication selection dialog on Desktop. This dialog lets the user choose the method of authentication when unmasking a server card, including a virtual card.">
+      Send
+    </message>
   </if>
   <message name="IDS_AUTOFILL_VIRTUAL_CARD_SUGGESTION_OPTION_VALUE" desc="The text shown in the virtual card option in the credit card suggestion list. It is shown as the value of the suggestion.">
     Virtual card
diff --git a/components/autofill_payments_strings_grdp/IDS_AUTOFILL_AUTHENTICATION_MODE_TEXT_MESSAGE_LABEL.png.sha1 b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_AUTHENTICATION_MODE_TEXT_MESSAGE_LABEL.png.sha1
new file mode 100644
index 0000000..c2bc346
--- /dev/null
+++ b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_AUTHENTICATION_MODE_TEXT_MESSAGE_LABEL.png.sha1
@@ -0,0 +1 @@
+7a79042ecd9dcd99d878979eb6a8cdda9ea72db1
\ No newline at end of file
diff --git a/components/autofill_payments_strings_grdp/IDS_AUTOFILL_CARD_UNMASK_AUTHENTICATION_SELECTION_DIALOG_CURRENT_INFO_NOT_SEEN_TEXT.png.sha1 b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_CARD_UNMASK_AUTHENTICATION_SELECTION_DIALOG_CURRENT_INFO_NOT_SEEN_TEXT.png.sha1
new file mode 100644
index 0000000..c2bc346
--- /dev/null
+++ b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_CARD_UNMASK_AUTHENTICATION_SELECTION_DIALOG_CURRENT_INFO_NOT_SEEN_TEXT.png.sha1
@@ -0,0 +1 @@
+7a79042ecd9dcd99d878979eb6a8cdda9ea72db1
\ No newline at end of file
diff --git a/components/autofill_payments_strings_grdp/IDS_AUTOFILL_CARD_UNMASK_AUTHENTICATION_SELECTION_DIALOG_ISSUER_CONFIRMATION_TEXT.png.sha1 b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_CARD_UNMASK_AUTHENTICATION_SELECTION_DIALOG_ISSUER_CONFIRMATION_TEXT.png.sha1
new file mode 100644
index 0000000..c2bc346
--- /dev/null
+++ b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_CARD_UNMASK_AUTHENTICATION_SELECTION_DIALOG_ISSUER_CONFIRMATION_TEXT.png.sha1
@@ -0,0 +1 @@
+7a79042ecd9dcd99d878979eb6a8cdda9ea72db1
\ No newline at end of file
diff --git a/components/autofill_payments_strings_grdp/IDS_AUTOFILL_CARD_UNMASK_AUTHENTICATION_SELECTION_DIALOG_OK_BUTTON_LABEL.png.sha1 b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_CARD_UNMASK_AUTHENTICATION_SELECTION_DIALOG_OK_BUTTON_LABEL.png.sha1
new file mode 100644
index 0000000..c2bc346
--- /dev/null
+++ b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_CARD_UNMASK_AUTHENTICATION_SELECTION_DIALOG_OK_BUTTON_LABEL.png.sha1
@@ -0,0 +1 @@
+7a79042ecd9dcd99d878979eb6a8cdda9ea72db1
\ No newline at end of file
diff --git a/components/browser_ui/modaldialog/android/java/src/org/chromium/components/browser_ui/modaldialog/ModalDialogView.java b/components/browser_ui/modaldialog/android/java/src/org/chromium/components/browser_ui/modaldialog/ModalDialogView.java
index b671f22a..a4fa245 100644
--- a/components/browser_ui/modaldialog/android/java/src/org/chromium/components/browser_ui/modaldialog/ModalDialogView.java
+++ b/components/browser_ui/modaldialog/android/java/src/org/chromium/components/browser_ui/modaldialog/ModalDialogView.java
@@ -112,6 +112,8 @@
             mOnButtonClickedCallback.onResult(ModalDialogProperties.ButtonType.POSITIVE);
         } else if (view == mNegativeButton) {
             mOnButtonClickedCallback.onResult(ModalDialogProperties.ButtonType.NEGATIVE);
+        } else if (view == mTitleIcon) {
+            mOnButtonClickedCallback.onResult(ModalDialogProperties.ButtonType.TITLE_ICON);
         }
     }
 
@@ -150,6 +152,7 @@
     public void setTitleIcon(Drawable drawable) {
         mTitleIcon.setImageDrawable(drawable);
         updateContentVisibility();
+        if (drawable != null) mTitleIcon.setOnClickListener(this);
     }
 
     /** @param titleScrollable Whether the title is scrollable with the message. */
diff --git a/components/browser_ui/site_settings/android/java/res/xml/site_settings_preferences.xml b/components/browser_ui/site_settings/android/java/res/xml/site_settings_preferences.xml
index ef0ef3bc..31260c2 100644
--- a/components/browser_ui/site_settings/android/java/res/xml/site_settings_preferences.xml
+++ b/components/browser_ui/site_settings/android/java/res/xml/site_settings_preferences.xml
@@ -109,4 +109,9 @@
     <org.chromium.components.browser_ui.settings.ChromeBasePreference
         android:fragment="org.chromium.components.browser_ui.site_settings.SingleCategorySettings"
         android:key="auto_dark_web_content" />
+    <!-- Request Desktop Site -->
+    <!-- TODO(crbug.com/1243758): Update the location of this setting once approved. -->
+    <org.chromium.components.browser_ui.settings.ChromeBasePreference
+        android:fragment="org.chromium.components.browser_ui.site_settings.SingleCategorySettings"
+        android:key="request_desktop_site" />
 </PreferenceScreen>
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/ContentSettingException.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/ContentSettingException.java
index 5314351..9fdb55f 100644
--- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/ContentSettingException.java
+++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/ContentSettingException.java
@@ -9,6 +9,7 @@
 import androidx.annotation.Nullable;
 
 import org.chromium.components.content_settings.ContentSettingValues;
+import org.chromium.components.content_settings.ContentSettingsType;
 import org.chromium.content_public.browser.BrowserContextHandle;
 
 import java.io.Serializable;
@@ -17,7 +18,7 @@
  * Exception information for a given origin.
  */
 public class ContentSettingException implements Serializable {
-    private final int mContentSettingType;
+    private final @ContentSettingsType int mContentSettingType;
     private final String mPrimaryPattern;
     private final String mSecondaryPattern;
     private final @ContentSettingValues @Nullable Integer mContentSetting;
@@ -31,8 +32,9 @@
      * @param setting The setting for this exception, e.g. ALLOW or BLOCK.
      * @param source The source for this exception, e.g. "policy".
      */
-    public ContentSettingException(int type, String primaryPattern, String secondaryPattern,
-            @ContentSettingValues @Nullable Integer setting, String source) {
+    public ContentSettingException(@ContentSettingsType int type, String primaryPattern,
+            String secondaryPattern, @ContentSettingValues @Nullable Integer setting,
+            String source) {
         mContentSettingType = type;
         mPrimaryPattern = primaryPattern;
         mSecondaryPattern = secondaryPattern;
@@ -44,7 +46,7 @@
      * Construct a ContentSettingException.
      * Same as above but defaults secondaryPattern to wildcard.
      */
-    public ContentSettingException(int type, String primaryPattern,
+    public ContentSettingException(@ContentSettingsType int type, String primaryPattern,
             @ContentSettingValues @Nullable Integer setting, String source) {
         this(type, primaryPattern, SITE_WILDCARD, setting, source);
     }
@@ -65,7 +67,7 @@
         return mContentSetting;
     }
 
-    public int getContentSettingType() {
+    public @ContentSettingsType int getContentSettingType() {
         return mContentSettingType;
     }
 
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/ContentSettingsResources.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/ContentSettingsResources.java
index 04d62a7..732da91b 100644
--- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/ContentSettingsResources.java
+++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/ContentSettingsResources.java
@@ -97,8 +97,9 @@
     private static ResourceItem getResourceItem(int contentType) {
         switch (contentType) {
             case ContentSettingsType.ADS:
-                return new ResourceItem(R.drawable.web_asset, 0, R.string.ads_permission_title,
-                        ContentSettingValues.ALLOW, ContentSettingValues.BLOCK, 0,
+                return new ResourceItem(R.drawable.web_asset, /*smallIcon=*/0,
+                        R.string.ads_permission_title, ContentSettingValues.ALLOW,
+                        ContentSettingValues.BLOCK, 0,
                         R.string.website_settings_category_ads_blocked);
 
             case ContentSettingsType.AR:
@@ -109,22 +110,29 @@
                         R.string.website_settings_category_ar_blocked);
 
             case ContentSettingsType.AUTOMATIC_DOWNLOADS:
-                return new ResourceItem(R.drawable.infobar_downloading, 0,
+                return new ResourceItem(R.drawable.infobar_downloading, /*smallIcon=*/0,
                         R.string.automatic_downloads_permission_title, ContentSettingValues.ASK,
                         ContentSettingValues.BLOCK, R.string.website_settings_category_ask, 0);
 
+            case ContentSettingsType.AUTO_DARK_WEB_CONTENT:
+                return new ResourceItem(R.drawable.ic_brightness_medium_24dp,
+                        R.drawable.ic_brightness_medium_20dp, R.string.auto_dark_web_content_title,
+                        ContentSettingValues.ALLOW, ContentSettingValues.BLOCK,
+                        R.string.website_settings_category_auto_dark_allowed,
+                        R.string.website_settings_category_auto_dark_blocked);
+
             case ContentSettingsType.BACKGROUND_SYNC:
-                return new ResourceItem(R.drawable.permission_background_sync, 0,
+                return new ResourceItem(R.drawable.permission_background_sync, /*smallIcon=*/0,
                         R.string.background_sync_permission_title, ContentSettingValues.ALLOW,
                         ContentSettingValues.BLOCK,
                         R.string.website_settings_category_allowed_recommended, 0);
 
             case ContentSettingsType.BLUETOOTH_CHOOSER_DATA:
-                return new ResourceItem(R.drawable.settings_bluetooth, 0, 0,
+                return new ResourceItem(R.drawable.settings_bluetooth, /*smallIcon=*/0, 0,
                         ContentSettingValues.ASK, ContentSettingValues.BLOCK, 0, 0);
 
             case ContentSettingsType.BLUETOOTH_GUARD:
-                return new ResourceItem(R.drawable.settings_bluetooth, 0,
+                return new ResourceItem(R.drawable.settings_bluetooth, /*smallIcon=*/0,
                         R.string.website_settings_bluetooth, ContentSettingValues.ASK,
                         ContentSettingValues.BLOCK,
                         R.string.website_settings_category_bluetooth_ask,
@@ -145,10 +153,18 @@
                         R.string.website_settings_category_clipboard_blocked);
 
             case ContentSettingsType.COOKIES:
-                return new ResourceItem(R.drawable.permission_cookie, 0, R.string.cookies_title,
-                        ContentSettingValues.ALLOW, ContentSettingValues.BLOCK,
+                return new ResourceItem(R.drawable.permission_cookie, /*smallIcon=*/0,
+                        R.string.cookies_title, ContentSettingValues.ALLOW,
+                        ContentSettingValues.BLOCK,
                         R.string.website_settings_category_cookie_allowed, 0);
 
+            case ContentSettingsType.REQUEST_DESKTOP_SITE:
+                return new ResourceItem(R.drawable.ic_desktop_windows, /*smallIcon=*/0,
+                        R.string.desktop_site_title, ContentSettingValues.ALLOW,
+                        ContentSettingValues.BLOCK,
+                        R.string.website_settings_category_desktop_site_allowed,
+                        R.string.website_settings_category_desktop_site_blocked);
+
             case ContentSettingsType.GEOLOCATION:
                 return new ResourceItem(R.drawable.gm_filled_location_on_24,
                         R.drawable.gm_filled_location_on_20,
@@ -164,7 +180,7 @@
                         R.string.website_settings_category_idle_detection_blocked);
 
             case ContentSettingsType.JAVASCRIPT:
-                return new ResourceItem(R.drawable.permission_javascript, 0,
+                return new ResourceItem(R.drawable.permission_javascript, /*smallIcon=*/0,
                         R.string.javascript_permission_title, ContentSettingValues.ALLOW,
                         ContentSettingValues.BLOCK,
                         R.string.website_settings_category_javascript_allowed, 0);
@@ -199,7 +215,7 @@
                         R.string.website_settings_category_notifications_ask, 0);
 
             case ContentSettingsType.POPUPS:
-                return new ResourceItem(R.drawable.permission_popups, 0,
+                return new ResourceItem(R.drawable.permission_popups, /*smallIcon=*/0,
                         R.string.popup_permission_title, ContentSettingValues.ALLOW,
                         ContentSettingValues.BLOCK, 0,
                         R.string.website_settings_category_popups_redirects_blocked);
@@ -207,7 +223,7 @@
             // PROTECTED_MEDIA_IDENTIFIER uses 3-state preference so some values are not used.
             // If 3-state becomes more common we should update localMaps to support it better.
             case ContentSettingsType.PROTECTED_MEDIA_IDENTIFIER:
-                return new ResourceItem(R.drawable.permission_protected_media, 0,
+                return new ResourceItem(R.drawable.permission_protected_media, /*smallIcon=*/0,
                         R.string.protected_content, ContentSettingValues.ASK,
                         ContentSettingValues.BLOCK, 0, 0);
 
@@ -232,12 +248,13 @@
                     // FeatureList.setTestFeatures() with a map that should not need to contain
                     // DeviceFeatureList.GENERIC_SENSOR_EXTRA_CLASSES.
                 }
-                return new ResourceItem(R.drawable.settings_sensors, 0, sensorsPermissionTitle,
-                        ContentSettingValues.ALLOW, ContentSettingValues.BLOCK,
-                        sensorsAllowedDescription, sensorsBlockedDescription);
+                return new ResourceItem(R.drawable.settings_sensors, /*smallIcon=*/0,
+                        sensorsPermissionTitle, ContentSettingValues.ALLOW,
+                        ContentSettingValues.BLOCK, sensorsAllowedDescription,
+                        sensorsBlockedDescription);
 
             case ContentSettingsType.SOUND:
-                return new ResourceItem(R.drawable.ic_volume_up_grey600_24dp, 0,
+                return new ResourceItem(R.drawable.ic_volume_up_grey600_24dp, /*smallIcon=*/0,
                         R.string.sound_permission_title, ContentSettingValues.ALLOW,
                         ContentSettingValues.BLOCK,
                         R.string.website_settings_category_sound_allowed,
@@ -259,13 +276,6 @@
                         ContentSettingValues.ASK, ContentSettingValues.BLOCK,
                         R.string.website_settings_category_vr_ask,
                         R.string.website_settings_category_vr_blocked);
-
-            case ContentSettingsType.AUTO_DARK_WEB_CONTENT:
-                return new ResourceItem(R.drawable.ic_brightness_medium_24dp,
-                        R.drawable.ic_brightness_medium_20dp, R.string.auto_dark_web_content_title,
-                        ContentSettingValues.ALLOW, ContentSettingValues.BLOCK,
-                        R.string.website_settings_category_auto_dark_allowed,
-                        R.string.website_settings_category_auto_dark_blocked);
         }
         assert false; // NOTREACHED
         return null;
@@ -510,6 +520,15 @@
     }
 
     /**
+     * Returns the allowed/blocked summary for the desktop site permission which should be used for
+     * display in the site settings list only.
+     */
+    public static int getDesktopSiteListSummary(boolean enabled) {
+        return enabled ? R.string.website_settings_category_desktop_site_allowed_list
+                       : R.string.website_settings_category_desktop_site_blocked_list;
+    }
+
+    /**
      * Returns the resources IDs for descriptions for Allowed, Ask and Blocked states, in that
      * order, on a tri-state setting.
      *
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettings.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettings.java
index 9783adb..0927ebd 100644
--- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettings.java
+++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettings.java
@@ -112,6 +112,8 @@
                 p.setSummary(ContentSettingsResources.getAdsBlockedListSummary());
             } else if (Type.SOUND == prefCategory && !checked) {
                 p.setSummary(ContentSettingsResources.getSoundBlockedListSummary());
+            } else if (Type.REQUEST_DESKTOP_SITE == prefCategory) {
+                p.setSummary(ContentSettingsResources.getDesktopSiteListSummary(checked));
             } else if (requiresTriStateSetting) {
                 p.setSummary(ContentSettingsResources.getCategorySummary(setting));
             } else {
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsCategory.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsCategory.java
index 2a3e934c..801c245 100644
--- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsCategory.java
+++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsCategory.java
@@ -42,7 +42,7 @@
             Type.CLIPBOARD, Type.COOKIES, Type.IDLE_DETECTION, Type.DEVICE_LOCATION,
             Type.JAVASCRIPT, Type.MICROPHONE, Type.NFC, Type.NOTIFICATIONS, Type.POPUPS,
             Type.PROTECTED_MEDIA, Type.SENSORS, Type.SOUND, Type.USB, Type.VIRTUAL_REALITY,
-            Type.USE_STORAGE, Type.AUTO_DARK_WEB_CONTENT})
+            Type.USE_STORAGE, Type.AUTO_DARK_WEB_CONTENT, Type.REQUEST_DESKTOP_SITE})
     @Retention(RetentionPolicy.SOURCE)
     public @interface Type {
         // All updates here must also be reflected in {@link #preferenceKey(int)
@@ -71,10 +71,11 @@
         int VIRTUAL_REALITY = 21;
         int USE_STORAGE = 22;
         int AUTO_DARK_WEB_CONTENT = 23;
+        int REQUEST_DESKTOP_SITE = 24;
         /**
          * Number of handled categories used for calculating array sizes.
          */
-        int NUM_ENTRIES = 24;
+        int NUM_ENTRIES = 25;
     }
 
     private final BrowserContextHandle mBrowserContextHandle;
@@ -148,7 +149,7 @@
     /**
      * Convert Type into {@link ContentSettingsType}.
      */
-    public static int contentSettingsType(@Type int type) {
+    public static @ContentSettingsType int contentSettingsType(@Type int type) {
         // This switch statement is ordered by types alphabetically.
         switch (type) {
             case Type.ADS:
@@ -171,6 +172,8 @@
                 return ContentSettingsType.CLIPBOARD_READ_WRITE;
             case Type.COOKIES:
                 return ContentSettingsType.COOKIES;
+            case Type.REQUEST_DESKTOP_SITE:
+                return ContentSettingsType.REQUEST_DESKTOP_SITE;
             case Type.DEVICE_LOCATION:
                 return ContentSettingsType.GEOLOCATION;
             case Type.IDLE_DETECTION:
@@ -198,7 +201,7 @@
             // case Type.ALL_SITES
             // case Type.USE_STORAGE
             default:
-                return -1; // Conversion unavailable.
+                return ContentSettingsType.DEFAULT; // Conversion unavailable.
         }
     }
 
@@ -245,6 +248,8 @@
                 return "clipboard";
             case Type.COOKIES:
                 return "cookies";
+            case Type.REQUEST_DESKTOP_SITE:
+                return "request_desktop_site";
             case Type.DEVICE_LOCATION:
                 return "device_location";
             case Type.IDLE_DETECTION:
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePermissionsFetcher.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePermissionsFetcher.java
index 6de6079f..9523dcc 100644
--- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePermissionsFetcher.java
+++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePermissionsFetcher.java
@@ -62,6 +62,7 @@
             case ContentSettingsType.BACKGROUND_SYNC:
             case ContentSettingsType.BLUETOOTH_SCANNING:
             case ContentSettingsType.COOKIES:
+            case ContentSettingsType.REQUEST_DESKTOP_SITE:
             case ContentSettingsType.JAVASCRIPT:
             case ContentSettingsType.JAVASCRIPT_JIT:
             case ContentSettingsType.POPUPS:
diff --git a/components/browser_ui/site_settings/android/website_preference_bridge.cc b/components/browser_ui/site_settings/android/website_preference_bridge.cc
index d4f6fc27..ee7d9bf 100644
--- a/components/browser_ui/site_settings/android/website_preference_bridge.cc
+++ b/components/browser_ui/site_settings/android/website_preference_bridge.cc
@@ -815,6 +815,7 @@
       case ContentSettingsType::AUTO_DARK_WEB_CONTENT:
       case ContentSettingsType::BACKGROUND_SYNC:
       case ContentSettingsType::COOKIES:
+      case ContentSettingsType::REQUEST_DESKTOP_SITE:
       case ContentSettingsType::JAVASCRIPT:
       case ContentSettingsType::POPUPS:
       case ContentSettingsType::SENSORS:
diff --git a/components/browser_ui/strings/android/site_settings.grdp b/components/browser_ui/strings/android/site_settings.grdp
index 21bffa3..e17ddec 100644
--- a/components/browser_ui/strings/android/site_settings.grdp
+++ b/components/browser_ui/strings/android/site_settings.grdp
@@ -73,6 +73,9 @@
   <message name="IDS_AUTO_DARK_WEB_CONTENT_TITLE" translateable="false" desc="Title of the permission auto darken web content [CHAR_LIMIT=32]">
     Auto-darken web content
   </message>
+  <message name="IDS_DESKTOP_SITE_TITLE" desc="Title of the permission to request the desktop view of a site by default [CHAR_LIMIT=32]">
+    Desktop site
+  </message>
 
   <!-- Site settings global toggles -->
 
@@ -342,6 +345,20 @@
     Cookies are files created by websites you visit. Sites use them to remember your preferences. Third-party cookies are created by other sites. These sites own some of the content, like ads or images, that you see on the webpage you visit.
   </message>
 
+  <!-- Desktop Site -->
+  <message name="IDS_WEBSITE_SETTINGS_CATEGORY_DESKTOP_SITE_ALLOWED" desc="Summary text explaining that desktop view of sites will be requested by default.">
+    Request the desktop view of sites
+  </message>
+  <message name="IDS_WEBSITE_SETTINGS_CATEGORY_DESKTOP_SITE_BLOCKED" desc="Summary text explaining that mobile view of sites will be requested by default.">
+    Request the mobile view of sites
+  </message>
+  <message name="IDS_WEBSITE_SETTINGS_CATEGORY_DESKTOP_SITE_ALLOWED_LIST" desc="Summary text explaining that desktop view of sites will be requested by default. To be shown in the list of permission categories.">
+    Enabled
+  </message>
+  <message name="IDS_WEBSITE_SETTINGS_CATEGORY_DESKTOP_SITE_BLOCKED_LIST" desc="Summary text explaining that mobile view of sites will be requested by default. To be shown in the list of permission categories.">
+    Disabled
+  </message>
+
   <!-- Idle Detection -->
   <message name="IDS_WEBSITE_SETTINGS_CATEGORY_IDLE_DETECTION_ASK" desc="The description for the option to allow sites to ask for permission to access your activity state">
     Ask when a site wants to know when you're actively using this device
diff --git a/components/browser_ui/strings/android/site_settings_grdp/IDS_DESKTOP_SITE_TITLE.png.sha1 b/components/browser_ui/strings/android/site_settings_grdp/IDS_DESKTOP_SITE_TITLE.png.sha1
new file mode 100644
index 0000000..b2c1564
--- /dev/null
+++ b/components/browser_ui/strings/android/site_settings_grdp/IDS_DESKTOP_SITE_TITLE.png.sha1
@@ -0,0 +1 @@
+bdd8cbec0a3b257b0014c455fd7d245f4f20f425
\ No newline at end of file
diff --git a/components/browser_ui/strings/android/site_settings_grdp/IDS_WEBSITE_SETTINGS_CATEGORY_DESKTOP_SITE_ALLOWED.png.sha1 b/components/browser_ui/strings/android/site_settings_grdp/IDS_WEBSITE_SETTINGS_CATEGORY_DESKTOP_SITE_ALLOWED.png.sha1
new file mode 100644
index 0000000..691eb1fa
--- /dev/null
+++ b/components/browser_ui/strings/android/site_settings_grdp/IDS_WEBSITE_SETTINGS_CATEGORY_DESKTOP_SITE_ALLOWED.png.sha1
@@ -0,0 +1 @@
+cb7e4b16e25ef0f0448853d5d3196220dbc8e092
\ No newline at end of file
diff --git a/components/browser_ui/strings/android/site_settings_grdp/IDS_WEBSITE_SETTINGS_CATEGORY_DESKTOP_SITE_ALLOWED_LIST.png.sha1 b/components/browser_ui/strings/android/site_settings_grdp/IDS_WEBSITE_SETTINGS_CATEGORY_DESKTOP_SITE_ALLOWED_LIST.png.sha1
new file mode 100644
index 0000000..e17bf1a
--- /dev/null
+++ b/components/browser_ui/strings/android/site_settings_grdp/IDS_WEBSITE_SETTINGS_CATEGORY_DESKTOP_SITE_ALLOWED_LIST.png.sha1
@@ -0,0 +1 @@
+2a608171c34ee211d5619060f7bd9b5271b31de7
\ No newline at end of file
diff --git a/components/browser_ui/strings/android/site_settings_grdp/IDS_WEBSITE_SETTINGS_CATEGORY_DESKTOP_SITE_BLOCKED.png.sha1 b/components/browser_ui/strings/android/site_settings_grdp/IDS_WEBSITE_SETTINGS_CATEGORY_DESKTOP_SITE_BLOCKED.png.sha1
new file mode 100644
index 0000000..60854a6
--- /dev/null
+++ b/components/browser_ui/strings/android/site_settings_grdp/IDS_WEBSITE_SETTINGS_CATEGORY_DESKTOP_SITE_BLOCKED.png.sha1
@@ -0,0 +1 @@
+c05d0943bf5465a77daf2ef8b5d0aaf8b918831c
\ No newline at end of file
diff --git a/components/browser_ui/strings/android/site_settings_grdp/IDS_WEBSITE_SETTINGS_CATEGORY_DESKTOP_SITE_BLOCKED_LIST.png.sha1 b/components/browser_ui/strings/android/site_settings_grdp/IDS_WEBSITE_SETTINGS_CATEGORY_DESKTOP_SITE_BLOCKED_LIST.png.sha1
new file mode 100644
index 0000000..2f45c21
--- /dev/null
+++ b/components/browser_ui/strings/android/site_settings_grdp/IDS_WEBSITE_SETTINGS_CATEGORY_DESKTOP_SITE_BLOCKED_LIST.png.sha1
@@ -0,0 +1 @@
+fbb9c2babd2afa3973b11193d330cf4c2f97ba96
\ No newline at end of file
diff --git a/components/browser_ui/styles/android/BUILD.gn b/components/browser_ui/styles/android/BUILD.gn
index dda93ad..e63e1921 100644
--- a/components/browser_ui/styles/android/BUILD.gn
+++ b/components/browser_ui/styles/android/BUILD.gn
@@ -158,6 +158,7 @@
     "java/res/drawable/ic_business.xml",
     "java/res/drawable/ic_collections_grey.xml",
     "java/res/drawable/ic_data_viz_grey.xml",
+    "java/res/drawable/ic_desktop_windows.xml",
     "java/res/drawable/ic_done_blue.xml",
     "java/res/drawable/ic_drive_document_24dp.xml",
     "java/res/drawable/ic_drive_file_24dp.xml",
diff --git a/chrome/android/java/res/drawable/ic_desktop_windows.xml b/components/browser_ui/styles/android/java/res/drawable/ic_desktop_windows.xml
similarity index 100%
rename from chrome/android/java/res/drawable/ic_desktop_windows.xml
rename to components/browser_ui/styles/android/java/res/drawable/ic_desktop_windows.xml
diff --git a/components/content_settings/core/browser/content_settings_registry.cc b/components/content_settings/core/browser/content_settings_registry.cc
index e8eb714..beeb578 100644
--- a/components/content_settings/core/browser/content_settings_registry.cc
+++ b/components/content_settings/core/browser/content_settings_registry.cc
@@ -628,6 +628,16 @@
            ContentSettingsInfo::INHERIT_IN_INCOGNITO,
            ContentSettingsInfo::PERSISTENT,
            ContentSettingsInfo::EXCEPTIONS_ON_SECURE_AND_INSECURE_ORIGINS);
+
+  Register(ContentSettingsType::REQUEST_DESKTOP_SITE, "request-desktop-site",
+           CONTENT_SETTING_BLOCK, WebsiteSettingsInfo::UNSYNCABLE,
+           AllowlistedSchemes(),
+           ValidSettings(CONTENT_SETTING_ALLOW, CONTENT_SETTING_BLOCK),
+           WebsiteSettingsInfo::SINGLE_ORIGIN_ONLY_SCOPE,
+           WebsiteSettingsRegistry::PLATFORM_ANDROID,
+           ContentSettingsInfo::INHERIT_IN_INCOGNITO,
+           ContentSettingsInfo::PERSISTENT,
+           ContentSettingsInfo::EXCEPTIONS_ON_SECURE_AND_INSECURE_ORIGINS);
 }
 
 void ContentSettingsRegistry::Register(
diff --git a/components/content_settings/core/browser/content_settings_registry_unittest.cc b/components/content_settings/core/browser/content_settings_registry_unittest.cc
index 9664153..bdb81f19 100644
--- a/components/content_settings/core/browser/content_settings_registry_unittest.cc
+++ b/components/content_settings/core/browser/content_settings_registry_unittest.cc
@@ -129,6 +129,7 @@
       ContentSettingsType::LEGACY_COOKIE_ACCESS,
       ContentSettingsType::STORAGE_ACCESS,
       ContentSettingsType::INSECURE_PRIVATE_NETWORK,
+      ContentSettingsType::REQUEST_DESKTOP_SITE,
   };
 
   for (const ContentSettingsInfo* info : *registry()) {
diff --git a/components/content_settings/core/common/content_settings.cc b/components/content_settings/core/common/content_settings.cc
index bd21916..7006397 100644
--- a/components/content_settings/core/common/content_settings.cc
+++ b/components/content_settings/core/common/content_settings.cc
@@ -102,6 +102,7 @@
     {ContentSettingsType::FORMFILL_METADATA, 81},
     {ContentSettingsType::FEDERATED_IDENTITY_ACTIVE_SESSION, 82},
     {ContentSettingsType::AUTO_DARK_WEB_CONTENT, 83},
+    {ContentSettingsType::REQUEST_DESKTOP_SITE, 84},
 };
 
 }  // namespace
diff --git a/components/content_settings/core/common/content_settings_types.h b/components/content_settings/core/common/content_settings_types.h
index a5fdcea45..03716cb 100644
--- a/components/content_settings/core/common/content_settings_types.h
+++ b/components/content_settings/core/common/content_settings_types.h
@@ -288,6 +288,10 @@
   // web content.
   AUTO_DARK_WEB_CONTENT,
 
+  // Setting to indicate whether Chrome should request the desktop view of a
+  // site instead of the mobile one.
+  REQUEST_DESKTOP_SITE,
+
   NUM_TYPES,
 };
 
diff --git a/components/exo/client_controlled_shell_surface_unittest.cc b/components/exo/client_controlled_shell_surface_unittest.cc
index 4d4e0fc4..caf1ace 100644
--- a/components/exo/client_controlled_shell_surface_unittest.cc
+++ b/components/exo/client_controlled_shell_surface_unittest.cc
@@ -17,7 +17,6 @@
 #include "ash/system/unified/unified_system_tray.h"
 #include "ash/test/test_widget_builder.h"
 #include "ash/wm/drag_window_resizer.h"
-#include "ash/wm/full_restore/full_restore_controller.h"
 #include "ash/wm/overview/overview_controller.h"
 #include "ash/wm/pip/pip_positioner.h"
 #include "ash/wm/splitview/split_view_controller.h"
@@ -27,6 +26,7 @@
 #include "ash/wm/tablet_mode/tablet_mode_window_resizer.h"
 #include "ash/wm/window_positioning_utils.h"
 #include "ash/wm/window_resizer.h"
+#include "ash/wm/window_restore/window_restore_controller.h"
 #include "ash/wm/window_state.h"
 #include "ash/wm/window_util.h"
 #include "ash/wm/wm_event.h"
@@ -2727,7 +2727,7 @@
 
   // Tablet mode -> clamshell mode. Top caption height should be reserved.
   EnableTabletMode(false);
-  EXPECT_EQ(gfx::Rect(0, 32, 396, 568), delegate->requested_bounds().back());
+  EXPECT_EQ(gfx::Rect(0, 32, 400, 568), delegate->requested_bounds().back());
 
   // Clean up state.
   shell_surface->SetSnappedToLeft();
@@ -2879,9 +2879,10 @@
   EXPECT_EQ(hidden_container_parent,
             wide_frame->GetWidget()->GetNativeWindow()->parent());
 
-  // Call the FullRestoreController, simulating the ARC task becoming ready. The
-  // surface should be reparented and the WideFrameView should follow it.
-  ash::FullRestoreController::Get()->OnARCTaskReadyForUnparentedWindow(window);
+  // Call the WindowRestoreController, simulating the ARC task becoming ready.
+  // The surface should be reparented and the WideFrameView should follow it.
+  ash::WindowRestoreController::Get()->OnARCTaskReadyForUnparentedWindow(
+      window);
   EXPECT_NE(hidden_container_parent, window->parent());
   wide_frame = shell_surface->wide_frame_for_test();
   EXPECT_TRUE(wide_frame);
diff --git a/components/exo/data_source.cc b/components/exo/data_source.cc
index 6832f42..4359ebf2 100644
--- a/components/exo/data_source.cc
+++ b/components/exo/data_source.cc
@@ -34,6 +34,7 @@
 constexpr char kTextHTML[] = "text/html";
 constexpr char kTextUriList[] = "text/uri-list";
 constexpr char kApplicationOctetStream[] = "application/octet-stream";
+constexpr char kWebCustomData[] = "chromium/x-web-custom-data";
 
 constexpr char kUtfPrefix[] = "UTF";
 constexpr char kEncoding16[] = "16";
@@ -259,6 +260,7 @@
     ReadDataCallback image_reader,
     ReadDataCallback filenames_reader,
     ReadFileContentsDataCallback file_contents_reader,
+    ReadDataCallback web_custom_data_reader,
     base::RepeatingClosure failure_callback) {
   std::string text_mime;
   std::string rtf_mime;
@@ -266,6 +268,7 @@
   std::string image_mime;
   std::string filenames_mime;
   std::string file_contents_mime;
+  std::string web_custom_data_mime;
 
   int text_rank = std::numeric_limits<int>::max();
   int html_rank = std::numeric_limits<int>::max();
@@ -317,6 +320,8 @@
       filenames_mime = mime_type;
     } else if (!GetApplicationOctetStreamName(mime_type).empty()) {
       file_contents_mime = mime_type;
+    } else if (net::MatchesMimeType(std::string(kWebCustomData), mime_type)) {
+      web_custom_data_mime = mime_type;
     }
   }
 
@@ -338,6 +343,8 @@
                           read_data_weak_ptr_factory_.GetWeakPtr(),
                           std::move(file_contents_reader)),
            failure_callback);
+  ReadData(web_custom_data_mime, std::move(web_custom_data_reader),
+           failure_callback);
 }
 
 void DataSource::OnTextRead(ReadTextDataCallback callback,
diff --git a/components/exo/data_source.h b/components/exo/data_source.h
index 394f37b..2618ea4 100644
--- a/components/exo/data_source.h
+++ b/components/exo/data_source.h
@@ -25,8 +25,8 @@
  public:
   // The maximum number of different data types that will be read by
   // GetDataForPreferredMimeTypes (plain text, RTF, HTML, image, text/uri-list,
-  // application/octet-stream).
-  static constexpr int kMaxDataTypes = 6;
+  // application/octet-stream, chromium/x-web-custom-data).
+  static constexpr int kMaxDataTypes = 7;
 
   explicit DataSource(DataSourceDelegate* delegate);
 
@@ -71,12 +71,12 @@
 
   // Search the set of offered MIME types for the most preferred of each of the
   // following categories: text/plain*, text/rtf, text/html*, image/*,
-  // text/uri-list. If any usable MIME types in a given category are available,
-  // the corresponding
+  // text/uri-list, chromium/x-web-custom-data. If any usable MIME types in a
+  // given category are available, the corresponding
   // |*_reader| input callback will be called with the best one and the
   // corresponding data. For any category that has no available MIME types,
   // |failure_callback| is run. |failure_callback| may therefore be run as many
-  // as four times.
+  // as seven times.
   using ReadDataCallback =
       base::OnceCallback<void(const std::string&, const std::vector<uint8_t>&)>;
   using ReadTextDataCallback =
@@ -85,6 +85,8 @@
       base::OnceCallback<void(const std::string&,
                               const base::FilePath&,
                               const std::vector<uint8_t>&)>;
+  using ReadWebCustomDataCallback =
+      base::OnceCallback<void(const std::string&, const std::vector<uint8_t>&)>;
   void GetDataForPreferredMimeTypes(
       ReadTextDataCallback text_reader,
       ReadDataCallback rtf_reader,
@@ -92,6 +94,7 @@
       ReadDataCallback image_reader,
       ReadDataCallback filenames_reader,
       ReadFileContentsDataCallback file_contents_reader,
+      ReadDataCallback web_custom_data_reader,
       base::RepeatingClosure failure_callback);
 
   void ReadDataForTesting(const std::string& mime_type,
diff --git a/components/exo/data_source_unittest.cc b/components/exo/data_source_unittest.cc
index 0039d46f..69a383a 100644
--- a/components/exo/data_source_unittest.cc
+++ b/components/exo/data_source_unittest.cc
@@ -81,19 +81,30 @@
   std::move(counter).Run();
 }
 
+void CheckWebCustomDataMimeType(const std::string& expected,
+                                base::OnceClosure counter,
+                                const std::string& mime_type,
+                                const std::vector<uint8_t>& data) {
+  EXPECT_FALSE(mime_type.empty());
+  EXPECT_EQ(expected, mime_type);
+  std::move(counter).Run();
+}
+
 void IncrementFailureCounter(std::atomic_int* failure_count,
                              base::RepeatingClosure counter) {
   ++(*failure_count);
   std::move(counter).Run();
 }
 
-void CheckMimeTypesReceived(DataSource* data_source,
-                            const std::string& text_mime,
-                            const std::string& rtf_mime,
-                            const std::string& html_mime,
-                            const std::string& image_mime,
-                            const std::string& filenames_mime,
-                            const FileContents& file_contents) {
+void CheckMimeTypesReceived(
+    DataSource* data_source,
+    const std::string& text_mime,
+    const std::string& rtf_mime,
+    const std::string& html_mime,
+    const std::string& image_mime,
+    const std::string& filenames_mime,
+    const FileContents& file_contents,
+    const std::string& web_custom_data_mime = std::string()) {
   base::RunLoop run_loop;
   base::RepeatingClosure counter =
       base::BarrierClosure(DataSource::kMaxDataTypes, run_loop.QuitClosure());
@@ -106,12 +117,15 @@
       base::BindOnce(&CheckMimeType, image_mime, counter),
       base::BindOnce(&CheckMimeType, filenames_mime, counter),
       base::BindOnce(&CheckFileContentsMimeType, file_contents, counter),
+      base::BindOnce(&CheckWebCustomDataMimeType, web_custom_data_mime,
+                     counter),
       base::BindRepeating(&IncrementFailureCounter, &failure_count, counter));
   run_loop.Run();
 
   int expected_failure_count = 0;
-  for (const auto& mime_type : {text_mime, rtf_mime, html_mime, image_mime,
-                                filenames_mime, file_contents.mime_type}) {
+  for (const auto& mime_type :
+       {text_mime, rtf_mime, html_mime, image_mime, filenames_mime,
+        file_contents.mime_type, web_custom_data_mime}) {
     if (mime_type.empty())
       ++expected_failure_count;
   }
@@ -339,5 +353,15 @@
       {"application/octet-stream;name=\"t\\\\est\\\".jpg\"", "t\\est\".jpg"});
 }
 
+TEST_F(DataSourceTest, WebCustomDataMime) {
+  TestDataSourceDelegate delegate;
+  DataSource data_source(&delegate);
+  std::string web_custom_data_mime("chromium/x-web-custom-data");
+  data_source.Offer(web_custom_data_mime);
+
+  CheckMimeTypesReceived(&data_source, "", "", "", "", "", {},
+                         web_custom_data_mime);
+}
+
 }  // namespace
 }  // namespace exo
diff --git a/components/exo/drag_drop_operation.cc b/components/exo/drag_drop_operation.cc
index 97cb9d6c..b4f9f5a7 100644
--- a/components/exo/drag_drop_operation.cc
+++ b/components/exo/drag_drop_operation.cc
@@ -6,6 +6,7 @@
 
 #include "base/barrier_closure.h"
 #include "base/check.h"
+#include "base/pickle.h"
 #include "base/strings/string_split.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "build/chromeos_buildflags.h"
@@ -226,6 +227,8 @@
                      origin->window()),
       base::BindOnce(&DragDropOperation::OnFileContentsRead,
                      weak_ptr_factory_.GetWeakPtr()),
+      base::BindOnce(&DragDropOperation::OnWebCustomDataRead,
+                     weak_ptr_factory_.GetWeakPtr()),
       counter_);
 }
 
@@ -290,6 +293,17 @@
   counter_.Run();
 }
 
+void DragDropOperation::OnWebCustomDataRead(const std::string& mime_type,
+                                            const std::vector<uint8_t>& data) {
+  DCHECK(os_exchange_data_);
+  base::Pickle pickle(reinterpret_cast<const char*>(data.data()), data.size());
+  os_exchange_data_->SetPickledData(
+      ui::ClipboardFormatType::WebCustomDataType(), pickle);
+
+  mime_type_ = mime_type;
+  counter_.Run();
+}
+
 void DragDropOperation::OnDragIconCaptured(const SkBitmap& icon_bitmap) {
   DCHECK(icon_);
 
diff --git a/components/exo/drag_drop_operation.h b/components/exo/drag_drop_operation.h
index ffcf85f8..35058f7 100644
--- a/components/exo/drag_drop_operation.h
+++ b/components/exo/drag_drop_operation.h
@@ -108,6 +108,8 @@
   void OnFileContentsRead(const std::string& mime_type,
                           const base::FilePath& filename,
                           const std::vector<uint8_t>& data);
+  void OnWebCustomDataRead(const std::string& mime_type,
+                           const std::vector<uint8_t>& data);
 
   void ScheduleStartDragDropOperation();
 
diff --git a/components/exo/seat.cc b/components/exo/seat.cc
index fe24cba..690277a8 100644
--- a/components/exo/seat.cc
+++ b/components/exo/seat.cc
@@ -170,7 +170,10 @@
                      data_read_callback),
       base::BindOnce(&Seat::OnFilenamesRead, weak_ptr_factory_.GetWeakPtr(),
                      endpoint_type, writer, data_read_callback),
-      DataSource::ReadFileContentsDataCallback(), data_read_callback);
+      DataSource::ReadFileContentsDataCallback(),
+      base::BindOnce(&Seat::OnWebCustomDataRead, weak_ptr_factory_.GetWeakPtr(),
+                     writer, data_read_callback),
+      data_read_callback);
 }
 
 class Seat::RefCountedScopedClipboardWriter
@@ -249,6 +252,16 @@
   std::move(callback).Run();
 }
 
+void Seat::OnWebCustomDataRead(
+    scoped_refptr<RefCountedScopedClipboardWriter> writer,
+    base::OnceClosure callback,
+    const std::string& mime_type,
+    const std::vector<uint8_t>& data) {
+  NOTREACHED()
+      << "Seat does not support custom data mime types for selections.";
+  std::move(callback).Run();
+}
+
 void Seat::OnAllReadsFinished(
     scoped_refptr<RefCountedScopedClipboardWriter> writer) {
   // We need to destroy the ScopedClipboardWriter in this call, before
diff --git a/components/exo/seat.h b/components/exo/seat.h
index 580f8f1..79d369a 100644
--- a/components/exo/seat.h
+++ b/components/exo/seat.h
@@ -189,6 +189,11 @@
                        base::OnceClosure callback,
                        const std::string& mime_type,
                        const std::vector<uint8_t>& data);
+  void OnWebCustomDataRead(
+      scoped_refptr<RefCountedScopedClipboardWriter> writer,
+      base::OnceClosure callback,
+      const std::string& mime_type,
+      const std::vector<uint8_t>& data);
 
   void OnAllReadsFinished(
       scoped_refptr<RefCountedScopedClipboardWriter> writer);
diff --git a/components/history_clusters_strings.grdp b/components/history_clusters_strings.grdp
index da9081f..6cbf909 100644
--- a/components/history_clusters_strings.grdp
+++ b/components/history_clusters_strings.grdp
@@ -2,6 +2,38 @@
 
 <!-- Strings for the chrome://history/journeys page -->
 
-<!-- TODO(crbug.com/1173908): Add strings currently hardcoded in HistoryUI. -->
 <grit-part>
+  <message name="IDS_HISTORY_CLUSTERS_DISABLE_MENU_ITEM_LABEL" desc="A label for the menu item to turn off the Journeys feature, which collects different search and browsing activities related to a single topic into a single place, and organizes them by topic. See glossary entry for meaning of 'Journeys'.">
+    Turn off Journeys
+  </message>
+  <message name="IDS_HISTORY_CLUSTERS_ENABLE_MENU_ITEM_LABEL" desc="A label for the menu item to turn on the Journeys feature, which collects different search and browsing activities related to a single topic into a single place, and organizes them by topic. See glossary entry for meaning of 'Journeys'.">
+    Turn on Journeys
+  </message>
+  <message name="IDS_HISTORY_CLUSTERS_HEADER_TEXT" desc="Header text shown when the history items related to a given user search term are shown.">
+    Based on activity related to "<ph name="SEARCH_TERM"><ex>dual kitchen range</ex>$1</ph>"
+  </message>
+  <message name="IDS_HISTORY_CLUSTERS_JOURNEYS_TAB_LABEL" desc="A label for the section in Chrome History (chrome://history) where Journeys are collected and shown to the user. See glossary entry for meaning of 'Journeys'.">
+    Journeys
+  </message>
+  <message name="IDS_HISTORY_CLUSTERS_LIST_TAB_LABEL" desc="A label for the section in Chrome History (chrome://history) where a list of history items are shown to the user.">
+    List
+  </message>
+  <message name="IDS_HISTORY_CLUSTERS_RELATED_SEARCHES_HEADER" desc="Header text shown for the section containing search suggestions related to a group of search and browsing activities.">
+    Related searches
+  </message>
+  <message name="IDS_HISTORY_CLUSTERS_REMOVE_ALL_ITEMS" desc="Label of the item in drop-down menu that allows the user to remove a group of history items.">
+    Remove all from history
+  </message>
+  <message name="IDS_HISTORY_CLUSTERS_REMOVE_ITEM_TOAST" desc="Confirmation message shown after user successfully removes one history item from the item's drop-down menu.">
+    Item removed
+  </message>
+  <message name="IDS_HISTORY_CLUSTERS_SAVED_IN_TABGROUP_LABEL" desc="A label indicating whether a history item was added to a tab group.">
+    Saved in tab group
+  </message>
+  <message name="IDS_HISTORY_CLUSTERS_SHOW_LESS_BUTTON_LABEL" desc="A label for the button that collapses the view showing fewer history items.">
+    Show less
+  </message>
+  <message name="IDS_HISTORY_CLUSTERS_SHOW_MORE_BUTTON_LABEL" desc="A label for the button that expands the view showing more history items.">
+    Show more
+  </message>
 </grit-part>
diff --git a/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_DISABLE_MENU_ITEM_LABEL.png.sha1 b/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_DISABLE_MENU_ITEM_LABEL.png.sha1
new file mode 100644
index 0000000..89a107a6b
--- /dev/null
+++ b/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_DISABLE_MENU_ITEM_LABEL.png.sha1
@@ -0,0 +1 @@
+e4c50977c1953af182eb2503a0c59a567205bafc
\ No newline at end of file
diff --git a/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_ENABLE_MENU_ITEM_LABEL.png.sha1 b/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_ENABLE_MENU_ITEM_LABEL.png.sha1
new file mode 100644
index 0000000..8e9590f3
--- /dev/null
+++ b/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_ENABLE_MENU_ITEM_LABEL.png.sha1
@@ -0,0 +1 @@
+043de46f71cf8f7aaa71fb3ac0d01da52c15d35d
\ No newline at end of file
diff --git a/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_HEADER_TEXT.png.sha1 b/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_HEADER_TEXT.png.sha1
new file mode 100644
index 0000000..015683cc
--- /dev/null
+++ b/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_HEADER_TEXT.png.sha1
@@ -0,0 +1 @@
+35373dc4f1bc5cfa770be6f9d591538cf9a79971
\ No newline at end of file
diff --git a/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_JOURNEYS_TAB_LABEL.png.sha1 b/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_JOURNEYS_TAB_LABEL.png.sha1
new file mode 100644
index 0000000..ee9dfb6a
--- /dev/null
+++ b/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_JOURNEYS_TAB_LABEL.png.sha1
@@ -0,0 +1 @@
+5856c4100ea8ebddbf2223ccdc7fbac6fa8c2eb9
\ No newline at end of file
diff --git a/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_LIST_TAB_LABEL.png.sha1 b/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_LIST_TAB_LABEL.png.sha1
new file mode 100644
index 0000000..5371cfb
--- /dev/null
+++ b/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_LIST_TAB_LABEL.png.sha1
@@ -0,0 +1 @@
+4ffbe741a547282addf291c3500b0df42422429d
\ No newline at end of file
diff --git a/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_RELATED_SEARCHES_HEADER.png.sha1 b/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_RELATED_SEARCHES_HEADER.png.sha1
new file mode 100644
index 0000000..7cfa70b
--- /dev/null
+++ b/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_RELATED_SEARCHES_HEADER.png.sha1
@@ -0,0 +1 @@
+4188ea380cffddbfe76068169c72ad928504135c
\ No newline at end of file
diff --git a/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_REMOVE_ALL_ITEMS.png.sha1 b/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_REMOVE_ALL_ITEMS.png.sha1
new file mode 100644
index 0000000..fece6d50
--- /dev/null
+++ b/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_REMOVE_ALL_ITEMS.png.sha1
@@ -0,0 +1 @@
+7cca01d73c9f6ed3515750932340d3402bfb0706
\ No newline at end of file
diff --git a/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_REMOVE_ITEM_TOAST.png.sha1 b/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_REMOVE_ITEM_TOAST.png.sha1
new file mode 100644
index 0000000..54695ede
--- /dev/null
+++ b/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_REMOVE_ITEM_TOAST.png.sha1
@@ -0,0 +1 @@
+3f1c7cca95a4b5163a5aa229a03c86453ef18e76
\ No newline at end of file
diff --git a/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_SAVED_IN_TABGROUP_LABEL.png.sha1 b/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_SAVED_IN_TABGROUP_LABEL.png.sha1
new file mode 100644
index 0000000..46dc060
--- /dev/null
+++ b/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_SAVED_IN_TABGROUP_LABEL.png.sha1
@@ -0,0 +1 @@
+ffd306ab011074141a70500277b2804d50f5de94
\ No newline at end of file
diff --git a/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_SHOW_LESS_BUTTON_LABEL.png.sha1 b/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_SHOW_LESS_BUTTON_LABEL.png.sha1
new file mode 100644
index 0000000..8ea28e1
--- /dev/null
+++ b/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_SHOW_LESS_BUTTON_LABEL.png.sha1
@@ -0,0 +1 @@
+6757d7986b7b533b4db5b7ead7260c3920395738
\ No newline at end of file
diff --git a/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_SHOW_MORE_BUTTON_LABEL.png.sha1 b/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_SHOW_MORE_BUTTON_LABEL.png.sha1
new file mode 100644
index 0000000..e8f7cc7
--- /dev/null
+++ b/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_SHOW_MORE_BUTTON_LABEL.png.sha1
@@ -0,0 +1 @@
+fede022166225d660bb19c69866af8e7f6b8e7ff
\ No newline at end of file
diff --git a/components/history_clusters_strings_grdp/OWNERS b/components/history_clusters_strings_grdp/OWNERS
new file mode 100644
index 0000000..d03b432
--- /dev/null
+++ b/components/history_clusters_strings_grdp/OWNERS
@@ -0,0 +1 @@
+file://components/history_clusters/OWNERS
diff --git a/components/management_strings.grdp b/components/management_strings.grdp
index 2b2ceb6..04d712a 100644
--- a/components/management_strings.grdp
+++ b/components/management_strings.grdp
@@ -111,9 +111,12 @@
     <message name="IDS_MANAGEMENT_LOG_UPLOAD_ENABLED" desc="Message stating that administrators have access to system logs on user's device.">
       Detailed system logs
     </message>
-    <message name="IDS_MANAGEMENT_REPORT_DEVICE_NETWORK_INTERFACES" desc="Message stating that administrators see device network interfaces.">
+    <message name="IDS_MANAGEMENT_REPORT_DEVICE_NETWORK_DATA" desc="Message stating that administrators see device network interfaces.">
       Network addresses
     </message>
+    <message name="IDS_MANAGEMENT_REPORT_DEVICE_HARDWARE_DATA" desc="Message stating that administrators see device hardware status.">
+      Device statistics such as CPU/RAM usage and hardware specifications
+    </message>
     <message name="IDS_MANAGEMENT_REPORT_DEVICE_CRASH_REPORTS" desc="Message stating that administrators see the numbers and causes of the crashes that occurred on the device recently.">
       Numbers and causes of the crashes that occurred recently
     </message>
diff --git a/components/management_strings_grdp/IDS_MANAGEMENT_REPORT_DEVICE_HARDWARE_DATA.png.sha1 b/components/management_strings_grdp/IDS_MANAGEMENT_REPORT_DEVICE_HARDWARE_DATA.png.sha1
new file mode 100644
index 0000000..c3a44931
--- /dev/null
+++ b/components/management_strings_grdp/IDS_MANAGEMENT_REPORT_DEVICE_HARDWARE_DATA.png.sha1
@@ -0,0 +1 @@
+b47e4323ab339253b680f0391d0270c69d3a325a
\ No newline at end of file
diff --git a/components/management_strings_grdp/IDS_MANAGEMENT_REPORT_DEVICE_NETWORK_DATA.png.sha1 b/components/management_strings_grdp/IDS_MANAGEMENT_REPORT_DEVICE_NETWORK_DATA.png.sha1
new file mode 100644
index 0000000..3cde1204
--- /dev/null
+++ b/components/management_strings_grdp/IDS_MANAGEMENT_REPORT_DEVICE_NETWORK_DATA.png.sha1
@@ -0,0 +1 @@
+78c4753ac68a32d71da371fce6d61e9eea040c5e
\ No newline at end of file
diff --git a/components/metrics/metrics_state_manager.cc b/components/metrics/metrics_state_manager.cc
index 0782473e..6bb01f6a 100644
--- a/components/metrics/metrics_state_manager.cc
+++ b/components/metrics/metrics_state_manager.cc
@@ -8,6 +8,7 @@
 #include <cstdint>
 #include <limits>
 #include <memory>
+#include <random>
 #include <string>
 #include <utility>
 
@@ -43,6 +44,35 @@
 namespace metrics {
 namespace {
 
+// The parameters for the log normal distribution. They refer to the default
+// mean, the delta that would be applied to the default mean (the actual mean
+// equals mean + log(1 + delta)) and the standard deviation of the distribution
+// that's being generated. These parameters are carefully calculated so that
+// ~0.01% of data drawn from the distribution would fall in the underflow bucket
+// and ~0.01% of data in the overflow bucket. And they also leave us enough
+// wiggle room to shift mean using delta in experiments without losing precision
+// badly because of data in the overflow bucket.
+//
+// The way we get these numbers are based on the following calculation:
+// u := the lower threshold for the overflow bucket (in this case, 10000).
+// l := the upper threshold for the smallest bucket (in this case, 1).
+// p := the probability that an observation will fall in the highest bucket (in
+//   this case, 0.01%) and also the probability that an observation will fall in
+//   the lowest bucket.
+//
+// mean = (log(u) + log(l)) / 2
+// sd = (log(u) - log(l)) / (2 * qnorm(1-p))
+//
+// At this point, experiments should only control the delta but not mean and
+// stdDev. Putting them in feature params so that we can configure them from the
+// server side if we want.
+const base::FeatureParam<double> kLogNormalMean{
+    &kNonUniformityValidationFeature, "mean", 4.605};
+const base::FeatureParam<double> kLogNormalDelta{
+    &kNonUniformityValidationFeature, "delta", 0};
+const base::FeatureParam<double> kLogNormalStdDev{
+    &kNonUniformityValidationFeature, "stdDev", 1.238};
+
 // The argument used to generate a non-identifying entropy source. We want no
 // more than 13 bits of entropy, so use this max to return a number in the range
 // [0, 7999] as the entropy source (12.97 bits of entropy).
@@ -78,6 +108,37 @@
   return nullptr;
 }
 
+// Returns a log normal distribution based on the feature params of
+// |kNonUniformityValidationFeature|.
+std::lognormal_distribution<double> GetLogNormalDist() {
+  double mean = kLogNormalMean.Get();
+  double delta = kLogNormalDelta.Get();
+  double std_dev = kLogNormalStdDev.Get();
+  return std::lognormal_distribution<double>(mean + std::log(1.0 + delta),
+                                             std_dev);
+}
+
+// Used to draw a data point from a log normal distribution.
+struct LogNormalMetricState {
+  LogNormalMetricState()
+      : dist(GetLogNormalDist()), gen(std::mt19937(std::random_device()())) {}
+
+  // Records the artificial non-uniformity histogram for data validation.
+  void LogArtificialNonUniformity() {
+    double rand = dist(gen);
+    // We pick 10k as the upper bound for this histogram so as to avoid losing
+    // precision. See comments for |kLogNormalMean|.
+    base::UmaHistogramCounts10000("UMA.DataValidation.LogNormal",
+                                  base::saturated_cast<int>(rand));
+  }
+
+  // A log normal distribution generator generated by the `GetLogNormalDist()`
+  // function.
+  std::lognormal_distribution<double> dist;
+  // The pseudo-random generator used to generate a data point from |dist|.
+  std::mt19937 gen;
+};
+
 class MetricsStateMetricsProvider : public MetricsProvider {
  public:
   MetricsStateMetricsProvider(
@@ -152,6 +213,12 @@
       ChromeUserMetricsExtension* uma_proto) override {
     if (cloned_install_detector_.ClonedInstallDetectedInCurrentSession())
       LogClonedInstall();
+    log_normal_metric_state_.LogArtificialNonUniformity();
+  }
+
+  // Set a random seed for the random number generator.
+  void SetRandomSeedForTesting(int64_t seed) {
+    log_normal_metric_state_.gen = std::mt19937(seed);
   }
 
  private:
@@ -164,6 +231,7 @@
   // the low entropy source was used to do randomization.
   const std::string initial_client_id_;
   const ClonedInstallDetector& cloned_install_detector_;
+  LogNormalMetricState log_normal_metric_state_;
 
   DISALLOW_COPY_AND_ASSIGN(MetricsStateMetricsProvider);
 };
@@ -256,6 +324,15 @@
       initial_client_id_, cloned_install_detector_);
 }
 
+std::unique_ptr<MetricsProvider>
+MetricsStateManager::GetProviderAndSetRandomSeedForTesting(int64_t seed) {
+  auto provider = std::make_unique<MetricsStateMetricsProvider>(
+      local_state_, metrics_ids_were_reset_, previous_client_id_,
+      initial_client_id_, cloned_install_detector_);
+  provider->SetRandomSeedForTesting(seed);  // IN-TEST
+  return provider;
+}
+
 bool MetricsStateManager::IsMetricsReportingEnabled() {
   return enabled_state_provider_->IsReportingEnabled();
 }
diff --git a/components/metrics/metrics_state_manager.h b/components/metrics/metrics_state_manager.h
index a9221c8f..4342825 100644
--- a/components/metrics/metrics_state_manager.h
+++ b/components/metrics/metrics_state_manager.h
@@ -9,6 +9,7 @@
 #include <string>
 
 #include "base/callback.h"
+#include "base/feature_list.h"
 #include "base/files/file_path.h"
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
@@ -48,6 +49,12 @@
   kLow = 1,      // Use CreateLowEntropyProvider().
 };
 
+// Used to assess the reliability of field trial data by sending artificial
+// non-uniform data. This feature's parameter controls the mu value of a log
+// normal distribution.
+const base::Feature kNonUniformityValidationFeature{
+    "NonUniformityValidation", base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Responsible for managing MetricsService state prefs, specifically the UMA
 // client id and low entropy source. Code outside the metrics directory should
 // not be instantiating or using this class directly.
@@ -191,6 +198,9 @@
 
  private:
   FRIEND_TEST_ALL_PREFIXES(MetricsStateManagerTest, CheckProviderResetIds);
+  FRIEND_TEST_ALL_PREFIXES(MetricsStateManagerTest, CheckProviderLogNormal);
+  FRIEND_TEST_ALL_PREFIXES(MetricsStateManagerTest,
+                           CheckProviderLogNormalWithParams);
   FRIEND_TEST_ALL_PREFIXES(
       MetricsStateManagerTest,
       CheckProviderResetIds_PreviousIdOnlyReportInResetSession);
@@ -248,6 +258,11 @@
                       StoreClientInfoCallback store_client_info,
                       LoadClientInfoCallback load_client_info);
 
+  // Returns a MetricsStateManagerProvider instance and sets its
+  // |log_normal_metric_state_.gen| with the provided random seed.
+  std::unique_ptr<MetricsProvider> GetProviderAndSetRandomSeedForTesting(
+      int64_t seed);
+
   // Backs up the current client info via |store_client_info_|.
   void BackUpCurrentClientInfo();
 
diff --git a/components/metrics/metrics_state_manager_unittest.cc b/components/metrics/metrics_state_manager_unittest.cc
index 143cc58..927f74f 100644
--- a/components/metrics/metrics_state_manager_unittest.cc
+++ b/components/metrics/metrics_state_manager_unittest.cc
@@ -19,6 +19,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
 #include "build/build_config.h"
 #include "components/metrics/client_info.h"
 #include "components/metrics/metrics_log.h"
@@ -538,6 +539,34 @@
   histogram_tester.ExpectTotalCount("UMA.IsClonedInstall", 0);
 }
 
+TEST_F(MetricsStateManagerTest, CheckProviderLogNormal) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  std::unique_ptr<MetricsStateManager> state_manager(CreateStateManager());
+  // Set the random seed to have a deterministic test.
+  std::unique_ptr<MetricsProvider> provider =
+      state_manager->GetProviderAndSetRandomSeedForTesting(42);
+
+  base::HistogramTester histogram_tester;
+  ChromeUserMetricsExtension uma_proto;
+  provider->ProvideCurrentSessionData(&uma_proto);
+  histogram_tester.ExpectUniqueSample("UMA.DataValidation.LogNormal", 189, 1);
+}
+
+TEST_F(MetricsStateManagerTest, CheckProviderLogNormalWithParams) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeatureWithParameters(
+      kNonUniformityValidationFeature, {{"delta", "10.0"}});
+  std::unique_ptr<MetricsStateManager> state_manager(CreateStateManager());
+  // Set the random seed to have a deterministic test.
+  std::unique_ptr<MetricsProvider> provider =
+      state_manager->GetProviderAndSetRandomSeedForTesting(42);
+
+  base::HistogramTester histogram_tester;
+  ChromeUserMetricsExtension uma_proto;
+  provider->ProvideCurrentSessionData(&uma_proto);
+  histogram_tester.ExpectUniqueSample("UMA.DataValidation.LogNormal", 2081, 1);
+}
+
 TEST_F(MetricsStateManagerTest, CheckClientIdWasNotUsedToAssignFieldTrial) {
   EnableMetricsReporting();
   ClientInfo client_info;
diff --git a/components/omnibox/browser/actions/omnibox_action.cc b/components/omnibox/browser/actions/omnibox_action.cc
index 1f31f4c..4b6aa9e 100644
--- a/components/omnibox/browser/actions/omnibox_action.cc
+++ b/components/omnibox/browser/actions/omnibox_action.cc
@@ -88,6 +88,10 @@
 }
 #endif
 
+SkColor OmniboxAction::GetVectorIconColor() const {
+  return SK_ColorTRANSPARENT;
+}
+
 size_t OmniboxAction::EstimateMemoryUsage() const {
   size_t total = 0;
   total += base::trace_event::EstimateMemoryUsage(url_);
diff --git a/components/omnibox/browser/actions/omnibox_action.h b/components/omnibox/browser/actions/omnibox_action.h
index 1cb1860d..e7a9013 100644
--- a/components/omnibox/browser/actions/omnibox_action.h
+++ b/components/omnibox/browser/actions/omnibox_action.h
@@ -16,6 +16,7 @@
 #include "components/search_engines/template_url.h"
 #include "ui/base/page_transition_types.h"
 #include "ui/base/window_open_disposition.h"
+#include "ui/gfx/color_utils.h"
 #include "url/gurl.h"
 
 #if (!defined(OS_ANDROID) || BUILDFLAG(ENABLE_VR)) && !defined(OS_IOS)
@@ -138,6 +139,10 @@
   virtual const gfx::VectorIcon& GetVectorIcon() const;
 #endif
 
+  // Returns SK_ColorTRANSPARENT by default to indicate usage of normal theme
+  // color for suggestion row buttons; or override to force icon color.
+  virtual SkColor GetVectorIconColor() const;
+
   // Estimates RAM usage in bytes for this Action.
   virtual size_t EstimateMemoryUsage() const;
 
diff --git a/components/omnibox/browser/actions/omnibox_pedal.cc b/components/omnibox/browser/actions/omnibox_pedal.cc
index cc69973..f1e5c2b6 100644
--- a/components/omnibox/browser/actions/omnibox_pedal.cc
+++ b/components/omnibox/browser/actions/omnibox_pedal.cc
@@ -230,7 +230,9 @@
 // =============================================================================
 
 OmniboxPedal::OmniboxPedal(OmniboxPedalId id, LabelStrings strings, GURL url)
-    : OmniboxAction(strings, url), id_(id) {}
+    : OmniboxAction(strings, url),
+      id_(id),
+      verbatim_synonym_group_(false, true, 0) {}
 
 OmniboxPedal::~OmniboxPedal() = default;
 
@@ -262,6 +264,11 @@
 }
 #endif
 
+void OmniboxPedal::AddVerbatimSequence(TokenSequence sequence) {
+  sequence.ResetLinks();
+  verbatim_synonym_group_.AddSynonym(std::move(sequence));
+}
+
 void OmniboxPedal::AddSynonymGroup(SynonymGroup&& group) {
   synonym_groups_.push_back(std::move(group));
 }
@@ -276,6 +283,12 @@
 }
 
 bool OmniboxPedal::IsConceptMatch(TokenSequence& match_sequence) const {
+  verbatim_synonym_group_.EraseMatchesIn(match_sequence, false);
+  if (match_sequence.IsFullyConsumed()) {
+    return true;
+  }
+  match_sequence.ResetLinks();
+
   for (const auto& group : synonym_groups_) {
     if (!group.EraseMatchesIn(match_sequence, false))
       return false;
@@ -297,6 +310,7 @@
   size_t total = 0;
   total += OmniboxAction::EstimateMemoryUsage();
   total += base::trace_event::EstimateMemoryUsage(synonym_groups_);
+  total += base::trace_event::EstimateMemoryUsage(verbatim_synonym_group_);
   return total;
 }
 
diff --git a/components/omnibox/browser/actions/omnibox_pedal.h b/components/omnibox/browser/actions/omnibox_pedal.h
index 2754af4c..66e9dae 100644
--- a/components/omnibox/browser/actions/omnibox_pedal.h
+++ b/components/omnibox/browser/actions/omnibox_pedal.h
@@ -188,6 +188,17 @@
   static const gfx::VectorIcon& GetDefaultVectorIcon();
 #endif
 
+  // Add a verbatim token sequence for direct matching.
+  // This can improve user experience of omnibox pedals by ensuring that
+  // button text entered verbatim is always a sufficient trigger. Since
+  // button text labels are not always within the specified set of triggers,
+  // it may be possible to discover a pedal, memorize the button
+  // label, and then go seeking it out again with the button label, but
+  // not find it. With the verbatim sequence, learning a pedal by label will
+  // always make the pedal available with that exact input (ignoring case and
+  // the common ignore group).
+  void AddVerbatimSequence(TokenSequence sequence);
+
   // Move a synonym group into this Pedal's collection.
   void AddSynonymGroup(SynonymGroup&& group);
 
@@ -220,6 +231,8 @@
  protected:
   FRIEND_TEST_ALL_PREFIXES(OmniboxPedalTest, SynonymGroupErasesFirstMatchOnly);
   FRIEND_TEST_ALL_PREFIXES(OmniboxPedalTest, SynonymGroupsDriveConceptMatches);
+  FRIEND_TEST_ALL_PREFIXES(OmniboxPedalTest,
+                           VerbatimSynonymGroupDrivesConceptMatches);
   FRIEND_TEST_ALL_PREFIXES(OmniboxPedalImplementationsTest,
                            UnorderedSynonymExpressionsAreConceptMatches);
 
@@ -227,6 +240,10 @@
 
   OmniboxPedalId id_;
 
+  // Before standard synonym group matching, we can check the verbatim
+  // syonym group for direct matches, e.g. with the button label text.
+  SynonymGroup verbatim_synonym_group_;
+
   std::vector<SynonymGroup> synonym_groups_;
 };
 
diff --git a/components/omnibox/browser/actions/omnibox_pedal_concepts.h b/components/omnibox/browser/actions/omnibox_pedal_concepts.h
index 33739870..1f01457 100644
--- a/components/omnibox/browser/actions/omnibox_pedal_concepts.h
+++ b/components/omnibox/browser/actions/omnibox_pedal_concepts.h
@@ -10,7 +10,7 @@
 // This value is generated during Pedal concept data processing, and written
 // to all data files as well as the source code here to ensure synchrony.
 // The runtime loaded data must match this version exactly or it won't load.
-constexpr int OMNIBOX_PEDAL_CONCEPTS_DATA_VERSION = 16031267;
+constexpr int OMNIBOX_PEDAL_CONCEPTS_DATA_VERSION = 16049958;
 
 // Unique identifiers for Pedals, used to bind loaded data to implementations.
 // Also used in the Omnibox.SuggestionUsed.Pedal histogram. Do not remove or
diff --git a/components/omnibox/browser/actions/omnibox_pedal_implementations.cc b/components/omnibox/browser/actions/omnibox_pedal_implementations.cc
index 0ab6aa84..4ed8a729 100644
--- a/components/omnibox/browser/actions/omnibox_pedal_implementations.cc
+++ b/components/omnibox/browser/actions/omnibox_pedal_implementations.cc
@@ -30,6 +30,10 @@
 #include "components/vector_icons/vector_icons.h"     // nogncheck
 #endif
 
+// This is the blue for some pedals that refer to settings pages,
+// taken to match existing icons e.g. the blue chrome://settings gear.
+constexpr SkColor kChromePagesBlue = SkColorSetARGB(255, 60, 115, 229);
+
 // =============================================================================
 
 class OmniboxPedalClearBrowsingData : public OmniboxPedal {
@@ -1162,6 +1166,8 @@
   }
 #endif
 
+  SkColor GetVectorIconColor() const override { return kChromePagesBlue; }
+
  protected:
   ~OmniboxPedalManageChromeSettings() override = default;
 };
@@ -1186,6 +1192,8 @@
   }
 #endif
 
+  SkColor GetVectorIconColor() const override { return kChromePagesBlue; }
+
  protected:
   ~OmniboxPedalManageChromeDownloads() override = default;
 };
@@ -1210,6 +1218,8 @@
   }
 #endif
 
+  SkColor GetVectorIconColor() const override { return kChromePagesBlue; }
+
  protected:
   ~OmniboxPedalViewChromeHistory() override = default;
 };
@@ -1267,6 +1277,8 @@
   }
 #endif
 
+  SkColor GetVectorIconColor() const override { return kChromePagesBlue; }
+
  protected:
   ~OmniboxPedalManageChromeAccessibility() override = default;
 };
@@ -1291,6 +1303,8 @@
   }
 #endif
 
+  SkColor GetVectorIconColor() const override { return kChromePagesBlue; }
+
   OmniboxPedalId GetMetricsId() const override {
     return OmniboxPedalId::MANAGE_CHROME_ACCESSIBILITY;
   }
diff --git a/components/omnibox/browser/actions/omnibox_pedal_implementations_unittest.cc b/components/omnibox/browser/actions/omnibox_pedal_implementations_unittest.cc
index a4e682a..29ee84f 100644
--- a/components/omnibox/browser/actions/omnibox_pedal_implementations_unittest.cc
+++ b/components/omnibox/browser/actions/omnibox_pedal_implementations_unittest.cc
@@ -16461,11 +16461,18 @@
         // ID#34
         {
             // Generated suggestions:
+            "cast page",
+            "cast screen",
+            "cast this page",
             "qr code",
+            "save page as",
+            "save this page",
             "send link",
+            "send link via qr code",
             "send link with qr code",
             "send page",
             "share link",
+            "share link via qr code",
             "share link with qr code",
             "share page",
             "share this page",
@@ -17360,97 +17367,1182 @@
         // ID#38
         {
             // Generated suggestions:
+            "add browser custom search",
+            "add browser custom search engines",
+            "add browser customized search",
+            "add browser scoped search",
+            "add browser search engines",
+            "add browser site search",
+            "add browser site search engines",
+            "add browser tab to search",
+            "add chrome custom search",
+            "add chrome custom search engines",
+            "add chrome customized search",
+            "add chrome scoped search",
+            "add chrome search engines",
+            "add chrome site search",
+            "add chrome site search engines",
+            "add chrome tab to search",
+            "add custom search",
+            "add custom search browser",
+            "add custom search chrome",
+            "add custom search engines",
+            "add custom search engines browser",
+            "add custom search engines chrome",
+            "add custom search engines google chrome",
+            "add custom search google chrome",
+            "add customized search",
+            "add customized search browser",
+            "add customized search chrome",
+            "add customized search google chrome",
+            "add google chrome custom search",
+            "add google chrome custom search engines",
+            "add google chrome customized search",
+            "add google chrome scoped search",
+            "add google chrome search engines",
+            "add google chrome site search",
+            "add google chrome site search engines",
+            "add google chrome tab to search",
+            "add scoped search",
+            "add scoped search browser",
+            "add scoped search chrome",
+            "add scoped search google chrome",
+            "add search engines",
+            "add search engines browser",
+            "add search engines chrome",
+            "add search engines google chrome",
+            "add site search",
+            "add site search browser",
+            "add site search chrome",
+            "add site search engines",
+            "add site search engines browser",
+            "add site search engines chrome",
+            "add site search engines google chrome",
+            "add site search google chrome",
+            "add tab to search",
+            "add tab to search browser",
+            "add tab to search chrome",
+            "add tab to search google chrome",
+            "browser add custom search",
+            "browser add custom search engines",
+            "browser add customized search",
+            "browser add scoped search",
+            "browser add search engines",
+            "browser add site search",
+            "browser add site search engines",
+            "browser add tab to search",
+            "browser change custom search",
+            "browser change custom search engines",
+            "browser change customized search",
+            "browser change scoped search",
+            "browser change search engines",
+            "browser change site search",
+            "browser change site search engines",
+            "browser change tab to search",
+            "browser control custom search",
+            "browser control custom search engines",
+            "browser control customized search",
+            "browser control scoped search",
+            "browser control search engines",
+            "browser control site search",
+            "browser control site search engines",
+            "browser control tab to search",
+            "browser custom search",
+            "browser custom search add",
+            "browser custom search change",
+            "browser custom search control",
+            "browser custom search customize",
+            "browser custom search edit",
+            "browser custom search engines",
+            "browser custom search engines add",
+            "browser custom search engines change",
+            "browser custom search engines control",
+            "browser custom search engines customize",
+            "browser custom search engines edit",
+            "browser custom search engines manage",
+            "browser custom search engines modify",
+            "browser custom search manage",
+            "browser custom search modify",
+            "browser customize custom search",
+            "browser customize custom search engines",
+            "browser customize customized search",
+            "browser customize scoped search",
+            "browser customize search engines",
+            "browser customize site search",
+            "browser customize site search engines",
+            "browser customize tab to search",
+            "browser customized search",
+            "browser customized search add",
+            "browser customized search change",
+            "browser customized search control",
+            "browser customized search customize",
+            "browser customized search edit",
+            "browser customized search manage",
+            "browser customized search modify",
+            "browser edit custom search",
+            "browser edit custom search engines",
+            "browser edit customized search",
+            "browser edit scoped search",
+            "browser edit search engines",
+            "browser edit site search",
+            "browser edit site search engines",
+            "browser edit tab to search",
+            "browser manage custom search",
+            "browser manage custom search engines",
+            "browser manage customized search",
+            "browser manage scoped search",
+            "browser manage search engines",
+            "browser manage site search",
+            "browser manage site search engines",
+            "browser manage tab to search",
+            "browser modify custom search",
+            "browser modify custom search engines",
+            "browser modify customized search",
+            "browser modify scoped search",
+            "browser modify search engines",
+            "browser modify site search",
+            "browser modify site search engines",
+            "browser modify tab to search",
+            "browser scoped search",
+            "browser scoped search add",
+            "browser scoped search change",
+            "browser scoped search control",
+            "browser scoped search customize",
+            "browser scoped search edit",
+            "browser scoped search manage",
+            "browser scoped search modify",
+            "browser search engines",
+            "browser search engines add",
+            "browser search engines change",
+            "browser search engines control",
+            "browser search engines customize",
+            "browser search engines edit",
+            "browser search engines manage",
+            "browser search engines modify",
+            "browser site search",
+            "browser site search add",
+            "browser site search change",
+            "browser site search control",
+            "browser site search customize",
+            "browser site search edit",
+            "browser site search engines",
+            "browser site search engines add",
+            "browser site search engines change",
+            "browser site search engines control",
+            "browser site search engines customize",
+            "browser site search engines edit",
+            "browser site search engines manage",
+            "browser site search engines modify",
+            "browser site search manage",
+            "browser site search modify",
+            "browser tab to search",
+            "browser tab to search add",
+            "browser tab to search change",
+            "browser tab to search control",
+            "browser tab to search customize",
+            "browser tab to search edit",
+            "browser tab to search manage",
+            "browser tab to search modify",
+            "change browser custom search",
+            "change browser custom search engines",
+            "change browser customized search",
+            "change browser scoped search",
+            "change browser search engines",
+            "change browser site search",
+            "change browser site search engines",
+            "change browser tab to search",
+            "change chrome custom search",
+            "change chrome custom search engines",
+            "change chrome customized search",
+            "change chrome scoped search",
+            "change chrome search engines",
+            "change chrome site search",
+            "change chrome site search engines",
+            "change chrome tab to search",
             "change custom search",
+            "change custom search browser",
+            "change custom search chrome",
             "change custom search engines",
+            "change custom search engines browser",
+            "change custom search engines chrome",
+            "change custom search engines google chrome",
+            "change custom search google chrome",
             "change customized search",
+            "change customized search browser",
+            "change customized search chrome",
+            "change customized search google chrome",
+            "change google chrome custom search",
+            "change google chrome custom search engines",
+            "change google chrome customized search",
+            "change google chrome scoped search",
+            "change google chrome search engines",
+            "change google chrome site search",
+            "change google chrome site search engines",
+            "change google chrome tab to search",
             "change scoped search",
+            "change scoped search browser",
+            "change scoped search chrome",
+            "change scoped search google chrome",
+            "change search engines",
+            "change search engines browser",
+            "change search engines chrome",
+            "change search engines google chrome",
             "change site search",
+            "change site search browser",
+            "change site search chrome",
             "change site search engines",
+            "change site search engines browser",
+            "change site search engines chrome",
+            "change site search engines google chrome",
+            "change site search google chrome",
             "change tab to search",
+            "change tab to search browser",
+            "change tab to search chrome",
+            "change tab to search google chrome",
+            "chrome add custom search",
+            "chrome add custom search engines",
+            "chrome add customized search",
+            "chrome add scoped search",
+            "chrome add search engines",
+            "chrome add site search",
+            "chrome add site search engines",
+            "chrome add tab to search",
+            "chrome change custom search",
+            "chrome change custom search engines",
+            "chrome change customized search",
+            "chrome change scoped search",
+            "chrome change search engines",
+            "chrome change site search",
+            "chrome change site search engines",
+            "chrome change tab to search",
+            "chrome control custom search",
+            "chrome control custom search engines",
+            "chrome control customized search",
+            "chrome control scoped search",
+            "chrome control search engines",
+            "chrome control site search",
+            "chrome control site search engines",
+            "chrome control tab to search",
+            "chrome custom search",
+            "chrome custom search add",
+            "chrome custom search change",
+            "chrome custom search control",
+            "chrome custom search customize",
+            "chrome custom search edit",
+            "chrome custom search engines",
+            "chrome custom search engines add",
+            "chrome custom search engines change",
+            "chrome custom search engines control",
+            "chrome custom search engines customize",
+            "chrome custom search engines edit",
+            "chrome custom search engines manage",
+            "chrome custom search engines modify",
+            "chrome custom search manage",
+            "chrome custom search modify",
+            "chrome customize custom search",
+            "chrome customize custom search engines",
+            "chrome customize customized search",
+            "chrome customize scoped search",
+            "chrome customize search engines",
+            "chrome customize site search",
+            "chrome customize site search engines",
+            "chrome customize tab to search",
+            "chrome customized search",
+            "chrome customized search add",
+            "chrome customized search change",
+            "chrome customized search control",
+            "chrome customized search customize",
+            "chrome customized search edit",
+            "chrome customized search manage",
+            "chrome customized search modify",
+            "chrome edit custom search",
+            "chrome edit custom search engines",
+            "chrome edit customized search",
+            "chrome edit scoped search",
+            "chrome edit search engines",
+            "chrome edit site search",
+            "chrome edit site search engines",
+            "chrome edit tab to search",
+            "chrome manage custom search",
+            "chrome manage custom search engines",
+            "chrome manage customized search",
+            "chrome manage scoped search",
+            "chrome manage search engines",
+            "chrome manage site search",
+            "chrome manage site search engines",
+            "chrome manage tab to search",
+            "chrome modify custom search",
+            "chrome modify custom search engines",
+            "chrome modify customized search",
+            "chrome modify scoped search",
+            "chrome modify search engines",
+            "chrome modify site search",
+            "chrome modify site search engines",
+            "chrome modify tab to search",
+            "chrome scoped search",
+            "chrome scoped search add",
+            "chrome scoped search change",
+            "chrome scoped search control",
+            "chrome scoped search customize",
+            "chrome scoped search edit",
+            "chrome scoped search manage",
+            "chrome scoped search modify",
+            "chrome search engines",
+            "chrome search engines add",
+            "chrome search engines change",
+            "chrome search engines control",
+            "chrome search engines customize",
+            "chrome search engines edit",
+            "chrome search engines manage",
+            "chrome search engines modify",
+            "chrome site search",
+            "chrome site search add",
+            "chrome site search change",
+            "chrome site search control",
+            "chrome site search customize",
+            "chrome site search edit",
+            "chrome site search engines",
+            "chrome site search engines add",
+            "chrome site search engines change",
+            "chrome site search engines control",
+            "chrome site search engines customize",
+            "chrome site search engines edit",
+            "chrome site search engines manage",
+            "chrome site search engines modify",
+            "chrome site search manage",
+            "chrome site search modify",
+            "chrome tab to search",
+            "chrome tab to search add",
+            "chrome tab to search change",
+            "chrome tab to search control",
+            "chrome tab to search customize",
+            "chrome tab to search edit",
+            "chrome tab to search manage",
+            "chrome tab to search modify",
+            "control browser custom search",
+            "control browser custom search engines",
+            "control browser customized search",
+            "control browser scoped search",
+            "control browser search engines",
+            "control browser site search",
+            "control browser site search engines",
+            "control browser tab to search",
+            "control chrome custom search",
+            "control chrome custom search engines",
+            "control chrome customized search",
+            "control chrome scoped search",
+            "control chrome search engines",
+            "control chrome site search",
+            "control chrome site search engines",
+            "control chrome tab to search",
             "control custom search",
+            "control custom search browser",
+            "control custom search chrome",
             "control custom search engines",
+            "control custom search engines browser",
+            "control custom search engines chrome",
+            "control custom search engines google chrome",
+            "control custom search google chrome",
             "control customized search",
+            "control customized search browser",
+            "control customized search chrome",
+            "control customized search google chrome",
+            "control google chrome custom search",
+            "control google chrome custom search engines",
+            "control google chrome customized search",
+            "control google chrome scoped search",
+            "control google chrome search engines",
+            "control google chrome site search",
+            "control google chrome site search engines",
+            "control google chrome tab to search",
             "control scoped search",
+            "control scoped search browser",
+            "control scoped search chrome",
+            "control scoped search google chrome",
+            "control search engines",
+            "control search engines browser",
+            "control search engines chrome",
+            "control search engines google chrome",
             "control site search",
+            "control site search browser",
+            "control site search chrome",
             "control site search engines",
+            "control site search engines browser",
+            "control site search engines chrome",
+            "control site search engines google chrome",
+            "control site search google chrome",
             "control tab to search",
+            "control tab to search browser",
+            "control tab to search chrome",
+            "control tab to search google chrome",
             "custom search",
+            "custom search add",
+            "custom search add browser",
+            "custom search add chrome",
+            "custom search add google chrome",
+            "custom search browser",
+            "custom search browser add",
+            "custom search browser change",
+            "custom search browser control",
+            "custom search browser customize",
+            "custom search browser edit",
+            "custom search browser manage",
+            "custom search browser modify",
             "custom search change",
+            "custom search change browser",
+            "custom search change chrome",
+            "custom search change google chrome",
+            "custom search chrome",
+            "custom search chrome add",
+            "custom search chrome change",
+            "custom search chrome control",
+            "custom search chrome customize",
+            "custom search chrome edit",
+            "custom search chrome manage",
+            "custom search chrome modify",
             "custom search control",
+            "custom search control browser",
+            "custom search control chrome",
+            "custom search control google chrome",
             "custom search customize",
+            "custom search customize browser",
+            "custom search customize chrome",
+            "custom search customize google chrome",
             "custom search edit",
+            "custom search edit browser",
+            "custom search edit chrome",
+            "custom search edit google chrome",
             "custom search engines",
+            "custom search engines add",
+            "custom search engines add browser",
+            "custom search engines add chrome",
+            "custom search engines add google chrome",
+            "custom search engines browser",
+            "custom search engines browser add",
+            "custom search engines browser change",
+            "custom search engines browser control",
+            "custom search engines browser customize",
+            "custom search engines browser edit",
+            "custom search engines browser manage",
+            "custom search engines browser modify",
             "custom search engines change",
+            "custom search engines change browser",
+            "custom search engines change chrome",
+            "custom search engines change google chrome",
+            "custom search engines chrome",
+            "custom search engines chrome add",
+            "custom search engines chrome change",
+            "custom search engines chrome control",
+            "custom search engines chrome customize",
+            "custom search engines chrome edit",
+            "custom search engines chrome manage",
+            "custom search engines chrome modify",
             "custom search engines control",
+            "custom search engines control browser",
+            "custom search engines control chrome",
+            "custom search engines control google chrome",
             "custom search engines customize",
+            "custom search engines customize browser",
+            "custom search engines customize chrome",
+            "custom search engines customize google chrome",
             "custom search engines edit",
+            "custom search engines edit browser",
+            "custom search engines edit chrome",
+            "custom search engines edit google chrome",
+            "custom search engines google chrome",
+            "custom search engines google chrome add",
+            "custom search engines google chrome change",
+            "custom search engines google chrome control",
+            "custom search engines google chrome customize",
+            "custom search engines google chrome edit",
+            "custom search engines google chrome manage",
+            "custom search engines google chrome modify",
             "custom search engines manage",
+            "custom search engines manage browser",
+            "custom search engines manage chrome",
+            "custom search engines manage google chrome",
             "custom search engines modify",
+            "custom search engines modify browser",
+            "custom search engines modify chrome",
+            "custom search engines modify google chrome",
+            "custom search google chrome",
+            "custom search google chrome add",
+            "custom search google chrome change",
+            "custom search google chrome control",
+            "custom search google chrome customize",
+            "custom search google chrome edit",
+            "custom search google chrome manage",
+            "custom search google chrome modify",
             "custom search manage",
+            "custom search manage browser",
+            "custom search manage chrome",
+            "custom search manage google chrome",
             "custom search modify",
+            "custom search modify browser",
+            "custom search modify chrome",
+            "custom search modify google chrome",
+            "customize browser custom search",
+            "customize browser custom search engines",
+            "customize browser customized search",
+            "customize browser scoped search",
+            "customize browser search engines",
+            "customize browser site search",
+            "customize browser site search engines",
+            "customize browser tab to search",
+            "customize chrome custom search",
+            "customize chrome custom search engines",
+            "customize chrome customized search",
+            "customize chrome scoped search",
+            "customize chrome search engines",
+            "customize chrome site search",
+            "customize chrome site search engines",
+            "customize chrome tab to search",
             "customize custom search",
+            "customize custom search browser",
+            "customize custom search chrome",
             "customize custom search engines",
+            "customize custom search engines browser",
+            "customize custom search engines chrome",
+            "customize custom search engines google chrome",
+            "customize custom search google chrome",
             "customize customized search",
+            "customize customized search browser",
+            "customize customized search chrome",
+            "customize customized search google chrome",
+            "customize google chrome custom search",
+            "customize google chrome custom search engines",
+            "customize google chrome customized search",
+            "customize google chrome scoped search",
+            "customize google chrome search engines",
+            "customize google chrome site search",
+            "customize google chrome site search engines",
+            "customize google chrome tab to search",
             "customize scoped search",
+            "customize scoped search browser",
+            "customize scoped search chrome",
+            "customize scoped search google chrome",
+            "customize search engines",
+            "customize search engines browser",
+            "customize search engines chrome",
+            "customize search engines google chrome",
             "customize site search",
+            "customize site search browser",
+            "customize site search chrome",
             "customize site search engines",
+            "customize site search engines browser",
+            "customize site search engines chrome",
+            "customize site search engines google chrome",
+            "customize site search google chrome",
             "customize tab to search",
+            "customize tab to search browser",
+            "customize tab to search chrome",
+            "customize tab to search google chrome",
             "customized search",
+            "customized search add",
+            "customized search add browser",
+            "customized search add chrome",
+            "customized search add google chrome",
+            "customized search browser",
+            "customized search browser add",
+            "customized search browser change",
+            "customized search browser control",
+            "customized search browser customize",
+            "customized search browser edit",
+            "customized search browser manage",
+            "customized search browser modify",
             "customized search change",
+            "customized search change browser",
+            "customized search change chrome",
+            "customized search change google chrome",
+            "customized search chrome",
+            "customized search chrome add",
+            "customized search chrome change",
+            "customized search chrome control",
+            "customized search chrome customize",
+            "customized search chrome edit",
+            "customized search chrome manage",
+            "customized search chrome modify",
             "customized search control",
+            "customized search control browser",
+            "customized search control chrome",
+            "customized search control google chrome",
             "customized search customize",
+            "customized search customize browser",
+            "customized search customize chrome",
+            "customized search customize google chrome",
             "customized search edit",
+            "customized search edit browser",
+            "customized search edit chrome",
+            "customized search edit google chrome",
+            "customized search google chrome",
+            "customized search google chrome add",
+            "customized search google chrome change",
+            "customized search google chrome control",
+            "customized search google chrome customize",
+            "customized search google chrome edit",
+            "customized search google chrome manage",
+            "customized search google chrome modify",
             "customized search manage",
+            "customized search manage browser",
+            "customized search manage chrome",
+            "customized search manage google chrome",
             "customized search modify",
+            "customized search modify browser",
+            "customized search modify chrome",
+            "customized search modify google chrome",
+            "edit browser custom search",
+            "edit browser custom search engines",
+            "edit browser customized search",
+            "edit browser scoped search",
+            "edit browser search engines",
+            "edit browser site search",
+            "edit browser site search engines",
+            "edit browser tab to search",
+            "edit chrome custom search",
+            "edit chrome custom search engines",
+            "edit chrome customized search",
+            "edit chrome scoped search",
+            "edit chrome search engines",
+            "edit chrome site search",
+            "edit chrome site search engines",
+            "edit chrome tab to search",
             "edit custom search",
+            "edit custom search browser",
+            "edit custom search chrome",
             "edit custom search engines",
+            "edit custom search engines browser",
+            "edit custom search engines chrome",
+            "edit custom search engines google chrome",
+            "edit custom search google chrome",
             "edit customized search",
+            "edit customized search browser",
+            "edit customized search chrome",
+            "edit customized search google chrome",
+            "edit google chrome custom search",
+            "edit google chrome custom search engines",
+            "edit google chrome customized search",
+            "edit google chrome scoped search",
+            "edit google chrome search engines",
+            "edit google chrome site search",
+            "edit google chrome site search engines",
+            "edit google chrome tab to search",
             "edit scoped search",
+            "edit scoped search browser",
+            "edit scoped search chrome",
+            "edit scoped search google chrome",
+            "edit search engines",
+            "edit search engines browser",
+            "edit search engines chrome",
+            "edit search engines google chrome",
             "edit site search",
+            "edit site search browser",
+            "edit site search chrome",
             "edit site search engines",
+            "edit site search engines browser",
+            "edit site search engines chrome",
+            "edit site search engines google chrome",
+            "edit site search google chrome",
             "edit tab to search",
+            "edit tab to search browser",
+            "edit tab to search chrome",
+            "edit tab to search google chrome",
+            "google chrome add custom search",
+            "google chrome add custom search engines",
+            "google chrome add customized search",
+            "google chrome add scoped search",
+            "google chrome add search engines",
+            "google chrome add site search",
+            "google chrome add site search engines",
+            "google chrome add tab to search",
+            "google chrome change custom search",
+            "google chrome change custom search engines",
+            "google chrome change customized search",
+            "google chrome change scoped search",
+            "google chrome change search engines",
+            "google chrome change site search",
+            "google chrome change site search engines",
+            "google chrome change tab to search",
+            "google chrome control custom search",
+            "google chrome control custom search engines",
+            "google chrome control customized search",
+            "google chrome control scoped search",
+            "google chrome control search engines",
+            "google chrome control site search",
+            "google chrome control site search engines",
+            "google chrome control tab to search",
+            "google chrome custom search",
+            "google chrome custom search add",
+            "google chrome custom search change",
+            "google chrome custom search control",
+            "google chrome custom search customize",
+            "google chrome custom search edit",
+            "google chrome custom search engines",
+            "google chrome custom search engines add",
+            "google chrome custom search engines change",
+            "google chrome custom search engines control",
+            "google chrome custom search engines customize",
+            "google chrome custom search engines edit",
+            "google chrome custom search engines manage",
+            "google chrome custom search engines modify",
+            "google chrome custom search manage",
+            "google chrome custom search modify",
+            "google chrome customize custom search",
+            "google chrome customize custom search engines",
+            "google chrome customize customized search",
+            "google chrome customize scoped search",
+            "google chrome customize search engines",
+            "google chrome customize site search",
+            "google chrome customize site search engines",
+            "google chrome customize tab to search",
+            "google chrome customized search",
+            "google chrome customized search add",
+            "google chrome customized search change",
+            "google chrome customized search control",
+            "google chrome customized search customize",
+            "google chrome customized search edit",
+            "google chrome customized search manage",
+            "google chrome customized search modify",
+            "google chrome edit custom search",
+            "google chrome edit custom search engines",
+            "google chrome edit customized search",
+            "google chrome edit scoped search",
+            "google chrome edit search engines",
+            "google chrome edit site search",
+            "google chrome edit site search engines",
+            "google chrome edit tab to search",
+            "google chrome manage custom search",
+            "google chrome manage custom search engines",
+            "google chrome manage customized search",
+            "google chrome manage scoped search",
+            "google chrome manage search engines",
+            "google chrome manage site search",
+            "google chrome manage site search engines",
+            "google chrome manage tab to search",
+            "google chrome modify custom search",
+            "google chrome modify custom search engines",
+            "google chrome modify customized search",
+            "google chrome modify scoped search",
+            "google chrome modify search engines",
+            "google chrome modify site search",
+            "google chrome modify site search engines",
+            "google chrome modify tab to search",
+            "google chrome scoped search",
+            "google chrome scoped search add",
+            "google chrome scoped search change",
+            "google chrome scoped search control",
+            "google chrome scoped search customize",
+            "google chrome scoped search edit",
+            "google chrome scoped search manage",
+            "google chrome scoped search modify",
+            "google chrome search engines",
+            "google chrome search engines add",
+            "google chrome search engines change",
+            "google chrome search engines control",
+            "google chrome search engines customize",
+            "google chrome search engines edit",
+            "google chrome search engines manage",
+            "google chrome search engines modify",
+            "google chrome site search",
+            "google chrome site search add",
+            "google chrome site search change",
+            "google chrome site search control",
+            "google chrome site search customize",
+            "google chrome site search edit",
+            "google chrome site search engines",
+            "google chrome site search engines add",
+            "google chrome site search engines change",
+            "google chrome site search engines control",
+            "google chrome site search engines customize",
+            "google chrome site search engines edit",
+            "google chrome site search engines manage",
+            "google chrome site search engines modify",
+            "google chrome site search manage",
+            "google chrome site search modify",
+            "google chrome tab to search",
+            "google chrome tab to search add",
+            "google chrome tab to search change",
+            "google chrome tab to search control",
+            "google chrome tab to search customize",
+            "google chrome tab to search edit",
+            "google chrome tab to search manage",
+            "google chrome tab to search modify",
+            "manage browser custom search",
+            "manage browser custom search engines",
+            "manage browser customized search",
+            "manage browser scoped search",
+            "manage browser search engines",
+            "manage browser site search",
+            "manage browser site search engines",
+            "manage browser tab to search",
+            "manage chrome custom search",
+            "manage chrome custom search engines",
+            "manage chrome customized search",
+            "manage chrome scoped search",
+            "manage chrome search engines",
+            "manage chrome site search",
+            "manage chrome site search engines",
+            "manage chrome tab to search",
             "manage custom search",
+            "manage custom search browser",
+            "manage custom search chrome",
             "manage custom search engines",
+            "manage custom search engines browser",
+            "manage custom search engines chrome",
+            "manage custom search engines google chrome",
+            "manage custom search google chrome",
             "manage customized search",
+            "manage customized search browser",
+            "manage customized search chrome",
+            "manage customized search google chrome",
+            "manage google chrome custom search",
+            "manage google chrome custom search engines",
+            "manage google chrome customized search",
+            "manage google chrome scoped search",
+            "manage google chrome search engines",
+            "manage google chrome site search",
+            "manage google chrome site search engines",
+            "manage google chrome tab to search",
             "manage scoped search",
+            "manage scoped search browser",
+            "manage scoped search chrome",
+            "manage scoped search google chrome",
+            "manage search engines",
+            "manage search engines browser",
+            "manage search engines chrome",
+            "manage search engines google chrome",
             "manage site search",
+            "manage site search browser",
+            "manage site search chrome",
             "manage site search engines",
+            "manage site search engines browser",
+            "manage site search engines chrome",
+            "manage site search engines google chrome",
+            "manage site search google chrome",
             "manage tab to search",
+            "manage tab to search browser",
+            "manage tab to search chrome",
+            "manage tab to search google chrome",
+            "modify browser custom search",
+            "modify browser custom search engines",
+            "modify browser customized search",
+            "modify browser scoped search",
+            "modify browser search engines",
+            "modify browser site search",
+            "modify browser site search engines",
+            "modify browser tab to search",
+            "modify chrome custom search",
+            "modify chrome custom search engines",
+            "modify chrome customized search",
+            "modify chrome scoped search",
+            "modify chrome search engines",
+            "modify chrome site search",
+            "modify chrome site search engines",
+            "modify chrome tab to search",
             "modify custom search",
+            "modify custom search browser",
+            "modify custom search chrome",
             "modify custom search engines",
+            "modify custom search engines browser",
+            "modify custom search engines chrome",
+            "modify custom search engines google chrome",
+            "modify custom search google chrome",
             "modify customized search",
+            "modify customized search browser",
+            "modify customized search chrome",
+            "modify customized search google chrome",
+            "modify google chrome custom search",
+            "modify google chrome custom search engines",
+            "modify google chrome customized search",
+            "modify google chrome scoped search",
+            "modify google chrome search engines",
+            "modify google chrome site search",
+            "modify google chrome site search engines",
+            "modify google chrome tab to search",
             "modify scoped search",
+            "modify scoped search browser",
+            "modify scoped search chrome",
+            "modify scoped search google chrome",
+            "modify search engines",
+            "modify search engines browser",
+            "modify search engines chrome",
+            "modify search engines google chrome",
             "modify site search",
+            "modify site search browser",
+            "modify site search chrome",
             "modify site search engines",
+            "modify site search engines browser",
+            "modify site search engines chrome",
+            "modify site search engines google chrome",
+            "modify site search google chrome",
             "modify tab to search",
+            "modify tab to search browser",
+            "modify tab to search chrome",
+            "modify tab to search google chrome",
             "scoped search",
+            "scoped search add",
+            "scoped search add browser",
+            "scoped search add chrome",
+            "scoped search add google chrome",
+            "scoped search browser",
+            "scoped search browser add",
+            "scoped search browser change",
+            "scoped search browser control",
+            "scoped search browser customize",
+            "scoped search browser edit",
+            "scoped search browser manage",
+            "scoped search browser modify",
             "scoped search change",
+            "scoped search change browser",
+            "scoped search change chrome",
+            "scoped search change google chrome",
+            "scoped search chrome",
+            "scoped search chrome add",
+            "scoped search chrome change",
+            "scoped search chrome control",
+            "scoped search chrome customize",
+            "scoped search chrome edit",
+            "scoped search chrome manage",
+            "scoped search chrome modify",
             "scoped search control",
+            "scoped search control browser",
+            "scoped search control chrome",
+            "scoped search control google chrome",
             "scoped search customize",
+            "scoped search customize browser",
+            "scoped search customize chrome",
+            "scoped search customize google chrome",
             "scoped search edit",
+            "scoped search edit browser",
+            "scoped search edit chrome",
+            "scoped search edit google chrome",
+            "scoped search google chrome",
+            "scoped search google chrome add",
+            "scoped search google chrome change",
+            "scoped search google chrome control",
+            "scoped search google chrome customize",
+            "scoped search google chrome edit",
+            "scoped search google chrome manage",
+            "scoped search google chrome modify",
             "scoped search manage",
+            "scoped search manage browser",
+            "scoped search manage chrome",
+            "scoped search manage google chrome",
             "scoped search modify",
+            "scoped search modify browser",
+            "scoped search modify chrome",
+            "scoped search modify google chrome",
+            "search engines",
+            "search engines add",
+            "search engines add browser",
+            "search engines add chrome",
+            "search engines add google chrome",
+            "search engines browser",
+            "search engines browser add",
+            "search engines browser change",
+            "search engines browser control",
+            "search engines browser customize",
+            "search engines browser edit",
+            "search engines browser manage",
+            "search engines browser modify",
+            "search engines change",
+            "search engines change browser",
+            "search engines change chrome",
+            "search engines change google chrome",
+            "search engines chrome",
+            "search engines chrome add",
+            "search engines chrome change",
+            "search engines chrome control",
+            "search engines chrome customize",
+            "search engines chrome edit",
+            "search engines chrome manage",
+            "search engines chrome modify",
+            "search engines control",
+            "search engines control browser",
+            "search engines control chrome",
+            "search engines control google chrome",
+            "search engines customize",
+            "search engines customize browser",
+            "search engines customize chrome",
+            "search engines customize google chrome",
+            "search engines edit",
+            "search engines edit browser",
+            "search engines edit chrome",
+            "search engines edit google chrome",
+            "search engines google chrome",
+            "search engines google chrome add",
+            "search engines google chrome change",
+            "search engines google chrome control",
+            "search engines google chrome customize",
+            "search engines google chrome edit",
+            "search engines google chrome manage",
+            "search engines google chrome modify",
+            "search engines manage",
+            "search engines manage browser",
+            "search engines manage chrome",
+            "search engines manage google chrome",
+            "search engines modify",
+            "search engines modify browser",
+            "search engines modify chrome",
+            "search engines modify google chrome",
             "site search",
+            "site search add",
+            "site search add browser",
+            "site search add chrome",
+            "site search add google chrome",
+            "site search browser",
+            "site search browser add",
+            "site search browser change",
+            "site search browser control",
+            "site search browser customize",
+            "site search browser edit",
+            "site search browser manage",
+            "site search browser modify",
             "site search change",
+            "site search change browser",
+            "site search change chrome",
+            "site search change google chrome",
+            "site search chrome",
+            "site search chrome add",
+            "site search chrome change",
+            "site search chrome control",
+            "site search chrome customize",
+            "site search chrome edit",
+            "site search chrome manage",
+            "site search chrome modify",
             "site search control",
+            "site search control browser",
+            "site search control chrome",
+            "site search control google chrome",
             "site search customize",
+            "site search customize browser",
+            "site search customize chrome",
+            "site search customize google chrome",
             "site search edit",
+            "site search edit browser",
+            "site search edit chrome",
+            "site search edit google chrome",
             "site search engines",
+            "site search engines add",
+            "site search engines add browser",
+            "site search engines add chrome",
+            "site search engines add google chrome",
+            "site search engines browser",
+            "site search engines browser add",
+            "site search engines browser change",
+            "site search engines browser control",
+            "site search engines browser customize",
+            "site search engines browser edit",
+            "site search engines browser manage",
+            "site search engines browser modify",
             "site search engines change",
+            "site search engines change browser",
+            "site search engines change chrome",
+            "site search engines change google chrome",
+            "site search engines chrome",
+            "site search engines chrome add",
+            "site search engines chrome change",
+            "site search engines chrome control",
+            "site search engines chrome customize",
+            "site search engines chrome edit",
+            "site search engines chrome manage",
+            "site search engines chrome modify",
             "site search engines control",
+            "site search engines control browser",
+            "site search engines control chrome",
+            "site search engines control google chrome",
             "site search engines customize",
+            "site search engines customize browser",
+            "site search engines customize chrome",
+            "site search engines customize google chrome",
             "site search engines edit",
+            "site search engines edit browser",
+            "site search engines edit chrome",
+            "site search engines edit google chrome",
+            "site search engines google chrome",
+            "site search engines google chrome add",
+            "site search engines google chrome change",
+            "site search engines google chrome control",
+            "site search engines google chrome customize",
+            "site search engines google chrome edit",
+            "site search engines google chrome manage",
+            "site search engines google chrome modify",
             "site search engines manage",
+            "site search engines manage browser",
+            "site search engines manage chrome",
+            "site search engines manage google chrome",
             "site search engines modify",
+            "site search engines modify browser",
+            "site search engines modify chrome",
+            "site search engines modify google chrome",
+            "site search google chrome",
+            "site search google chrome add",
+            "site search google chrome change",
+            "site search google chrome control",
+            "site search google chrome customize",
+            "site search google chrome edit",
+            "site search google chrome manage",
+            "site search google chrome modify",
             "site search manage",
+            "site search manage browser",
+            "site search manage chrome",
+            "site search manage google chrome",
             "site search modify",
+            "site search modify browser",
+            "site search modify chrome",
+            "site search modify google chrome",
             "tab to search",
+            "tab to search add",
+            "tab to search add browser",
+            "tab to search add chrome",
+            "tab to search add google chrome",
+            "tab to search browser",
+            "tab to search browser add",
+            "tab to search browser change",
+            "tab to search browser control",
+            "tab to search browser customize",
+            "tab to search browser edit",
+            "tab to search browser manage",
+            "tab to search browser modify",
             "tab to search change",
+            "tab to search change browser",
+            "tab to search change chrome",
+            "tab to search change google chrome",
+            "tab to search chrome",
+            "tab to search chrome add",
+            "tab to search chrome change",
+            "tab to search chrome control",
+            "tab to search chrome customize",
+            "tab to search chrome edit",
+            "tab to search chrome manage",
+            "tab to search chrome modify",
             "tab to search control",
+            "tab to search control browser",
+            "tab to search control chrome",
+            "tab to search control google chrome",
             "tab to search customize",
+            "tab to search customize browser",
+            "tab to search customize chrome",
+            "tab to search customize google chrome",
             "tab to search edit",
+            "tab to search edit browser",
+            "tab to search edit chrome",
+            "tab to search edit google chrome",
+            "tab to search google chrome",
+            "tab to search google chrome add",
+            "tab to search google chrome change",
+            "tab to search google chrome control",
+            "tab to search google chrome customize",
+            "tab to search google chrome edit",
+            "tab to search google chrome manage",
+            "tab to search google chrome modify",
             "tab to search manage",
+            "tab to search manage browser",
+            "tab to search manage chrome",
+            "tab to search manage google chrome",
             "tab to search modify",
+            "tab to search modify browser",
+            "tab to search modify chrome",
+            "tab to search modify google chrome",
         },
 
         // End of generated test code
diff --git a/components/omnibox/browser/actions/omnibox_pedal_provider.cc b/components/omnibox/browser/actions/omnibox_pedal_provider.cc
index b424678..49a083bc 100644
--- a/components/omnibox/browser/actions/omnibox_pedal_provider.cc
+++ b/components/omnibox/browser/actions/omnibox_pedal_provider.cc
@@ -344,6 +344,11 @@
       pedal->SetNavigationUrl(GURL(*url));
     }
 
+    OmniboxPedal::TokenSequence verbatim_sequence(0);
+    Tokenize(verbatim_sequence, pedal->GetLabelStrings().hint);
+    ignore_group_.EraseMatchesIn(verbatim_sequence, true);
+    pedal->AddVerbatimSequence(std::move(verbatim_sequence));
+
     std::vector<OmniboxPedal::SynonymGroupSpec> specs =
         pedal->SpecifySynonymGroups();
     // `specs` will be empty for any pedals not yet processed by l10n because
diff --git a/components/omnibox/browser/actions/omnibox_pedal_unittest.cc b/components/omnibox/browser/actions/omnibox_pedal_unittest.cc
index 9bcb63ccc..728b7b2 100644
--- a/components/omnibox/browser/actions/omnibox_pedal_unittest.cc
+++ b/components/omnibox/browser/actions/omnibox_pedal_unittest.cc
@@ -104,3 +104,27 @@
   EXPECT_FALSE(is_concept_match(
       make_sequence({required_b, required_a, optional, optional})));
 }
+
+TEST_F(OmniboxPedalTest, VerbatimSynonymGroupDrivesConceptMatches) {
+  constexpr int required_a = 1;
+  constexpr int required_b = 2;
+  constexpr int nonsense = 3;
+  scoped_refptr<OmniboxPedal> test_pedal = base::MakeRefCounted<OmniboxPedal>(
+      OmniboxPedalId::CLEAR_BROWSING_DATA,
+      OmniboxPedal::LabelStrings(
+          IDS_OMNIBOX_PEDAL_CLEAR_BROWSING_DATA_HINT,
+          IDS_OMNIBOX_PEDAL_CLEAR_BROWSING_DATA_SUGGESTION_CONTENTS,
+          IDS_ACC_OMNIBOX_PEDAL_CLEAR_BROWSING_DATA_SUFFIX,
+          IDS_ACC_OMNIBOX_PEDAL_CLEAR_BROWSING_DATA),
+      GURL());
+  const auto is_concept_match = [&](OmniboxPedal::TokenSequence sequence) {
+    return test_pedal->IsConceptMatch(sequence);
+  };
+
+  test_pedal->AddVerbatimSequence(make_sequence({required_a, required_b}));
+
+  EXPECT_TRUE(is_concept_match(make_sequence({required_a, required_b})));
+  EXPECT_FALSE(
+      is_concept_match(make_sequence({required_a, required_b, nonsense})));
+  EXPECT_FALSE(is_concept_match(make_sequence({required_b, required_a})));
+}
diff --git a/components/omnibox/resources/omnibox_pedal_concepts.json b/components/omnibox/resources/omnibox_pedal_concepts.json
index a3a8bb6..2b06cd0b 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedals_translation_model",
   "schema_version": 3,
-  "time_generated": "2021-09-09T19:28:45.880Z",
+  "time_generated": "2021-09-22T19:12:06.162Z",
   "primary_language_code": "en",
   "pedal_definitions": [
     {
@@ -10556,12 +10556,12 @@
           "cover_cases": [],
           "enabled": true,
           "omnibox_ui_strings": {
-            "button_text": "Close Incognito windows",
+            "button_text": "Close all Incognito windows",
             "description_text": "Close all Incognito windows that are currently open.",
             "spoken_suggestion_description_suffix": "$1, Press tab then Enter to close all Incognito windows that are currently open.",
-            "spoken_button_focus_announcement": "Close Incognito windows button, Enter to close all Incognito windows that are currently open."
+            "spoken_button_focus_announcement": "Close Incognito windows button, press Enter to close all Incognito windows that are currently open."
           },
-          "date_modified_omnibox_ui_strings": "2021-09-09T00:42:07.559Z"
+          "date_modified_omnibox_ui_strings": "2021-09-22T19:11:13.609Z"
         },
         {
           "id": 27,
@@ -10586,12 +10586,12 @@
           "cover_cases": [],
           "enabled": true,
           "omnibox_ui_strings": {
-            "button_text": "Play Dino Game",
+            "button_text": "Play Chrome Dino game",
             "description_text": "Play the Dino Run game in Chrome",
             "spoken_suggestion_description_suffix": "$1, Press tab then Enter to play the Dino Run game in Chrome",
-            "spoken_button_focus_announcement": "Play Dino Run button, Enter to play the Dino Run game in Chrome"
+            "spoken_button_focus_announcement": "Play Dino Run button, press Enter to play the Dino Run game in Chrome"
           },
-          "date_modified_omnibox_ui_strings": "2021-09-09T00:42:07.559Z"
+          "date_modified_omnibox_ui_strings": "2021-09-22T19:11:13.609Z"
         },
         {
           "id": 28,
@@ -10630,7 +10630,7 @@
             "spoken_suggestion_description_suffix": "$1, Press Tab then Enter to Find your device in the Google Account",
             "spoken_button_focus_announcement": "Find my device button, press Enter to visit find your device in the Google Account"
           },
-          "date_modified_omnibox_ui_strings": "2021-09-09T00:42:07.559Z"
+          "date_modified_omnibox_ui_strings": "2021-09-22T19:11:13.609Z"
         },
         {
           "id": 29,
@@ -10658,12 +10658,12 @@
           "cover_cases": [],
           "enabled": true,
           "omnibox_ui_strings": {
-            "button_text": "Google Account privacy settings",
+            "button_text": "Manage Google Account privacy settings",
             "description_text": "Manage Google privacy settings in your Google Account",
             "spoken_suggestion_description_suffix": "$1, Press Tab then Enter to manage your Google Account privacy settings",
             "spoken_button_focus_announcement": "Manage Google Privacy settings button, press Enter to visit your Google Account privacy settings"
           },
-          "date_modified_omnibox_ui_strings": "2021-09-09T00:42:07.559Z"
+          "date_modified_omnibox_ui_strings": "2021-09-22T19:11:13.609Z"
         },
         {
           "id": 30,
@@ -10737,7 +10737,7 @@
             "spoken_suggestion_description_suffix": "$1, Press Tab then Enter to manage your Chrome settings",
             "spoken_button_focus_announcement": "Manage Chrome settings button, press Enter to visit your Chrome settings"
           },
-          "date_modified_omnibox_ui_strings": "2021-09-09T00:42:07.559Z"
+          "date_modified_omnibox_ui_strings": "2021-09-22T19:11:13.609Z"
         },
         {
           "id": 32,
@@ -10773,12 +10773,12 @@
           "cover_cases": [],
           "enabled": true,
           "omnibox_ui_strings": {
-            "button_text": "Manage downloads in Chrome",
+            "button_text": "Manage downloads",
             "description_text": "Manage files you have downloaded in Chrome",
             "spoken_suggestion_description_suffix": "$1, Press Tab then Enter to manage files you have downloaded in Chrome",
             "spoken_button_focus_announcement": "Manage downloads in Chrome button, press Enter to manage files you have downloaded in Chrome."
           },
-          "date_modified_omnibox_ui_strings": "2021-09-09T00:42:07.559Z"
+          "date_modified_omnibox_ui_strings": "2021-09-22T19:11:13.609Z"
         },
         {
           "id": 33,
@@ -10813,9 +10813,9 @@
             "button_text": "View your Chrome history",
             "description_text": "View and manage your browsing history in Chrome settings",
             "spoken_suggestion_description_suffix": "$1, Press tab then Enter to view your browsing history in Chrome",
-            "spoken_button_focus_announcement": "View your Chrome history button, Enter to view and manage your browsing history in Chrome settings"
+            "spoken_button_focus_announcement": "View your Chrome history button, press Enter to view and manage your browsing history in Chrome settings"
           },
-          "date_modified_omnibox_ui_strings": "2021-09-09T00:42:07.559Z"
+          "date_modified_omnibox_ui_strings": "2021-09-22T19:11:13.609Z"
         },
         {
           "id": 34,
@@ -10826,11 +10826,18 @@
               "synonyms": [
                 "share link with qr code",
                 "send link with qr code",
+                "share link via qr code",
+                "send link via qr code",
                 "share this page",
+                "cast this page",
+                "save this page",
+                "save page as",
+                "cast screen",
                 "share link",
                 "share page",
                 "send link",
                 "send page",
+                "cast page",
                 "qr code"
               ]
             }
@@ -10841,9 +10848,9 @@
             "button_text": "Share this page",
             "description_text": "Share this page by sharing the link, creating a QR code, casting, and more.",
             "spoken_suggestion_description_suffix": "$1, Press tab then Enter to share this page, with options to share the link, create a QR code, cast, and more.",
-            "spoken_button_focus_announcement": "Share this page button, Enter to share this page with options to share the link, create a QR code, cast, and more."
+            "spoken_button_focus_announcement": "Share this page button, press Enter to share this page with options to share the link, create a QR code, cast, and more."
           },
-          "date_modified_omnibox_ui_strings": "2021-09-09T00:42:07.559Z"
+          "date_modified_omnibox_ui_strings": "2021-09-22T19:11:13.609Z"
         },
         {
           "id": 35,
@@ -10883,9 +10890,9 @@
             "button_text": "Manage accessibility settings",
             "description_text": "Personalize your accessibility tools in Chrome settings",
             "spoken_suggestion_description_suffix": "$1, Press tab then Enter to personalize your accessibility tools in Chrome settings.",
-            "spoken_button_focus_announcement": "Manage accessibility settings button, Enter to personalize your accessibility tools in Chrome settings."
+            "spoken_button_focus_announcement": "Manage accessibility settings button, press Enter to personalize your accessibility tools in Chrome settings."
           },
-          "date_modified_omnibox_ui_strings": "2021-09-09T00:42:07.559Z"
+          "date_modified_omnibox_ui_strings": "2021-09-22T19:11:13.609Z"
         },
         {
           "id": 36,
@@ -10930,12 +10937,12 @@
           ],
           "enabled": true,
           "omnibox_ui_strings": {
-            "button_text": "Customize fonts in Chrome",
+            "button_text": "Customize fonts",
             "description_text": "Customize font sizes and typefaces in Chrome",
             "spoken_suggestion_description_suffix": "$1, Press tab then Enter to customize font sizes and typefaces in Chrome",
-            "spoken_button_focus_announcement": "Customize fonts in Chrome button, Enter to customize font sizes and typefaces in Chrome"
+            "spoken_button_focus_announcement": "Customize fonts in Chrome button, press Enter to customize font sizes and typefaces in Chrome"
           },
-          "date_modified_omnibox_ui_strings": "2021-09-09T00:42:07.559Z"
+          "date_modified_omnibox_ui_strings": "2021-09-22T19:11:13.609Z"
         },
         {
           "id": 37,
@@ -10968,12 +10975,12 @@
           "cover_cases": [],
           "enabled": true,
           "omnibox_ui_strings": {
-            "button_text": "Manage Chrome appearance",
+            "button_text": "Customize appearance",
             "description_text": "Customize the look of your browser",
             "spoken_suggestion_description_suffix": "$1, Press tab then Enter to customize the look of your browser.",
-            "spoken_button_focus_announcement": "Manage Chrome appearance button, Enter to customize the look of your browser with themes."
+            "spoken_button_focus_announcement": "Manage Chrome appearance button, press Enter to customize the look of your browser with themes."
           },
-          "date_modified_omnibox_ui_strings": "2021-09-09T00:42:07.559Z"
+          "date_modified_omnibox_ui_strings": "2021-09-22T19:11:13.609Z"
         },
         {
           "id": 38,
@@ -10987,7 +10994,8 @@
                 "manage",
                 "change",
                 "modify",
-                "edit"
+                "edit",
+                "add"
               ]
             },
             {
@@ -10997,22 +11005,35 @@
                 "custom search engines",
                 "site search engines",
                 "customized search",
+                "search engines",
                 "tab to search",
                 "scoped search",
                 "custom search",
                 "site search"
               ]
+            },
+            {
+              "required": false,
+              "single": true,
+              "synonyms": [
+                "google chrome",
+                "browser",
+                "chrome"
+              ]
             }
           ],
-          "cover_cases": [],
+          "cover_cases": [
+            "add custom search",
+            "manage search engines"
+          ],
           "enabled": true,
           "omnibox_ui_strings": {
             "button_text": "Manage site search",
             "description_text": "Manage site search and your default search engine",
             "spoken_suggestion_description_suffix": "$1, Press tab then Enter to manage site search and your default search engine",
-            "spoken_button_focus_announcement": "Manage site search button, Enter to manage site search and your default search engine"
+            "spoken_button_focus_announcement": "Manage site search button, press Enter to manage site search and your default search engine"
           },
-          "date_modified_omnibox_ui_strings": "2021-09-09T00:42:07.559Z"
+          "date_modified_omnibox_ui_strings": "2021-09-22T19:11:13.609Z"
         },
         {
           "id": 39,
@@ -11056,7 +11077,7 @@
             "spoken_suggestion_description_suffix": "$1, Press tab then Enter to personalize your accessibility tools in Chrome OS settings.",
             "spoken_button_focus_announcement": "Manage accessibility settings button, Enter to personalize your accessibility tools in Chrome OS settings"
           },
-          "date_modified_omnibox_ui_strings": "2021-09-09T00:42:07.559Z"
+          "date_modified_omnibox_ui_strings": "2021-09-22T19:11:13.609Z"
         }
       ],
       "tokenize_each_character": false
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_am.json b/components/omnibox/resources/omnibox_pedal_concepts_am.json
index ffbac78..39f6c19d 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_am.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_am.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "chrome",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_ar.json b/components/omnibox/resources/omnibox_pedal_concepts_ar.json
index 9c1b5c22..64e79dc8 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_ar.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_ar.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "a",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_bg.json b/components/omnibox/resources/omnibox_pedal_concepts_bg.json
index 0cd86a5..fc28e68c 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_bg.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_bg.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "chrome",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_bn.json b/components/omnibox/resources/omnibox_pedal_concepts_bn.json
index 1148bcd..7bb75489 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_bn.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_bn.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "chrome",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_ca.json b/components/omnibox/resources/omnibox_pedal_concepts_ca.json
index 3a9c304..264851e 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_ca.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_ca.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "a",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_cs.json b/components/omnibox/resources/omnibox_pedal_concepts_cs.json
index d1f8f3d8..f5cbd85 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_cs.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_cs.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "aktualizovat",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_da.json b/components/omnibox/resources/omnibox_pedal_concepts_da.json
index f783f45a..c2f01e0 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_da.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_da.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "adgangskode",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_de.json b/components/omnibox/resources/omnibox_pedal_concepts_de.json
index c28f5b98..1b5003a7 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_de.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_de.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "aktualisieren",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_el.json b/components/omnibox/resources/omnibox_pedal_concepts_el.json
index c1aedd2..4bd7d3c 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_el.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_el.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "chrome",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_en-GB.json b/components/omnibox/resources/omnibox_pedal_concepts_en-GB.json
index f0994b1..989e0fa 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_en-GB.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_en-GB.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "a",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_en.json b/components/omnibox/resources/omnibox_pedal_concepts_en.json
index 247c1d2..b11ef4c 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_en.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_en.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "a",
@@ -18,6 +18,7 @@
     "alter",
     "an",
     "appearance",
+    "as",
     "assistive",
     "backgrounds",
     "block",
@@ -31,6 +32,7 @@
     "captions",
     "card",
     "cards",
+    "cast",
     "center",
     "certificates",
     "change",
@@ -156,6 +158,7 @@
     "save",
     "schedule",
     "scoped",
+    "screen",
     "search",
     "secure",
     "securely",
@@ -201,6 +204,7 @@
     "upgrade",
     "url",
     "use",
+    "via",
     "view",
     "vision",
     "visit",
@@ -226,62 +230,62 @@
           "single": true,
           "synonyms": [
             [
-              83,
-              33
-            ],
-            [
-              19
-            ],
-            [
-              18
-            ],
-            [
-              33
-            ]
-          ]
-        },
-        {
-          "required": true,
-          "single": true,
-          "synonyms": [
-            [
-              52
-            ],
-            [
-              142
-            ],
-            [
-              34
-            ],
-            [
-              69
-            ],
-            [
-              205
-            ]
-          ]
-        },
-        {
-          "required": true,
-          "single": true,
-          "synonyms": [
-            [
-              93
-            ],
-            [
-              43
-            ],
-            [
-              86
+              85,
+              35
             ],
             [
               20
             ],
             [
-              50
+              19
             ],
             [
-              92
+              35
+            ]
+          ]
+        },
+        {
+          "required": true,
+          "single": true,
+          "synonyms": [
+            [
+              54
+            ],
+            [
+              144
+            ],
+            [
+              36
+            ],
+            [
+              71
+            ],
+            [
+              209
+            ]
+          ]
+        },
+        {
+          "required": true,
+          "single": true,
+          "synonyms": [
+            [
+              95
+            ],
+            [
+              45
+            ],
+            [
+              88
+            ],
+            [
+              21
+            ],
+            [
+              52
+            ],
+            [
+              94
             ]
           ]
         }
@@ -297,14 +301,14 @@
           "single": true,
           "synonyms": [
             [
-              83,
-              33
+              85,
+              35
             ],
             [
-              18
+              19
             ],
             [
-              33
+              35
             ]
           ]
         },
@@ -313,28 +317,28 @@
           "single": true,
           "synonyms": [
             [
-              109
+              111
             ],
             [
-              29
+              31
             ],
             [
-              108
+              110
             ],
             [
-              192
+              195
             ],
             [
-              63
+              65
             ],
             [
-              149
+              151
             ],
             [
-              163
+              166
             ],
             [
-              197
+              201
             ]
           ]
         },
@@ -343,13 +347,13 @@
           "single": true,
           "synonyms": [
             [
-              45
+              47
             ],
             [
-              128
+              130
             ],
             [
-              127
+              129
             ]
           ]
         }
@@ -365,14 +369,14 @@
           "single": true,
           "synonyms": [
             [
-              83,
-              33
+              85,
+              35
             ],
             [
-              18
+              19
             ],
             [
-              33
+              35
             ]
           ]
         },
@@ -381,19 +385,19 @@
           "single": true,
           "synonyms": [
             [
-              29
+              31
             ],
             [
-              108
+              110
             ],
             [
-              192
+              195
             ],
             [
-              63
+              65
             ],
             [
-              149
+              151
             ]
           ]
         },
@@ -402,43 +406,43 @@
           "single": true,
           "synonyms": [
             [
-              46,
-              25,
-              93
+              48,
+              26,
+              95
             ],
             [
-              46,
-              25,
-              92
+              48,
+              26,
+              94
             ],
             [
-              25,
-              93
+              26,
+              95
             ],
             [
-              129,
-              113
+              131,
+              115
             ],
             [
-              46,
+              48,
+              27
+            ],
+            [
+              48,
               26
             ],
             [
-              46,
-              25
+              26,
+              94
             ],
             [
-              25,
-              92
+              132
             ],
             [
-              130
+              131
             ],
             [
-              129
-            ],
-            [
-              26
+              27
             ]
           ]
         }
@@ -454,14 +458,14 @@
           "single": true,
           "synonyms": [
             [
-              83,
-              33
+              85,
+              35
             ],
             [
-              18
+              19
             ],
             [
-              33
+              35
             ]
           ]
         },
@@ -470,19 +474,19 @@
           "single": true,
           "synonyms": [
             [
-              44
+              46
             ],
             [
-              101
+              103
             ],
             [
-              68
+              70
             ],
             [
-              172
+              175
             ],
             [
-              124
+              126
             ]
           ]
         },
@@ -491,31 +495,31 @@
           "single": true,
           "synonyms": [
             [
-              91,
-              204
+              93,
+              208
             ],
             [
-              91,
-              114
+              93,
+              116
             ],
             [
-              138,
-              204
+              140,
+              208
             ],
             [
-              91,
-              177
+              93,
+              180
             ],
             [
-              138,
-              114
+              140,
+              116
             ],
             [
-              138,
-              177
+              140,
+              180
             ],
             [
-              91
+              93
             ]
           ]
         }
@@ -531,14 +535,14 @@
           "single": true,
           "synonyms": [
             [
-              83,
-              33
+              85,
+              35
             ],
             [
-              18
+              19
             ],
             [
-              33
+              35
             ]
           ]
         },
@@ -547,11 +551,11 @@
           "single": true,
           "synonyms": [
             [
-              29,
-              100
+              31,
+              102
             ],
             [
-              188
+              191
             ]
           ]
         },
@@ -560,21 +564,21 @@
           "single": true,
           "synonyms": [
             [
-              184,
-              125
+              187,
+              127
             ],
             [
-              200,
-              125
+              204,
+              127
             ],
             [
-              201
+              205
             ],
             [
-              125
+              127
             ],
             [
-              184
+              187
             ]
           ]
         }
@@ -590,14 +594,14 @@
           "single": true,
           "synonyms": [
             [
-              83,
-              33
+              85,
+              35
             ],
             [
-              18
+              19
             ],
             [
-              33
+              35
             ]
           ]
         },
@@ -606,16 +610,16 @@
           "single": true,
           "synonyms": [
             [
-              95
+              97
             ],
             [
-              193
+              196
             ],
             [
-              194
+              197
             ],
             [
-              192
+              195
             ]
           ]
         }
@@ -634,13 +638,13 @@
               3
             ],
             [
-              131
+              133
             ],
             [
-              146
+              148
             ],
             [
-              196
+              199
             ]
           ]
         },
@@ -649,17 +653,17 @@
           "single": true,
           "synonyms": [
             [
-              83,
-              33
+              85,
+              35
             ],
             [
-              18
+              19
             ],
             [
-              33
+              35
             ],
             [
-              83
+              85
             ]
           ]
         },
@@ -668,13 +672,13 @@
           "single": true,
           "synonyms": [
             [
+              34
+            ],
+            [
+              33
+            ],
+            [
               32
-            ],
-            [
-              31
-            ],
-            [
-              30
             ]
           ]
         },
@@ -683,16 +687,16 @@
           "single": true,
           "synonyms": [
             [
-              128
+              130
             ],
             [
-              155
+              158
             ],
             [
-              127
+              129
             ],
             [
-              148
+              150
             ]
           ]
         }
@@ -713,29 +717,29 @@
           "single": false,
           "synonyms": [
             [
-              83,
-              33
+              85,
+              35
+            ],
+            [
+              20
             ],
             [
               19
             ],
             [
+              35
+            ],
+            [
+              85
+            ],
+            [
               18
             ],
             [
-              33
+              31
             ],
             [
-              83
-            ],
-            [
-              17
-            ],
-            [
-              29
-            ],
-            [
-              108
+              110
             ]
           ]
         },
@@ -744,33 +748,33 @@
           "single": true,
           "synonyms": [
             [
-              67,
-              139
+              69,
+              141
             ],
             [
-              171,
-              139
+              174,
+              141
             ],
             [
-              155,
-              158
+              158,
+              161
             ],
             [
-              155,
-              99
+              158,
+              101
             ],
             [
-              153,
-              58
+              156,
+              60
             ],
             [
-              28
+              30
             ],
             [
-              154
+              157
             ],
             [
-              147
+              149
             ]
           ]
         },
@@ -782,7 +786,7 @@
               11
             ],
             [
-              196
+              199
             ]
           ]
         }
@@ -803,15 +807,15 @@
           "single": true,
           "synonyms": [
             [
-              119,
-              187
+              121,
+              190
             ],
             [
-              42,
-              158
+              44,
+              161
             ],
             [
-              43
+              45
             ]
           ]
         },
@@ -820,29 +824,29 @@
           "single": false,
           "synonyms": [
             [
-              83,
-              33
+              85,
+              35
             ],
             [
-              57
+              59
             ],
             [
-              18
+              19
             ],
             [
-              40
+              42
             ],
             [
-              83
+              85
             ],
             [
-              33
+              35
             ],
             [
-              108
+              110
             ],
             [
-              16
+              17
             ],
             [
               10
@@ -851,7 +855,7 @@
               11
             ],
             [
-              196
+              199
             ]
           ]
         },
@@ -860,8 +864,8 @@
           "single": false,
           "synonyms": [
             [
-              183,
-              126
+              186,
+              128
             ],
             [
               9
@@ -885,25 +889,25 @@
           "single": true,
           "synonyms": [
             [
-              40
+              42
             ],
             [
-              108
+              110
             ],
             [
               8
             ],
             [
-              52
+              54
             ],
             [
-              29
+              31
             ],
             [
-              173
+              176
             ],
             [
-              63
+              65
             ],
             [
               5
@@ -915,15 +919,15 @@
           "single": true,
           "synonyms": [
             [
-              162,
+              165,
               7
             ],
             [
-              162,
+              165,
               6
             ],
             [
-              118,
+              120,
               6
             ],
             [
@@ -939,17 +943,17 @@
           "single": true,
           "synonyms": [
             [
-              83,
-              33
+              85,
+              35
             ],
             [
-              18
+              19
             ],
             [
-              33
+              35
             ],
             [
-              83
+              85
             ]
           ]
         }
@@ -970,11 +974,11 @@
           "single": true,
           "synonyms": [
             [
-              176,
-              158
+              179,
+              161
             ],
             [
-              176
+              179
             ]
           ]
         },
@@ -983,38 +987,38 @@
           "single": false,
           "synonyms": [
             [
-              83,
-              33
+              85,
+              35
             ],
             [
-              48
+              50
             ],
             [
-              18
+              19
             ],
             [
-              40
+              42
             ],
             [
-              56
+              58
             ],
             [
-              33
+              35
             ],
             [
-              83
+              85
             ],
             [
-              108
+              110
             ],
             [
               8
             ],
             [
-              29
+              31
             ],
             [
-              63
+              65
             ],
             [
               5
@@ -1038,15 +1042,15 @@
           "single": true,
           "synonyms": [
             [
-              164,
-              132
+              167,
+              134
             ],
             [
-              164,
-              158
+              167,
+              161
             ],
             [
-              132
+              134
             ]
           ]
         },
@@ -1055,35 +1059,35 @@
           "single": false,
           "synonyms": [
             [
-              83,
-              33
+              85,
+              35
             ],
             [
-              48
+              50
             ],
             [
-              18
+              19
             ],
             [
-              40
+              42
             ],
             [
-              33
+              35
             ],
             [
-              83
+              85
             ],
             [
-              108
+              110
             ],
             [
               8
             ],
             [
-              29
+              31
             ],
             [
-              63
+              65
             ]
           ]
         }
@@ -1104,31 +1108,31 @@
           "single": true,
           "synonyms": [
             [
-              83,
-              208
+              85,
+              212
             ],
             [
-              83,
-              33
+              85,
+              35
             ],
             [
-              80,
-              174
+              82,
+              177
             ],
             [
-              208
+              212
             ],
             [
-              18
+              19
             ],
             [
-              83
+              85
             ],
             [
-              33
+              35
             ],
             [
-              84
+              86
             ]
           ]
         },
@@ -1137,19 +1141,19 @@
           "single": false,
           "synonyms": [
             [
-              44
+              46
             ],
             [
-              172
+              175
             ],
             [
-              124
+              126
             ],
             [
-              107
+              109
             ],
             [
-              118
+              120
             ]
           ]
         },
@@ -1158,10 +1162,10 @@
           "single": true,
           "synonyms": [
             [
-              61
+              63
             ],
             [
-              60
+              62
             ]
           ]
         }
@@ -1182,19 +1186,19 @@
           "single": false,
           "synonyms": [
             [
-              44
+              46
             ],
             [
-              172
+              175
             ],
             [
-              124
+              126
             ],
             [
-              107
+              109
             ],
             [
-              118
+              120
             ]
           ]
         },
@@ -1203,28 +1207,28 @@
           "single": true,
           "synonyms": [
             [
-              83,
-              208
+              85,
+              212
             ],
             [
-              83,
-              33
+              85,
+              35
             ],
             [
-              80,
-              174
+              82,
+              177
             ],
             [
-              208
+              212
             ],
             [
-              18
+              19
             ],
             [
-              83
+              85
             ],
             [
-              33
+              35
             ]
           ]
         },
@@ -1233,16 +1237,16 @@
           "single": true,
           "synonyms": [
             [
-              170
+              173
             ],
             [
-              161
+              164
             ],
             [
-              160
+              163
             ],
             [
-              189
+              192
             ]
           ]
         }
@@ -1263,19 +1267,19 @@
           "single": true,
           "synonyms": [
             [
-              44
+              46
             ],
             [
-              172
+              175
             ],
             [
-              124
+              126
             ],
             [
-              107
+              109
             ],
             [
-              118
+              120
             ]
           ]
         },
@@ -1284,19 +1288,19 @@
           "single": true,
           "synonyms": [
             [
-              135
+              137
             ],
             [
-              169
+              172
             ],
             [
-              168
+              171
             ],
             [
-              136
+              138
             ],
             [
-              51
+              53
             ]
           ]
         },
@@ -1305,20 +1309,20 @@
           "single": false,
           "synonyms": [
             [
-              80,
-              174
+              82,
+              177
             ],
             [
-              208
+              212
             ],
             [
-              18
+              19
             ],
             [
-              83
+              85
             ],
             [
-              33
+              35
             ]
           ]
         }
@@ -1339,22 +1343,22 @@
           "single": false,
           "synonyms": [
             [
-              150
+              152
             ],
             [
-              44
+              46
             ],
             [
-              172
+              175
             ],
             [
-              124
+              126
             ],
             [
-              107
+              109
             ],
             [
-              118
+              120
             ],
             [
               5
@@ -1366,26 +1370,26 @@
           "single": false,
           "synonyms": [
             [
-              80,
-              174
+              82,
+              177
             ],
             [
-              208
+              212
+            ],
+            [
+              23
+            ],
+            [
+              19
+            ],
+            [
+              85
+            ],
+            [
+              35
             ],
             [
               22
-            ],
-            [
-              18
-            ],
-            [
-              83
-            ],
-            [
-              33
-            ],
-            [
-              21
             ]
           ]
         },
@@ -1394,13 +1398,13 @@
           "single": true,
           "synonyms": [
             [
-              111
+              113
             ],
             [
-              96
+              98
             ],
             [
-              70
+              72
             ]
           ]
         }
@@ -1421,19 +1425,19 @@
           "single": false,
           "synonyms": [
             [
-              44
+              46
             ],
             [
-              172
+              175
             ],
             [
-              124
+              126
             ],
             [
-              107
+              109
             ],
             [
-              118
+              120
             ]
           ]
         },
@@ -1442,20 +1446,20 @@
           "single": false,
           "synonyms": [
             [
-              80,
-              174
+              82,
+              177
             ],
             [
-              208
+              212
             ],
             [
-              18
+              19
             ],
             [
-              83
+              85
             ],
             [
-              33
+              35
             ]
           ]
         },
@@ -1464,10 +1468,10 @@
           "single": true,
           "synonyms": [
             [
-              202
+              206
             ],
             [
-              164
+              167
             ]
           ]
         }
@@ -1488,19 +1492,19 @@
           "single": false,
           "synonyms": [
             [
-              44
+              46
             ],
             [
-              172
+              175
             ],
             [
-              124
+              126
             ],
             [
-              107
+              109
             ],
             [
-              118
+              120
             ]
           ]
         },
@@ -1509,23 +1513,23 @@
           "single": false,
           "synonyms": [
             [
-              80,
-              174
+              82,
+              177
             ],
             [
-              208
+              212
             ],
             [
-              18
+              19
             ],
             [
-              83
+              85
             ],
             [
-              33
+              35
             ],
             [
-              98
+              100
             ]
           ]
         },
@@ -1534,10 +1538,10 @@
           "single": true,
           "synonyms": [
             [
-              121
+              123
             ],
             [
-              120
+              122
             ]
           ]
         }
@@ -1558,19 +1562,19 @@
           "single": false,
           "synonyms": [
             [
-              44
+              46
             ],
             [
-              172
+              175
             ],
             [
-              124
+              126
             ],
             [
-              107
+              109
             ],
             [
-              118
+              120
             ]
           ]
         },
@@ -1579,20 +1583,20 @@
           "single": false,
           "synonyms": [
             [
-              80,
-              174
+              82,
+              177
             ],
             [
-              208
+              212
             ],
             [
-              18
+              19
             ],
             [
-              33
+              35
             ],
             [
-              83
+              85
             ]
           ]
         },
@@ -1601,16 +1605,16 @@
           "single": true,
           "synonyms": [
             [
-              175
+              178
             ],
             [
-              79
+              81
             ],
             [
-              78
+              80
             ],
             [
-              141
+              143
             ]
           ]
         }
@@ -1631,24 +1635,24 @@
           "single": true,
           "synonyms": [
             [
-              107,
-              116,
-              122
+              109,
+              118,
+              124
             ],
             [
-              191
+              194
             ],
             [
-              71
+              73
             ],
             [
-              102
+              104
             ],
             [
-              199
+              203
             ],
             [
-              156
+              159
             ]
           ]
         },
@@ -1657,10 +1661,10 @@
           "single": false,
           "synonyms": [
             [
-              18
+              19
             ],
             [
-              83
+              85
             ]
           ]
         },
@@ -1669,22 +1673,22 @@
           "single": true,
           "synonyms": [
             [
-              118,
-              33,
-              72
+              120,
+              35,
+              74
             ],
             [
-              33,
-              185,
-              27
+              35,
+              188,
+              29
             ],
             [
-              33,
-              72
+              35,
+              74
             ],
             [
-              33,
-              185
+              35,
+              188
             ]
           ]
         }
@@ -1705,7 +1709,7 @@
           "single": true,
           "synonyms": [
             [
-              83,
+              85,
               2
             ]
           ]
@@ -1715,10 +1719,10 @@
           "single": false,
           "synonyms": [
             [
-              18
+              19
             ],
             [
-              33
+              35
             ]
           ]
         },
@@ -1727,16 +1731,16 @@
           "single": true,
           "synonyms": [
             [
-              40
+              42
             ],
             [
-              108
+              110
             ],
             [
               8
             ],
             [
-              74
+              76
             ]
           ]
         }
@@ -1757,22 +1761,22 @@
           "single": true,
           "synonyms": [
             [
-              83,
+              85,
               2,
-              127
+              129
             ],
             [
-              82,
+              84,
               2,
-              127
+              129
             ],
             [
-              83,
-              127
+              85,
+              129
             ],
             [
-              82,
-              127
+              84,
+              129
             ]
           ]
         },
@@ -1781,13 +1785,13 @@
           "single": false,
           "synonyms": [
             [
-              18
+              19
             ],
             [
-              33
+              35
             ],
             [
-              83
+              85
             ]
           ]
         },
@@ -1796,16 +1800,16 @@
           "single": true,
           "synonyms": [
             [
-              29
+              31
             ],
             [
-              192
+              195
             ],
             [
-              143
+              145
             ],
             [
-              74
+              76
             ]
           ]
         }
@@ -1826,16 +1830,16 @@
           "single": true,
           "synonyms": [
             [
-              52
+              54
             ],
             [
-              35
+              37
             ],
             [
-              34
+              36
             ],
             [
-              65
+              67
             ]
           ]
         },
@@ -1844,24 +1848,24 @@
           "single": true,
           "synonyms": [
             [
-              91,
-              204
+              93,
+              208
             ],
             [
-              91,
-              114
+              93,
+              116
             ],
             [
-              91
+              93
             ]
           ]
         }
       ],
       "omnibox_ui_strings": {
-        "button_text": "Close Incognito windows",
+        "button_text": "Close all Incognito windows",
         "description_text": "Close all Incognito windows that are currently open.",
         "spoken_suggestion_description_suffix": "$1, Press tab then Enter to close all Incognito windows that are currently open.",
-        "spoken_button_focus_announcement": "Close Incognito windows button, Enter to close all Incognito windows that are currently open."
+        "spoken_button_focus_announcement": "Close Incognito windows button, press Enter to close all Incognito windows that are currently open."
       },
       "url": "batch3"
     },
@@ -1873,60 +1877,60 @@
           "single": true,
           "synonyms": [
             [
-              134,
-              33,
-              54,
-              81
+              136,
+              35,
+              56,
+              83
             ],
             [
-              134,
-              33,
-              55
+              136,
+              35,
+              57
             ],
             [
-              134,
-              33,
-              54
+              136,
+              35,
+              56
             ],
             [
-              33,
-              54,
-              81
+              35,
+              56,
+              83
             ],
             [
-              134,
-              54,
-              81
+              136,
+              56,
+              83
             ],
             [
-              134,
-              54,
-              146
+              136,
+              56,
+              148
             ],
             [
-              33,
-              55
+              35,
+              57
             ],
             [
-              33,
-              54
+              35,
+              56
             ],
             [
-              54,
-              81
+              56,
+              83
             ],
             [
-              54,
-              146
+              56,
+              148
             ]
           ]
         }
       ],
       "omnibox_ui_strings": {
-        "button_text": "Play Dino Game",
+        "button_text": "Play Chrome Dino game",
         "description_text": "Play the Dino Run game in Chrome",
         "spoken_suggestion_description_suffix": "$1, Press tab then Enter to play the Dino Run game in Chrome",
-        "spoken_button_focus_announcement": "Play Dino Run button, Enter to play the Dino Run game in Chrome"
+        "spoken_button_focus_announcement": "Play Dino Run button, press Enter to play the Dino Run game in Chrome"
       },
       "url": "chrome://dino"
     },
@@ -1938,39 +1942,39 @@
           "single": true,
           "synonyms": [
             [
-              85,
-              110,
-              104
+              87,
+              112,
+              106
             ],
             [
-              85,
-              110,
-              73
+              87,
+              112,
+              75
             ],
             [
-              85,
-              73
+              87,
+              75
             ],
             [
-              85,
-              104
+              87,
+              106
             ],
             [
-              85,
-              73
+              87,
+              75
             ],
             [
-              203,
-              97
+              207,
+              99
             ],
             [
-              89
+              91
             ],
             [
-              104
+              106
             ],
             [
-              73
+              75
             ]
           ]
         },
@@ -1979,18 +1983,18 @@
           "single": true,
           "synonyms": [
             [
-              105,
-              53
+              107,
+              55
             ],
             [
-              105,
-              133
+              107,
+              135
             ],
             [
-              53
+              55
             ],
             [
-              133
+              135
             ]
           ]
         }
@@ -2011,77 +2015,77 @@
           "single": true,
           "synonyms": [
             [
-              108,
-              83,
-              137,
-              158
+              110,
+              85,
+              139,
+              161
             ],
             [
-              29,
-              83,
-              137,
-              158
+              31,
+              85,
+              139,
+              161
             ],
             [
-              63,
-              83,
-              137,
-              158
+              65,
+              85,
+              139,
+              161
             ],
             [
-              29,
-              137,
-              83
+              31,
+              139,
+              85
             ],
             [
-              63,
-              137,
-              83
+              65,
+              139,
+              85
             ],
             [
-              83,
-              137,
-              158
+              85,
+              139,
+              161
             ],
             [
-              83,
-              137,
-              41
+              85,
+              139,
+              43
             ],
             [
-              83,
+              85,
               2,
-              137
+              139
             ],
             [
-              83,
-              137,
-              32
+              85,
+              139,
+              34
             ],
             [
-              108,
-              83,
-              137
+              110,
+              85,
+              139
             ],
             [
-              29,
-              83,
-              137
+              31,
+              85,
+              139
             ],
             [
-              63,
-              83,
-              137
+              65,
+              85,
+              139
             ],
             [
-              83,
-              137
+              85,
+              139
             ]
           ]
         }
       ],
       "omnibox_ui_strings": {
-        "button_text": "Google Account privacy settings",
+        "button_text": "Manage Google Account privacy settings",
         "description_text": "Manage Google privacy settings in your Google Account",
         "spoken_suggestion_description_suffix": "$1, Press Tab then Enter to manage your Google Account privacy settings",
         "spoken_button_focus_announcement": "Manage Google Privacy settings button, press Enter to visit your Google Account privacy settings"
@@ -2096,28 +2100,28 @@
           "single": true,
           "synonyms": [
             [
-              40
+              42
             ],
             [
-              145
+              147
             ],
             [
-              29
+              31
             ],
             [
-              115
+              117
             ],
             [
-              108
+              110
             ],
             [
-              144
+              146
             ],
             [
               11
             ],
             [
-              63
+              65
             ]
           ]
         },
@@ -2126,25 +2130,25 @@
           "single": true,
           "synonyms": [
             [
-              33,
-              18,
-              158
+              35,
+              19,
+              161
             ],
             [
-              83,
-              33,
-              158
+              85,
+              35,
+              161
             ],
             [
-              18,
-              158
+              19,
+              161
             ],
             [
-              33,
-              158
+              35,
+              161
             ],
             [
-              158
+              161
             ]
           ]
         }
@@ -2165,34 +2169,34 @@
           "single": true,
           "synonyms": [
             [
-              40
+              42
             ],
             [
-              145
+              147
             ],
             [
-              29
+              31
             ],
             [
-              115
+              117
             ],
             [
-              108
+              110
             ],
             [
-              144
+              146
             ],
             [
               11
             ],
             [
-              63
+              65
             ],
             [
-              197
+              201
             ],
             [
-              156
+              159
             ]
           ]
         },
@@ -2201,31 +2205,31 @@
           "single": true,
           "synonyms": [
             [
-              33,
-              18,
-              62
+              35,
+              19,
+              64
             ],
             [
-              83,
-              33,
-              62
+              85,
+              35,
+              64
             ],
             [
-              18,
-              62
+              19,
+              64
             ],
             [
-              33,
-              62
+              35,
+              64
             ],
             [
-              62
+              64
             ]
           ]
         }
       ],
       "omnibox_ui_strings": {
-        "button_text": "Manage downloads in Chrome",
+        "button_text": "Manage downloads",
         "description_text": "Manage files you have downloaded in Chrome",
         "spoken_suggestion_description_suffix": "$1, Press Tab then Enter to manage files you have downloaded in Chrome",
         "spoken_button_focus_announcement": "Manage downloads in Chrome button, press Enter to manage files you have downloaded in Chrome."
@@ -2240,19 +2244,19 @@
           "single": true,
           "synonyms": [
             [
-              145
+              147
             ],
             [
-              199
+              203
             ],
             [
-              73
+              75
             ],
             [
-              197
+              201
             ],
             [
-              156
+              159
             ]
           ]
         },
@@ -2261,31 +2265,31 @@
           "single": true,
           "synonyms": [
             [
-              83,
-              33,
-              19,
-              86
+              85,
+              35,
+              20,
+              88
             ],
             [
-              83,
-              33,
-              86
+              85,
+              35,
+              88
+            ],
+            [
+              20,
+              88
             ],
             [
               19,
-              86
+              88
             ],
             [
-              18,
-              86
+              35,
+              88
             ],
             [
-              33,
-              86
-            ],
-            [
-              195,
-              86
+              198,
+              88
             ]
           ]
         }
@@ -2294,7 +2298,7 @@
         "button_text": "View your Chrome history",
         "description_text": "View and manage your browsing history in Chrome settings",
         "spoken_suggestion_description_suffix": "$1, Press tab then Enter to view your browsing history in Chrome",
-        "spoken_button_focus_announcement": "View your Chrome history button, Enter to view and manage your browsing history in Chrome settings"
+        "spoken_button_focus_announcement": "View your Chrome history button, press Enter to view and manage your browsing history in Chrome settings"
       },
       "url": "chrome://history"
     },
@@ -2306,43 +2310,80 @@
           "single": true,
           "synonyms": [
             [
-              159,
-              103,
-              206,
-              140,
-              36
+              162,
+              105,
+              210,
+              142,
+              38
             ],
             [
-              157,
-              103,
-              206,
-              140,
-              36
+              160,
+              105,
+              210,
+              142,
+              38
             ],
             [
-              159,
-              184,
-              125
+              162,
+              105,
+              200,
+              142,
+              38
             ],
             [
-              159,
-              103
+              160,
+              105,
+              200,
+              142,
+              38
             ],
             [
-              159,
-              125
+              162,
+              187,
+              127
             ],
             [
-              157,
-              103
+              28,
+              187,
+              127
             ],
             [
-              157,
-              125
+              151,
+              187,
+              127
             ],
             [
-              140,
-              36
+              151,
+              127,
+              14
+            ],
+            [
+              28,
+              154
+            ],
+            [
+              162,
+              105
+            ],
+            [
+              162,
+              127
+            ],
+            [
+              160,
+              105
+            ],
+            [
+              160,
+              127
+            ],
+            [
+              28,
+              127
+            ],
+            [
+              142,
+              38
             ]
           ]
         }
@@ -2351,7 +2392,7 @@
         "button_text": "Share this page",
         "description_text": "Share this page by sharing the link, creating a QR code, casting, and more.",
         "spoken_suggestion_description_suffix": "$1, Press tab then Enter to share this page, with options to share the link, create a QR code, cast, and more.",
-        "spoken_button_focus_announcement": "Share this page button, Enter to share this page with options to share the link, create a QR code, cast, and more."
+        "spoken_button_focus_announcement": "Share this page button, press Enter to share this page with options to share the link, create a QR code, cast, and more."
       },
       "url": ""
     },
@@ -2363,22 +2404,22 @@
           "single": true,
           "synonyms": [
             [
-              48
+              50
             ],
             [
-              40
+              42
             ],
             [
-              108
+              110
             ],
             [
-              199
+              203
             ],
             [
-              197
+              201
             ],
             [
-              63
+              65
             ]
           ]
         },
@@ -2387,44 +2428,44 @@
           "single": true,
           "synonyms": [
             [
-              106,
-              198,
-              158
+              108,
+              202,
+              161
             ],
             [
-              106,
-              198,
-              72
+              108,
+              202,
+              74
             ],
             [
               1,
-              158
+              161
             ],
             [
               1,
-              72
+              74
             ],
             [
-              14,
-              179
+              15,
+              182
             ],
             [
-              33,
+              35,
               1
             ],
             [
-              23,
-              158
+              24,
+              161
             ],
             [
-              14,
-              178
+              15,
+              181
             ],
             [
               1
             ],
             [
-              24
+              25
             ]
           ]
         }
@@ -2433,7 +2474,7 @@
         "button_text": "Manage accessibility settings",
         "description_text": "Personalize your accessibility tools in Chrome settings",
         "spoken_suggestion_description_suffix": "$1, Press tab then Enter to personalize your accessibility tools in Chrome settings.",
-        "spoken_button_focus_announcement": "Manage accessibility settings button, Enter to personalize your accessibility tools in Chrome settings."
+        "spoken_button_focus_announcement": "Manage accessibility settings button, press Enter to personalize your accessibility tools in Chrome settings."
       },
       "url": "chrome://settings/accessibility"
     },
@@ -2445,22 +2486,22 @@
           "single": true,
           "synonyms": [
             [
-              48
+              50
             ],
             [
-              40
+              42
             ],
             [
-              29
+              31
             ],
             [
-              108
+              110
             ],
             [
               11
             ],
             [
-              63
+              65
             ]
           ]
         },
@@ -2469,14 +2510,14 @@
           "single": true,
           "synonyms": [
             [
-              83,
-              33
+              85,
+              35
             ],
             [
-              18
+              19
             ],
             [
-              33
+              35
             ]
           ]
         },
@@ -2485,39 +2526,39 @@
           "single": true,
           "synonyms": [
             [
-              75,
-              167
+              77,
+              170
             ],
             [
-              75,
-              166
+              77,
+              169
             ],
             [
-              76,
-              190
+              78,
+              193
             ],
             [
-              75,
-              165
+              77,
+              168
             ],
             [
-              75,
-              190
+              77,
+              193
             ],
             [
-              76
+              78
             ],
             [
-              75
+              77
             ]
           ]
         }
       ],
       "omnibox_ui_strings": {
-        "button_text": "Customize fonts in Chrome",
+        "button_text": "Customize fonts",
         "description_text": "Customize font sizes and typefaces in Chrome",
         "spoken_suggestion_description_suffix": "$1, Press tab then Enter to customize font sizes and typefaces in Chrome",
-        "spoken_button_focus_announcement": "Customize fonts in Chrome button, Enter to customize font sizes and typefaces in Chrome"
+        "spoken_button_focus_announcement": "Customize fonts in Chrome button, press Enter to customize font sizes and typefaces in Chrome"
       },
       "url": "chrome://settings/fonts"
     },
@@ -2529,22 +2570,22 @@
           "single": true,
           "synonyms": [
             [
-              48
+              50
             ],
             [
-              40
+              42
             ],
             [
-              29
+              31
             ],
             [
-              108
+              110
             ],
             [
-              115
+              117
             ],
             [
-              63
+              65
             ]
           ]
         },
@@ -2553,37 +2594,37 @@
           "single": true,
           "synonyms": [
             [
-              33,
-              15
+              35,
+              16
             ],
             [
-              33,
+              35,
               13
             ],
             [
-              33,
-              182
+              35,
+              185
             ],
             [
-              33,
-              38
+              35,
+              40
             ],
             [
-              33,
-              181
+              35,
+              184
             ],
             [
-              33,
-              37
+              35,
+              39
             ]
           ]
         }
       ],
       "omnibox_ui_strings": {
-        "button_text": "Manage Chrome appearance",
+        "button_text": "Customize appearance",
         "description_text": "Customize the look of your browser",
         "spoken_suggestion_description_suffix": "$1, Press tab then Enter to customize the look of your browser.",
-        "spoken_button_focus_announcement": "Manage Chrome appearance button, Enter to customize the look of your browser with themes."
+        "spoken_button_focus_announcement": "Manage Chrome appearance button, press Enter to customize the look of your browser with themes."
       },
       "url": "chrome://new-tab-page/?customize=backgrounds"
     },
@@ -2595,22 +2636,25 @@
           "single": true,
           "synonyms": [
             [
-              48
+              50
             ],
             [
-              40
+              42
             ],
             [
-              108
+              110
             ],
             [
-              29
+              31
             ],
             [
-              115
+              117
             ],
             [
-              63
+              65
+            ],
+            [
+              5
             ]
           ]
         },
@@ -2619,34 +2663,54 @@
           "single": true,
           "synonyms": [
             [
-              47,
-              152,
-              66
+              49,
+              155,
+              68
             ],
             [
-              164,
-              152,
-              66
+              167,
+              155,
+              68
             ],
             [
-              177,
-              152
+              180,
+              155
+            ],
+            [
+              51,
+              155
+            ],
+            [
+              155,
+              68
+            ],
+            [
+              153,
+              155
             ],
             [
               49,
-              152
+              155
             ],
             [
-              151,
-              152
+              167,
+              155
+            ]
+          ]
+        },
+        {
+          "required": false,
+          "single": true,
+          "synonyms": [
+            [
+              85,
+              35
             ],
             [
-              47,
-              152
+              19
             ],
             [
-              164,
-              152
+              35
             ]
           ]
         }
@@ -2655,7 +2719,7 @@
         "button_text": "Manage site search",
         "description_text": "Manage site search and your default search engine",
         "spoken_suggestion_description_suffix": "$1, Press tab then Enter to manage site search and your default search engine",
-        "spoken_button_focus_announcement": "Manage site search button, Enter to manage site search and your default search engine"
+        "spoken_button_focus_announcement": "Manage site search button, press Enter to manage site search and your default search engine"
       },
       "url": "chrome://settings/searchEngines"
     },
@@ -2667,22 +2731,22 @@
           "single": true,
           "synonyms": [
             [
-              48
+              50
             ],
             [
-              40
+              42
             ],
             [
-              108
+              110
             ],
             [
-              199
+              203
             ],
             [
-              197
+              201
             ],
             [
-              63
+              65
             ]
           ]
         },
@@ -2691,44 +2755,44 @@
           "single": true,
           "synonyms": [
             [
-              106,
-              198,
-              158
+              108,
+              202,
+              161
             ],
             [
-              106,
-              198,
-              72
+              108,
+              202,
+              74
             ],
             [
               1,
-              158
+              161
             ],
             [
               1,
-              72
+              74
             ],
             [
-              14,
-              179
+              15,
+              182
             ],
             [
-              33,
+              35,
               1
             ],
             [
-              23,
-              158
+              24,
+              161
             ],
             [
-              14,
-              178
+              15,
+              181
             ],
             [
               1
             ],
             [
-              24
+              25
             ]
           ]
         }
@@ -2747,43 +2811,43 @@
     "single": false,
     "synonyms": [
       [
-        94
+        96
       ],
       [
-        207
+        211
       ],
       [
-        77
+        79
       ],
       [
-        87
+        89
       ],
       [
-        180
+        183
       ],
       [
         12
       ],
       [
-        59
+        61
       ],
       [
-        90
+        92
       ],
       [
-        117
+        119
       ],
       [
-        123
+        125
       ],
       [
-        186
+        189
       ],
       [
         0
       ],
       [
-        88
+        90
       ]
     ]
   },
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_es-419.json b/components/omnibox/resources/omnibox_pedal_concepts_es-419.json
index d93300e..b589a2e7 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_es-419.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_es-419.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "abrir",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_es.json b/components/omnibox/resources/omnibox_pedal_concepts_es.json
index 001a3b9..91f7ae0 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_es.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_es.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "a",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_et.json b/components/omnibox/resources/omnibox_pedal_concepts_et.json
index c8963f6..8fd5016 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_et.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_et.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "ajalugu",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_fa.json b/components/omnibox/resources/omnibox_pedal_concepts_fa.json
index 8cf2673..a8fb38b3 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_fa.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_fa.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "chrome",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_fi.json b/components/omnibox/resources/omnibox_pedal_concepts_fi.json
index 402ce3ed..5771dfa7 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_fi.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_fi.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "asenna",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_fil.json b/components/omnibox/resources/omnibox_pedal_concepts_fil.json
index 942ef3e..3942564 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_fil.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_fil.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "akin",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_fr.json b/components/omnibox/resources/omnibox_pedal_concepts_fr.json
index 68a9530..97c6d105 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_fr.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_fr.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "actualise",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_gu.json b/components/omnibox/resources/omnibox_pedal_concepts_gu.json
index 49c4038..1056f5c 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_gu.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_gu.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "chrome",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_he.json b/components/omnibox/resources/omnibox_pedal_concepts_he.json
index b0536ea3..66fbc9f 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_he.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_he.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "chrome",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_hi.json b/components/omnibox/resources/omnibox_pedal_concepts_hi.json
index 954c2cd85..e8f500a7 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_hi.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_hi.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "chrome",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_hr.json b/components/omnibox/resources/omnibox_pedal_concepts_hr.json
index 01ac05a..119b750 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_hr.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_hr.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "anonimna",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_hu.json b/components/omnibox/resources/omnibox_pedal_concepts_hu.json
index 7e3cb68..cb15cf7 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_hu.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_hu.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "a",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_id.json b/components/omnibox/resources/omnibox_pedal_concepts_id.json
index b8bcbed..e0efb43d 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_id.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_id.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "bagaimana",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_it.json b/components/omnibox/resources/omnibox_pedal_concepts_it.json
index ec97523d..fb691b27 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_it.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_it.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "a",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_ja.json b/components/omnibox/resources/omnibox_pedal_concepts_ja.json
index a0a2406..7ea176c4 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_ja.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_ja.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": true,
   "dictionary": [
     " ",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_kn.json b/components/omnibox/resources/omnibox_pedal_concepts_kn.json
index ca7ab4c..19702c8 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_kn.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_kn.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "chrome",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_ko.json b/components/omnibox/resources/omnibox_pedal_concepts_ko.json
index 26846d0..1da5aba0 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_ko.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_ko.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "chrome",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_lt.json b/components/omnibox/resources/omnibox_pedal_concepts_lt.json
index 105dfb7..73512de1 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_lt.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_lt.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "a",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_lv.json b/components/omnibox/resources/omnibox_pedal_concepts_lv.json
index 9e0158f..399c185a 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_lv.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_lv.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "a",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_ml.json b/components/omnibox/resources/omnibox_pedal_concepts_ml.json
index 8b94536a..031aa4e 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_ml.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_ml.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "chrome",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_mr.json b/components/omnibox/resources/omnibox_pedal_concepts_mr.json
index f1570f2..67e1a551 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_mr.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_mr.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "chrome",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_ms.json b/components/omnibox/resources/omnibox_pedal_concepts_ms.json
index 83b481ed4..5d1b056 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_ms.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_ms.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "alih",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_nl.json b/components/omnibox/resources/omnibox_pedal_concepts_nl.json
index 142dc4f8..0dc8a01 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_nl.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_nl.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "aan",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_pl.json b/components/omnibox/resources/omnibox_pedal_concepts_pl.json
index 60523ae..0ad4a62 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_pl.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_pl.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "a",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_pt-BR.json b/components/omnibox/resources/omnibox_pedal_concepts_pt-BR.json
index 63ce8193a..e462f60 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_pt-BR.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_pt-BR.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "abrir",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_pt-PT.json b/components/omnibox/resources/omnibox_pedal_concepts_pt-PT.json
index 31fcd1e..c0352f5 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_pt-PT.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_pt-PT.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "abrir",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_ro.json b/components/omnibox/resources/omnibox_pedal_concepts_ro.json
index cf58a970a..8f97b9d 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_ro.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_ro.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "a",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_ru.json b/components/omnibox/resources/omnibox_pedal_concepts_ru.json
index 57d222f..5face0e 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_ru.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_ru.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "chrome",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_sk.json b/components/omnibox/resources/omnibox_pedal_concepts_sk.json
index 4246c78..87eb3d1 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_sk.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_sk.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "a",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_sl.json b/components/omnibox/resources/omnibox_pedal_concepts_sl.json
index 80428ad..4116f62c 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_sl.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_sl.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "beleženja",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_sr.json b/components/omnibox/resources/omnibox_pedal_concepts_sr.json
index 8742319..4ced820 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_sr.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_sr.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "chrome",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_sv.json b/components/omnibox/resources/omnibox_pedal_concepts_sv.json
index 18ebf66..c6852db 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_sv.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_sv.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "aktivera",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_sw.json b/components/omnibox/resources/omnibox_pedal_concepts_sw.json
index f13b60e..8f0f39b 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_sw.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_sw.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "anza",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_ta.json b/components/omnibox/resources/omnibox_pedal_concepts_ta.json
index 7902d9d..72fee249 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_ta.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_ta.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "chrome",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_te.json b/components/omnibox/resources/omnibox_pedal_concepts_te.json
index e8665a5..d49da1c 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_te.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_te.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "chrome",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_th.json b/components/omnibox/resources/omnibox_pedal_concepts_th.json
index 78ac6636..bddbc93 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_th.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_th.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "chrome",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_tr.json b/components/omnibox/resources/omnibox_pedal_concepts_tr.json
index 09c4849..f6277a4 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_tr.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_tr.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "aç",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_uk.json b/components/omnibox/resources/omnibox_pedal_concepts_uk.json
index 1b7fd575..8dab185e 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_uk.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_uk.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "a",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_vi.json b/components/omnibox/resources/omnibox_pedal_concepts_vi.json
index f7eaa7b..23a1516 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_vi.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_vi.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "a",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_zh-CN.json b/components/omnibox/resources/omnibox_pedal_concepts_zh-CN.json
index 0a566a31..7459d24 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_zh-CN.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_zh-CN.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": true,
   "dictionary": [
     " ",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_zh-TW.json b/components/omnibox/resources/omnibox_pedal_concepts_zh-TW.json
index 6d4bcd9..5be40ea 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_zh-TW.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_zh-TW.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 3,
-  "data_version": 16031267,
+  "data_version": 16049958,
   "tokenize_each_character": false,
   "dictionary": [
     "chrome",
diff --git a/components/omnibox/resources/omnibox_pedal_synonyms.grd_unused b/components/omnibox/resources/omnibox_pedal_synonyms.grd_unused
index c61f7d1..560cd01e 100644
--- a/components/omnibox/resources/omnibox_pedal_synonyms.grd_unused
+++ b/components/omnibox/resources/omnibox_pedal_synonyms.grd_unused
@@ -289,7 +289,7 @@
 
       <!-- Pedal #34: SHARE_THIS_PAGE -->
       <message name="IDS_OMNIBOX_PEDAL_SYNONYMS_SHARE_THIS_PAGE_ONE_REQUIRED_SHARE_LINK_WITH_QR_CODE" is_accessibility_with_no_ui="true" desc="Synonyms for the SHARE_THIS_PAGE Pedal's 'share link with qr code' group. To trigger, exactly ONE of this group is REQUIRED. Context: The user is typing into the omnibox to find a way to 'Learn about and use the Sharing Hub' but the user is not sure how to describe this action. The input text is scanned for any words included in this synonym group to determine whether this concept is present in the query. Do not translate the list word for word; rather, list the various ways users typing in the target language might describe this synonym group's concept when trying to perform this Pedal's action. Each Pedal has a few such groups, some required and some optional, and this list represents just one (the 'share link with qr code' group). Being able to identify presence of specific concepts in the query enables the Pedals system to help the user perform the desired action.">
-        share link with qr code, send link with qr code, share this page, share link, share page, send link, send page, qr code
+        share link with qr code, send link with qr code, share link via qr code, send link via qr code, share this page, cast this page, save this page, save page as, cast screen, share link, share page, send link, send page, cast page, qr code
       </message>
 
       <!-- Pedal #35: MANAGE_CHROME_ACCESSIBILITY -->
@@ -321,10 +321,13 @@
 
       <!-- Pedal #38: CUSTOMIZE_SEARCH_ENGINES -->
       <message name="IDS_OMNIBOX_PEDAL_SYNONYMS_CUSTOMIZE_SEARCH_ENGINES_ONE_OPTIONAL_CUSTOMIZE" is_accessibility_with_no_ui="true" desc="Synonyms for the CUSTOMIZE_SEARCH_ENGINES Pedal's 'customize' group. To trigger, exactly ONE of this group is OPTIONAL. Context: The user is typing into the omnibox to find a way to 'Manage search engines in Chrome' via chrome://settings/searchEngines but the user is not sure how to describe this action. The input text is scanned for any words included in this synonym group to determine whether this concept is present in the query. Do not translate the list word for word; rather, list the various ways users typing in the target language might describe this synonym group's concept when trying to perform this Pedal's action. Each Pedal has a few such groups, some required and some optional, and this list represents just one (the 'customize' group). Being able to identify presence of specific concepts in the query enables the Pedals system to help the user perform the desired action.">
-        customize, control, manage, change, modify, edit
+        customize, control, manage, change, modify, edit, add
       </message>
       <message name="IDS_OMNIBOX_PEDAL_SYNONYMS_CUSTOMIZE_SEARCH_ENGINES_ONE_REQUIRED_CUSTOM_SEARCH_ENGINES" is_accessibility_with_no_ui="true" desc="Synonyms for the CUSTOMIZE_SEARCH_ENGINES Pedal's 'custom search engines' group. To trigger, exactly ONE of this group is REQUIRED. Context: The user is typing into the omnibox to find a way to 'Manage search engines in Chrome' via chrome://settings/searchEngines but the user is not sure how to describe this action. The input text is scanned for any words included in this synonym group to determine whether this concept is present in the query. Do not translate the list word for word; rather, list the various ways users typing in the target language might describe this synonym group's concept when trying to perform this Pedal's action. Each Pedal has a few such groups, some required and some optional, and this list represents just one (the 'custom search engines' group). Being able to identify presence of specific concepts in the query enables the Pedals system to help the user perform the desired action.">
-        custom search engines, site search engines, customized search, tab to search, scoped search, custom search, site search
+        custom search engines, site search engines, customized search, search engines, tab to search, scoped search, custom search, site search
+      </message>
+      <message name="IDS_OMNIBOX_PEDAL_SYNONYMS_CUSTOMIZE_SEARCH_ENGINES_ONE_OPTIONAL_GOOGLE_CHROME" is_accessibility_with_no_ui="true" desc="Synonyms for the CUSTOMIZE_SEARCH_ENGINES Pedal's 'google chrome' group. To trigger, exactly ONE of this group is OPTIONAL. Context: The user is typing into the omnibox to find a way to 'Manage search engines in Chrome' via chrome://settings/searchEngines but the user is not sure how to describe this action. The input text is scanned for any words included in this synonym group to determine whether this concept is present in the query. Do not translate the list word for word; rather, list the various ways users typing in the target language might describe this synonym group's concept when trying to perform this Pedal's action. Each Pedal has a few such groups, some required and some optional, and this list represents just one (the 'google chrome' group). Being able to identify presence of specific concepts in the query enables the Pedals system to help the user perform the desired action.">
+        google chrome, browser, chrome
       </message>
 
       <!-- Pedal #39: MANAGE_CHROMEOS_ACCESSIBILITY -->
diff --git a/components/omnibox_strings.grdp b/components/omnibox_strings.grdp
index c48d22b..eaaac1f 100644
--- a/components/omnibox_strings.grdp
+++ b/components/omnibox_strings.grdp
@@ -106,6 +106,33 @@
   </if>
 
 
+  <!-- Omnibox Actions, which are a generalization of Omnibox Pedals. -->
+  <message name="IDS_OMNIBOX_ACTION_HISTORY_CLUSTERS_SEARCH_HINT" desc="The button text for the History Clusters omnibox action. Clicking this button takes users to a view of their browsing history related to the attached suggestion.">
+    Resume your journey
+  </message>
+  <message name="IDS_OMNIBOX_ACTION_HISTORY_CLUSTERS_SEARCH_SUGGESTION_CONTENTS" desc="The button tooltip for the History Clusters omnibox action. Clicking this button takes users to a view of their browsing history related to the attached suggestion.">
+    Resume your journey to see relevant activity in your Chrome history
+  </message>
+  <message name="IDS_ACC_OMNIBOX_ACTION_HISTORY_CLUSTERS_SEARCH_SUFFIX" desc="Suffix for spoken suggestion description with action button to explain keystroke used to Search History Clusters.">
+    <ph name="HISTORY_CLUSTERS_SEARCH_FOCUSED_FRIENDLY_MATCH_TEXT">$1<ex>dog food</ex></ph>, press Tab, then Enter to resume your journey and see relevant activity in your Chrome history
+  </message>
+  <message name="IDS_ACC_OMNIBOX_ACTION_HISTORY_CLUSTERS_SEARCH" desc="Announcement when the Search History Clusters action button is focused.">
+    Resume your journey button, press Enter to resume your journey and see relevant activity in your Chrome history
+  </message>
+  <message name="IDS_OMNIBOX_ACTION_HISTORY_CLUSTERS_SEARCH_HINT_ALTERNATE" desc="The button text for the History Clusters omnibox action. Clicking this button takes users to a view of their browsing history related to the attached suggestion.">
+    Resume your research
+  </message>
+  <message name="IDS_OMNIBOX_ACTION_HISTORY_CLUSTERS_SEARCH_SUGGESTION_CONTENTS_ALTERNATE" desc="The button tooltip for the History Clusters omnibox action. Clicking this button takes users to a view of their browsing history related to the attached suggestion.">
+    Resume your research to see relevant activity in your Chrome history
+  </message>
+  <message name="IDS_ACC_OMNIBOX_ACTION_HISTORY_CLUSTERS_SEARCH_SUFFIX_ALTERNATE" desc="Suffix for spoken suggestion description with action button to explain keystroke used to Search History Clusters.">
+    <ph name="HISTORY_CLUSTERS_SEARCH_FOCUSED_FRIENDLY_MATCH_TEXT">$1<ex>dog food</ex></ph>, press Tab, then Enter to resume your research and see relevant activity in your Chrome history
+  </message>
+  <message name="IDS_ACC_OMNIBOX_ACTION_HISTORY_CLUSTERS_SEARCH_ALTERNATE" desc="Announcement when the Search History Clusters action button is focused.">
+    Resume your research button, press Enter to resume your research and see relevant activity in your Chrome history
+  </message>
+
+
   <!-- Omnibox Pedals -->
   <message name="IDS_OMNIBOX_PEDAL_CLEAR_BROWSING_DATA_HINT" desc="The button text contents to suggest pedal action, clear browsing data.">
     Clear browsing data
@@ -394,87 +421,55 @@
   </message>
 
   <message name="IDS_OMNIBOX_PEDAL_CLOSE_INCOGNITO_WINDOWS_HINT" desc="The button text contents to suggest pedal action, CLOSE_INCOGNITO_WINDOWS">
-    Close incognito windows
+    Close all Incognito windows
   </message>
   <message name="IDS_OMNIBOX_PEDAL_CLOSE_INCOGNITO_WINDOWS_SUGGESTION_CONTENTS" desc="The button hover tooltip text to describe pedal action, CLOSE_INCOGNITO_WINDOWS">
-    Close all incognito windows for the current incognito profile
+    Close all Incognito windows that are currently open.
   </message>
-  <message name="IDS_ACC_OMNIBOX_PEDAL_CLOSE_INCOGNITO_WINDOWS_SUFFIX" desc="Suffix for spoken suggestion description with pedal action button, to explain keystroke used to close incognito windows.">
-    <ph name="CLOSE_INCOGNITO_WINDOWS_FOCUSED_FRIENDLY_MATCH_TEXT">$1<ex>The Chromium Projects http://www.chromium.org bookmark</ex></ph>, press Tab then Enter to close all incognito windows for the current incognito profile
+  <message name="IDS_ACC_OMNIBOX_PEDAL_CLOSE_INCOGNITO_WINDOWS_SUFFIX" desc="Suffix for spoken suggestion description with pedal action button, to explain keystroke used to CLOSE_INCOGNITO_WINDOWS.">
+    <ph name="CLOSE_INCOGNITO_WINDOWS_FOCUSED_FRIENDLY_MATCH_TEXT">$1<ex>The Chromium Projects http://www.chromium.org bookmark</ex></ph>, Press tab then Enter to close all Incognito windows that are currently open.
   </message>
   <message name="IDS_ACC_OMNIBOX_PEDAL_CLOSE_INCOGNITO_WINDOWS" desc="Announcement when pedal action button is focused, CLOSE_INCOGNITO_WINDOWS">
-    Close incognito windows button, press Enter to close all incognito windows for the current incognito profile
+    Close Incognito windows button, press Enter to close all Incognito windows that are currently open.
   </message>
 
   <message name="IDS_OMNIBOX_PEDAL_PLAY_CHROME_DINO_GAME_HINT" desc="The button text contents to suggest pedal action, PLAY_CHROME_DINO_GAME">
-    Play Chrome Dino
+    Play Chrome Dino game
   </message>
   <message name="IDS_OMNIBOX_PEDAL_PLAY_CHROME_DINO_GAME_SUGGESTION_CONTENTS" desc="The button hover tooltip text to describe pedal action, PLAY_CHROME_DINO_GAME">
-    Play the Chrome Dino game
+    Play the Dino Run game in Chrome
   </message>
-  <message name="IDS_ACC_OMNIBOX_PEDAL_PLAY_CHROME_DINO_GAME_SUFFIX" desc="Suffix for spoken suggestion description with pedal action button, to explain keystroke used to play Chrome Dino game.">
-    <ph name="PLAY_CHROME_DINO_GAME_FOCUSED_FRIENDLY_MATCH_TEXT">$1<ex>The Chromium Projects http://www.chromium.org bookmark</ex></ph>, press Tab then Enter to play the Chrome Dino game
+  <message name="IDS_ACC_OMNIBOX_PEDAL_PLAY_CHROME_DINO_GAME_SUFFIX" desc="Suffix for spoken suggestion description with pedal action button, to explain keystroke used to PLAY_CHROME_DINO_GAME.">
+    <ph name="PLAY_CHROME_DINO_GAME_FOCUSED_FRIENDLY_MATCH_TEXT">$1<ex>The Chromium Projects http://www.chromium.org bookmark</ex></ph>, Press tab then Enter to play the Dino Run game in Chrome
   </message>
   <message name="IDS_ACC_OMNIBOX_PEDAL_PLAY_CHROME_DINO_GAME" desc="Announcement when pedal action button is focused, PLAY_CHROME_DINO_GAME">
-    Play Chrome Dino game button, press Enter to play the Chrome Dino game
+    Play Dino Run button, press Enter to play the Dino Run game in Chrome
   </message>
 
-  <!-- Omnibox Actions, which are a generalization of Omnibox Pedals. -->
-  <message name="IDS_OMNIBOX_ACTION_HISTORY_CLUSTERS_SEARCH_HINT" desc="The button text for the History Clusters omnibox action. Clicking this button takes users to a view of their browsing history related to the attached suggestion.">
-    Resume your journey
-  </message>
-  <message name="IDS_OMNIBOX_ACTION_HISTORY_CLUSTERS_SEARCH_SUGGESTION_CONTENTS" desc="The button tooltip for the History Clusters omnibox action. Clicking this button takes users to a view of their browsing history related to the attached suggestion.">
-    Resume your journey to see relevant activity in your Chrome history
-  </message>
-  <message name="IDS_ACC_OMNIBOX_ACTION_HISTORY_CLUSTERS_SEARCH_SUFFIX" desc="Suffix for spoken suggestion description with action button to explain keystroke used to Search History Clusters.">
-    <ph name="HISTORY_CLUSTERS_SEARCH_FOCUSED_FRIENDLY_MATCH_TEXT">$1<ex>dog food</ex></ph>, press Tab, then Enter to resume your journey and see relevant activity in your Chrome history
-  </message>
-  <message name="IDS_ACC_OMNIBOX_ACTION_HISTORY_CLUSTERS_SEARCH" desc="Announcement when the Search History Clusters action button is focused.">
-    Resume your journey button, press Enter to resume your journey and see relevant activity in your Chrome history
-  </message>
-
-  <message name="IDS_OMNIBOX_ACTION_HISTORY_CLUSTERS_SEARCH_HINT_ALTERNATE" desc="The button text for the History Clusters omnibox action. Clicking this button takes users to a view of their browsing history related to the attached suggestion.">
-    Resume your research
-  </message>
-  <message name="IDS_OMNIBOX_ACTION_HISTORY_CLUSTERS_SEARCH_SUGGESTION_CONTENTS_ALTERNATE" desc="The button tooltip for the History Clusters omnibox action. Clicking this button takes users to a view of their browsing history related to the attached suggestion.">
-    Resume your research to see relevant activity in your Chrome history
-  </message>
-  <message name="IDS_ACC_OMNIBOX_ACTION_HISTORY_CLUSTERS_SEARCH_SUFFIX_ALTERNATE" desc="Suffix for spoken suggestion description with action button to explain keystroke used to Search History Clusters.">
-    <ph name="HISTORY_CLUSTERS_SEARCH_FOCUSED_FRIENDLY_MATCH_TEXT">$1<ex>dog food</ex></ph>, press Tab, then Enter to resume your research and see relevant activity in your Chrome history
-  </message>
-  <message name="IDS_ACC_OMNIBOX_ACTION_HISTORY_CLUSTERS_SEARCH_ALTERNATE" desc="Announcement when the Search History Clusters action button is focused.">
-    Resume your research button, press Enter to resume your research and see relevant activity in your Chrome history
-  </message>
-
-
-
-
-
-
   <message name="IDS_OMNIBOX_PEDAL_FIND_MY_PHONE_HINT" desc="The button text contents to suggest pedal action, FIND_MY_PHONE">
-    Find my phone
+    Find your phone
   </message>
   <message name="IDS_OMNIBOX_PEDAL_FIND_MY_PHONE_SUGGESTION_CONTENTS" desc="The button hover tooltip text to describe pedal action, FIND_MY_PHONE">
-    Find my phone
+    Find, secure, or erase your device
   </message>
   <message name="IDS_ACC_OMNIBOX_PEDAL_FIND_MY_PHONE_SUFFIX" desc="Suffix for spoken suggestion description with pedal action button, to explain keystroke used to FIND_MY_PHONE.">
-    <ph name="FIND_MY_PHONE_FOCUSED_FRIENDLY_MATCH_TEXT">$1<ex>The Chromium Projects http://www.chromium.org bookmark</ex></ph>, Find my phone
+    <ph name="FIND_MY_PHONE_FOCUSED_FRIENDLY_MATCH_TEXT">$1<ex>The Chromium Projects http://www.chromium.org bookmark</ex></ph>, Press Tab then Enter to Find your device in the Google Account
   </message>
   <message name="IDS_ACC_OMNIBOX_PEDAL_FIND_MY_PHONE" desc="Announcement when pedal action button is focused, FIND_MY_PHONE">
-    Find my phone
+    Find my device button, press Enter to visit find your device in the Google Account
   </message>
 
   <message name="IDS_OMNIBOX_PEDAL_MANAGE_GOOGLE_PRIVACY_HINT" desc="The button text contents to suggest pedal action, MANAGE_GOOGLE_PRIVACY">
-    Manage my privacy on Google
+    Manage Google Account privacy settings
   </message>
   <message name="IDS_OMNIBOX_PEDAL_MANAGE_GOOGLE_PRIVACY_SUGGESTION_CONTENTS" desc="The button hover tooltip text to describe pedal action, MANAGE_GOOGLE_PRIVACY">
-    Manage my privacy on Google
+    Manage Google privacy settings in your Google Account
   </message>
   <message name="IDS_ACC_OMNIBOX_PEDAL_MANAGE_GOOGLE_PRIVACY_SUFFIX" desc="Suffix for spoken suggestion description with pedal action button, to explain keystroke used to MANAGE_GOOGLE_PRIVACY.">
-    <ph name="MANAGE_GOOGLE_PRIVACY_FOCUSED_FRIENDLY_MATCH_TEXT">$1<ex>The Chromium Projects http://www.chromium.org bookmark</ex></ph>, Manage my privacy on Google
+    <ph name="MANAGE_GOOGLE_PRIVACY_FOCUSED_FRIENDLY_MATCH_TEXT">$1<ex>The Chromium Projects http://www.chromium.org bookmark</ex></ph>, Press Tab then Enter to manage your Google Account privacy settings
   </message>
   <message name="IDS_ACC_OMNIBOX_PEDAL_MANAGE_GOOGLE_PRIVACY" desc="Announcement when pedal action button is focused, MANAGE_GOOGLE_PRIVACY">
-    Manage my privacy on Google
+    Manage Google Privacy settings button, press Enter to visit your Google Account privacy settings
   </message>
 
   <message name="IDS_OMNIBOX_PEDAL_MANAGE_CHROME_SETTINGS_HINT" desc="The button text contents to suggest pedal action, MANAGE_CHROME_SETTINGS">
@@ -491,7 +486,7 @@
   </message>
 
   <message name="IDS_OMNIBOX_PEDAL_MANAGE_CHROME_DOWNLOADS_HINT" desc="The button text contents to suggest pedal action, MANAGE_CHROME_DOWNLOADS">
-    Manage downloads in Chrome
+    Manage downloads
   </message>
   <message name="IDS_OMNIBOX_PEDAL_MANAGE_CHROME_DOWNLOADS_SUGGESTION_CONTENTS" desc="The button hover tooltip text to describe pedal action, MANAGE_CHROME_DOWNLOADS">
     Manage files you have downloaded in Chrome
@@ -513,7 +508,7 @@
     <ph name="VIEW_CHROME_HISTORY_FOCUSED_FRIENDLY_MATCH_TEXT">$1<ex>The Chromium Projects http://www.chromium.org bookmark</ex></ph>, Press tab then Enter to view your browsing history in Chrome
   </message>
   <message name="IDS_ACC_OMNIBOX_PEDAL_VIEW_CHROME_HISTORY" desc="Announcement when pedal action button is focused, VIEW_CHROME_HISTORY">
-    View your Chrome history button, Enter to view and manage your browsing history in Chrome settings
+    View your Chrome history button, press Enter to view and manage your browsing history in Chrome settings
   </message>
 
   <message name="IDS_OMNIBOX_PEDAL_SHARE_THIS_PAGE_HINT" desc="The button text contents to suggest pedal action, SHARE_THIS_PAGE">
@@ -526,7 +521,7 @@
     <ph name="SHARE_THIS_PAGE_FOCUSED_FRIENDLY_MATCH_TEXT">$1<ex>The Chromium Projects http://www.chromium.org bookmark</ex></ph>, Press tab then Enter to share this page, with options to share the link, create a QR code, cast, and more.
   </message>
   <message name="IDS_ACC_OMNIBOX_PEDAL_SHARE_THIS_PAGE" desc="Announcement when pedal action button is focused, SHARE_THIS_PAGE">
-    Share this page button, Enter to share this page with options to share the link, create a QR code, cast, and more.
+    Share this page button, press Enter to share this page with options to share the link, create a QR code, cast, and more.
   </message>
 
   <message name="IDS_OMNIBOX_PEDAL_MANAGE_CHROME_ACCESSIBILITY_HINT" desc="The button text contents to suggest pedal action, MANAGE_CHROME_ACCESSIBILITY">
@@ -539,11 +534,11 @@
     <ph name="MANAGE_CHROME_ACCESSIBILITY_FOCUSED_FRIENDLY_MATCH_TEXT">$1<ex>The Chromium Projects http://www.chromium.org bookmark</ex></ph>, Press tab then Enter to personalize your accessibility tools in Chrome settings.
   </message>
   <message name="IDS_ACC_OMNIBOX_PEDAL_MANAGE_CHROME_ACCESSIBILITY" desc="Announcement when pedal action button is focused, MANAGE_CHROME_ACCESSIBILITY">
-    Manage accessibility settings button, Enter to personalize your accessibility tools in Chrome settings.
+    Manage accessibility settings button, press Enter to personalize your accessibility tools in Chrome settings.
   </message>
 
   <message name="IDS_OMNIBOX_PEDAL_CUSTOMIZE_CHROME_FONTS_HINT" desc="The button text contents to suggest pedal action, CUSTOMIZE_CHROME_FONTS">
-    Customize fonts in Chrome
+    Customize fonts
   </message>
   <message name="IDS_OMNIBOX_PEDAL_CUSTOMIZE_CHROME_FONTS_SUGGESTION_CONTENTS" desc="The button hover tooltip text to describe pedal action, CUSTOMIZE_CHROME_FONTS">
     Customize font sizes and typefaces in Chrome
@@ -552,20 +547,20 @@
     <ph name="CUSTOMIZE_CHROME_FONTS_FOCUSED_FRIENDLY_MATCH_TEXT">$1<ex>The Chromium Projects http://www.chromium.org bookmark</ex></ph>, Press tab then Enter to customize font sizes and typefaces in Chrome
   </message>
   <message name="IDS_ACC_OMNIBOX_PEDAL_CUSTOMIZE_CHROME_FONTS" desc="Announcement when pedal action button is focused, CUSTOMIZE_CHROME_FONTS">
-    Customize fonts in Chrome button, Enter to customize font sizes and typefaces in Chrome
+    Customize fonts in Chrome button, press Enter to customize font sizes and typefaces in Chrome
   </message>
 
   <message name="IDS_OMNIBOX_PEDAL_MANAGE_CHROME_THEMES_HINT" desc="The button text contents to suggest pedal action, MANAGE_CHROME_THEMES">
-    Manage Chrome themes
+    Customize appearance
   </message>
   <message name="IDS_OMNIBOX_PEDAL_MANAGE_CHROME_THEMES_SUGGESTION_CONTENTS" desc="The button hover tooltip text to describe pedal action, MANAGE_CHROME_THEMES">
-    Customize the look of your browser with themes
+    Customize the look of your browser
   </message>
   <message name="IDS_ACC_OMNIBOX_PEDAL_MANAGE_CHROME_THEMES_SUFFIX" desc="Suffix for spoken suggestion description with pedal action button, to explain keystroke used to MANAGE_CHROME_THEMES.">
-    <ph name="MANAGE_CHROME_THEMES_FOCUSED_FRIENDLY_MATCH_TEXT">$1<ex>The Chromium Projects http://www.chromium.org bookmark</ex></ph>, Press tab then Enter to customize the look of your browser with themes.
+    <ph name="MANAGE_CHROME_THEMES_FOCUSED_FRIENDLY_MATCH_TEXT">$1<ex>The Chromium Projects http://www.chromium.org bookmark</ex></ph>, Press tab then Enter to customize the look of your browser.
   </message>
   <message name="IDS_ACC_OMNIBOX_PEDAL_MANAGE_CHROME_THEMES" desc="Announcement when pedal action button is focused, MANAGE_CHROME_THEMES">
-    Manage Chrome themes button, Enter to customize the look of your browser with themes.
+    Manage Chrome appearance button, press Enter to customize the look of your browser with themes.
   </message>
 
   <message name="IDS_OMNIBOX_PEDAL_CUSTOMIZE_SEARCH_ENGINES_HINT" desc="The button text contents to suggest pedal action, CUSTOMIZE_SEARCH_ENGINES">
@@ -591,8 +586,9 @@
     <ph name="MANAGE_CHROMEOS_ACCESSIBILITY_FOCUSED_FRIENDLY_MATCH_TEXT">$1<ex>The Chromium Projects http://www.chromium.org bookmark</ex></ph>, Press tab then Enter to personalize your accessibility tools in Chrome OS settings.
   </message>
   <message name="IDS_ACC_OMNIBOX_PEDAL_MANAGE_CHROMEOS_ACCESSIBILITY" desc="Announcement when pedal action button is focused, MANAGE_CHROMEOS_ACCESSIBILITY">
-    Manage accessibility settings button, press Enter to personalize your accessibility tools in Chrome OS settings
+    Manage accessibility settings button, Enter to personalize your accessibility tools in Chrome OS settings
   </message>
+  <!-- End of Pedals -->
 
 
   <!-- Accessibility labels for autocomplete match types.
diff --git a/components/page_load_metrics/renderer/page_timing_metrics_sender_unittest.cc b/components/page_load_metrics/renderer/page_timing_metrics_sender_unittest.cc
index 0acd6ac..30d6dedf 100644
--- a/components/page_load_metrics/renderer/page_timing_metrics_sender_unittest.cc
+++ b/components/page_load_metrics/renderer/page_timing_metrics_sender_unittest.cc
@@ -167,7 +167,7 @@
   mojom::PageLoadTiming timing;
   blink::MobileFriendliness mobile_friendliness;
   mobile_friendliness.viewport_hardcoded_width = 480;
-  mobile_friendliness.allow_user_zoom = blink::mojom::ViewportStatus::kYes;
+  mobile_friendliness.allow_user_zoom = true;
   InitPageLoadTimingForTest(&timing);
   metrics_sender_->Update(timing.Clone(),
                           PageTimingMetadataRecorder::MonotonicTiming());
@@ -177,7 +177,7 @@
 
   blink::MobileFriendliness expected_mf;
   expected_mf.viewport_hardcoded_width = 480;
-  expected_mf.allow_user_zoom = blink::mojom::ViewportStatus::kYes;
+  expected_mf.allow_user_zoom = true;
   validator_.UpdateExpectedMobileFriendliness(expected_mf);
   metrics_sender_->mock_timer()->Fire();
   validator_.VerifyExpectedMobileFriendliness();
diff --git a/components/policy/tools/generate_policy_source.py b/components/policy/tools/generate_policy_source.py
index a0051ad..e485783 100755
--- a/components/policy/tools/generate_policy_source.py
+++ b/components/policy/tools/generate_policy_source.py
@@ -1463,7 +1463,7 @@
 RESERVED_IDS = 2
 
 
-def _WritePolicyProto(f, policy, fields):
+def _WritePolicyProto(f, policy):
   _OutputComment(f, policy.caption + '\n\n' + policy.desc)
   if policy.items is not None:
     _OutputComment(f, '\nValid values:')
@@ -1484,10 +1484,6 @@
   f.write('  optional PolicyOptions policy_options = 1;\n')
   f.write('  optional %s %s = 2;\n' % (policy.protobuf_type, policy.name))
   f.write('}\n\n')
-  fields += [
-      '  optional %sProto %s = %s;\n' % (policy.name, policy.name,
-                                         policy.id + RESERVED_IDS)
-  ]
 
 
 def _WriteChromeSettingsProtobuf(policies,
@@ -1510,7 +1506,13 @@
     # Note: This protobuf also gets the unsupported policies, since it's an
     # exhaustive list of all the supported user policies on any platform.
     if not policy.is_device_only:
-      _WritePolicyProto(f, policy, fields)
+      # Write the individual policy proto into the file
+      _WritePolicyProto(f, policy)
+      # Add to |fields| in order to eventually add to ChromeSettingsProto
+      fields += [
+          '  optional %sProto %s = %s;\n' %
+          (policy.name, policy.name, policy.id + RESERVED_IDS)
+      ]
 
   f.write('// --------------------------------------------------\n'
           '// Big wrapper PB containing the above groups.\n\n'
diff --git a/components/policy/tools/generate_policy_source_test.py b/components/policy/tools/generate_policy_source_test.py
index dcf4d659..5092ebe 100755
--- a/components/policy/tools/generate_policy_source_test.py
+++ b/components/policy/tools/generate_policy_source_test.py
@@ -211,6 +211,17 @@
         self._assertCallsEqual(mocked_file().write.call_args_list,
                                expected_formatted)
 
+  def testWritePolicyProto(self):
+    output_path = 'mock_write_policy_proto'
+
+    with patch('codecs.open', mock_open()) as mocked_file:
+      with codecs.open(output_path, 'w', encoding='utf-8') as f:
+        generate_policy_source._WritePolicyProto(f, self.policies[0])
+
+    mocked_file.assert_called_once_with(output_path, 'w', encoding='utf-8')
+    self._assertCallsEqual(mocked_file().write.call_args_list,
+                           test_data.EXPECTED_POLICY_PROTO)
+
   def testGetMetapoliciesOfType(self):
     merge_metapolicies = generate_policy_source._GetMetapoliciesOfType(
         self.policies, "merge")
diff --git a/components/policy/tools/generate_policy_source_test_data.py b/components/policy/tools/generate_policy_source_test_data.py
index 483b106c..6e94b551 100644
--- a/components/policy/tools/generate_policy_source_test_data.py
+++ b/components/policy/tools/generate_policy_source_test_data.py
@@ -86,6 +86,18 @@
 }
 """
 
+EXPECTED_POLICY_PROTO = '''\
+// ExampleStringPolicy caption
+//
+// ExampleStringPolicy desc
+//
+// Supported on: chrome_os
+message ExampleStringPolicyProto {
+  optional PolicyOptions policy_options = 1;
+  optional string ExampleStringPolicy = 2;
+}
+'''
+
 EXPECTED_POLICY_CONSTANTS_HEADER = '''
 #ifndef COMPONENTS_POLICY_POLICY_CONSTANTS_H_
 #define COMPONENTS_POLICY_POLICY_CONSTANTS_H_
@@ -533,4 +545,4 @@
 };
 
 }  // namespace policy
-'''
+'''
\ No newline at end of file
diff --git a/components/site_isolation/features.cc b/components/site_isolation/features.cc
index bd0e06a..cf3725d 100644
--- a/components/site_isolation/features.cc
+++ b/components/site_isolation/features.cc
@@ -47,19 +47,24 @@
 #endif
 };
 
-// kSitePerProcessOnlyForHighMemoryClients is checked before kSitePerProcess,
-// and (if enabled) can restrict if kSitePerProcess feature is checked at all -
-// no check will be made on devices with low memory (these devices will have no
-// Site Isolation via kSitePerProcess trials and won't activate either the
-// control or the experiment group).  The threshold for what is considered a
-// "low memory" device is set (in MB) via a field trial param with the name
-// defined below ("site-per-process-low-memory-cutoff-mb") and compared against
-// base::SysInfo::AmountOfPhysicalMemoryMB().
-const base::Feature kSitePerProcessOnlyForHighMemoryClients{
-    "site-per-process-only-for-high-memory-clients",
-    base::FEATURE_DISABLED_BY_DEFAULT};
-const char kSitePerProcessOnlyForHighMemoryClientsParamName[] =
-    "site-per-process-low-memory-cutoff-mb";
+// kSiteIsolationMemoryThresholds is checked before individual site isolation
+// mode base::Features (such as kSitePerProcess or
+// kSiteIsolationForPasswordSites), and (if enabled) can restrict those modes
+// to not apply to low-memory devices below a certain memory threshold.  The
+// threshold for what is considered a "low memory" device can be set (in MB)
+// via field trial params with the names defined below, with independent params
+// for strict site isolation (kSitePerProcess) and partial site isolation modes
+// (kSiteIsolationForPasswordSites, kSiteIsolationForOAuthSites, etc). These
+// thresholds are compared against base::SysInfo::AmountOfPhysicalMemoryMB().
+// On devices below the memory threshold, the site isolation features such as
+// kSitePerProcess won't be checked at all, and field trials won't activate
+// either the control or the experiment group.
+const base::Feature kSiteIsolationMemoryThresholds{
+    "SiteIsolationMemoryThresholds", base::FEATURE_DISABLED_BY_DEFAULT};
+const char kStrictSiteIsolationMemoryThresholdParamName[] =
+    "strict_site_isolation_threshold_mb";
+const char kPartialSiteIsolationMemoryThresholdParamName[] =
+    "partial_site_isolation_threshold_mb";
 
 }  // namespace features
 }  // namespace site_isolation
diff --git a/components/site_isolation/features.h b/components/site_isolation/features.h
index 5c75cf4..90ed4a2b 100644
--- a/components/site_isolation/features.h
+++ b/components/site_isolation/features.h
@@ -12,8 +12,9 @@
 
 extern const base::Feature kSiteIsolationForPasswordSites;
 extern const base::Feature kSiteIsolationForOAuthSites;
-extern const base::Feature kSitePerProcessOnlyForHighMemoryClients;
-extern const char kSitePerProcessOnlyForHighMemoryClientsParamName[];
+extern const base::Feature kSiteIsolationMemoryThresholds;
+extern const char kStrictSiteIsolationMemoryThresholdParamName[];
+extern const char kPartialSiteIsolationMemoryThresholdParamName[];
 
 }  // namespace features
 }  // namespace site_isolation
diff --git a/components/site_isolation/site_isolation_policy.cc b/components/site_isolation/site_isolation_policy.cc
index 0ba8b77..773fbfc 100644
--- a/components/site_isolation/site_isolation_policy.cc
+++ b/components/site_isolation/site_isolation_policy.cc
@@ -98,40 +98,51 @@
 }
 
 // static
-bool SiteIsolationPolicy::ShouldDisableSiteIsolationDueToMemoryThreshold() {
+bool SiteIsolationPolicy::ShouldDisableSiteIsolationDueToMemoryThreshold(
+    content::SiteIsolationMode site_isolation_mode) {
   // The memory threshold behavior differs for desktop and Android:
-  // - Android uses a 1900MB default threshold, which is the threshold used by
-  //   password-triggered site isolation - see docs in
-  //   https://crbug.com/849815.  This can be overridden via a param defined in
-  //   a kSitePerProcessOnlyForHighMemoryClients field trial.
+  // - Android uses a 1900MB default threshold for partial site isolation modes
+  //   and a 3200MB default threshold for strict site isolation. See docs in
+  //   https://crbug.com/849815. The thresholds roughly correspond to 2GB+ and
+  //   4GB+ devices and are lower to account for memory carveouts, which
+  //   reduce the amount of memory seen by AmountOfPhysicalMemoryMB(). Both
+  //   partial and strict site isolation thresholds can be overridden via
+  //   params defined in a kSiteIsolationMemoryThresholds field trial.
   // - Desktop does not enforce a default memory threshold, but for now we
-  //   still support a threshold defined via a
-  //   kSitePerProcessOnlyForHighMemoryClients field trial.  The trial
-  //   typically carries the threshold in a param; if it doesn't, use a default
-  //   that's slightly higher than 1GB (see https://crbug.com/844118).
-  //
-  // TODO(alexmos): currently, this threshold applies to all site isolation
-  // modes.  Eventually, we may need separate thresholds for different modes,
-  // such as full site isolation vs. password-triggered site isolation.
+  //   still support a threshold defined via a kSiteIsolationMemoryThresholds
+  //   field trial.  The trial typically carries the threshold in a param; if
+  //   it doesn't, use a default that's slightly higher than 1GB (see
+  //   https://crbug.com/844118).
+  int default_memory_threshold_mb;
 #if defined(OS_ANDROID)
-  constexpr int kDefaultMemoryThresholdMb = 1900;
+  if (site_isolation_mode == content::SiteIsolationMode::kStrictSiteIsolation) {
+    default_memory_threshold_mb = 3200;
+  } else {
+    default_memory_threshold_mb = 1900;
+  }
 #else
-  constexpr int kDefaultMemoryThresholdMb = 1077;
+  default_memory_threshold_mb = 1077;
 #endif
 
-  // TODO(acolwell): Rename feature since it now affects more than just the
-  // site-per-process case.
-  if (base::FeatureList::IsEnabled(
-          features::kSitePerProcessOnlyForHighMemoryClients)) {
+  if (base::FeatureList::IsEnabled(features::kSiteIsolationMemoryThresholds)) {
+    std::string param_name;
+    switch (site_isolation_mode) {
+      case content::SiteIsolationMode::kStrictSiteIsolation:
+        param_name = features::kStrictSiteIsolationMemoryThresholdParamName;
+        break;
+      case content::SiteIsolationMode::kPartialSiteIsolation:
+        param_name = features::kPartialSiteIsolationMemoryThresholdParamName;
+        break;
+    }
     int memory_threshold_mb = base::GetFieldTrialParamByFeatureAsInt(
-        features::kSitePerProcessOnlyForHighMemoryClients,
-        features::kSitePerProcessOnlyForHighMemoryClientsParamName,
-        kDefaultMemoryThresholdMb);
+        features::kSiteIsolationMemoryThresholds, param_name,
+        default_memory_threshold_mb);
     return base::SysInfo::AmountOfPhysicalMemoryMB() <= memory_threshold_mb;
   }
 
 #if defined(OS_ANDROID)
-  if (base::SysInfo::AmountOfPhysicalMemoryMB() <= kDefaultMemoryThresholdMb) {
+  if (base::SysInfo::AmountOfPhysicalMemoryMB() <=
+      default_memory_threshold_mb) {
     return true;
   }
 #endif
diff --git a/components/site_isolation/site_isolation_policy.h b/components/site_isolation/site_isolation_policy.h
index 55e1312..361a367 100644
--- a/components/site_isolation/site_isolation_policy.h
+++ b/components/site_isolation/site_isolation_policy.h
@@ -13,6 +13,7 @@
 class GURL;
 
 namespace content {
+enum class SiteIsolationMode;
 class BrowserContext;
 }
 
@@ -74,13 +75,12 @@
                                  const GURL& signed_in_url);
 
   // Determines whether Site Isolation should be disabled because the device
-  // does not have the minimum required amount of memory.
-  //
-  // TODO(alexmos): Currently, the memory threshold is shared for all site
-  // isolation modes, including strict site isolation and password site
-  // isolation.  In the future, some site isolation modes may require their own
-  // memory threshold.
-  static bool ShouldDisableSiteIsolationDueToMemoryThreshold();
+  // does not have the minimum required amount of memory. `site_isolation_mode`
+  // determines the type of memory threshold to apply; for example, strict site
+  // isolation on Android might require a higher memory threshold than partial
+  // site isolation.
+  static bool ShouldDisableSiteIsolationDueToMemoryThreshold(
+      content::SiteIsolationMode site_isolation_mode);
 
   // Returns true if the PDF compositor should be enabled to allow out-of-
   // process iframes (OOPIF's) to print properly.
diff --git a/components/site_isolation/site_isolation_policy_unittest.cc b/components/site_isolation/site_isolation_policy_unittest.cc
index 5dc99613..2ded9d54 100644
--- a/components/site_isolation/site_isolation_policy_unittest.cc
+++ b/components/site_isolation/site_isolation_policy_unittest.cc
@@ -86,9 +86,10 @@
       return strict_isolation_enabled_;
     }
 
-    bool ShouldDisableSiteIsolation() override {
+    bool ShouldDisableSiteIsolation(
+        content::SiteIsolationMode site_isolation_mode) override {
       return SiteIsolationPolicy::
-          ShouldDisableSiteIsolationDueToMemoryThreshold();
+          ShouldDisableSiteIsolationDueToMemoryThreshold(site_isolation_mode);
     }
 
     std::vector<url::Origin> GetOriginsRequiringDedicatedProcess() override {
@@ -170,9 +171,9 @@
     // threshold.  To ensure that COOP isolation is also enabled on those
     // machines, set a very low 128MB threshold.
     base::test::ScopedFeatureList::FeatureAndParams memory_threshold_feature = {
-        site_isolation::features::kSitePerProcessOnlyForHighMemoryClients,
+        site_isolation::features::kSiteIsolationMemoryThresholds,
         {{site_isolation::features::
-              kSitePerProcessOnlyForHighMemoryClientsParamName,
+              kPartialSiteIsolationMemoryThresholdParamName,
           "128"}}};
 
     feature_list_.InitWithFeaturesAndParameters(
@@ -459,20 +460,25 @@
           SitePerProcessMemoryThresholdBrowserTestParams> {
  public:
   SitePerProcessMemoryThresholdBrowserTest() {
+    // When a memory threshold is specified, set it for both strict site
+    // isolation and partial site isolation modes, since these tests care about
+    // both. For example, UseDedicatedProcessesForAllSites() depends on the
+    // former, while isolated origins specified via field trials use the
+    // latter.
     switch (GetParam().threshold) {
       case SitePerProcessMemoryThreshold::kNone:
         break;
       case SitePerProcessMemoryThreshold::k128MB:
         threshold_feature_.InitAndEnableFeatureWithParameters(
-            features::kSitePerProcessOnlyForHighMemoryClients,
-            {{features::kSitePerProcessOnlyForHighMemoryClientsParamName,
-              "128"}});
+            features::kSiteIsolationMemoryThresholds,
+            {{features::kStrictSiteIsolationMemoryThresholdParamName, "128"},
+             {features::kPartialSiteIsolationMemoryThresholdParamName, "128"}});
         break;
       case SitePerProcessMemoryThreshold::k768MB:
         threshold_feature_.InitAndEnableFeatureWithParameters(
-            features::kSitePerProcessOnlyForHighMemoryClients,
-            {{features::kSitePerProcessOnlyForHighMemoryClientsParamName,
-              "768"}});
+            features::kSiteIsolationMemoryThresholds,
+            {{features::kStrictSiteIsolationMemoryThresholdParamName, "768"},
+             {features::kPartialSiteIsolationMemoryThresholdParamName, "768"}});
         break;
     }
 
@@ -752,8 +758,8 @@
   // now be disabled.
   base::test::ScopedFeatureList memory_feature;
   memory_feature.InitAndEnableFeatureWithParameters(
-      features::kSitePerProcessOnlyForHighMemoryClients,
-      {{features::kSitePerProcessOnlyForHighMemoryClientsParamName, "768"}});
+      features::kSiteIsolationMemoryThresholds,
+      {{features::kPartialSiteIsolationMemoryThresholdParamName, "768"}});
 
   EXPECT_FALSE(SiteIsolationPolicy::IsIsolationForPasswordSitesEnabled());
 
@@ -789,8 +795,8 @@
   // still be enabled.
   base::test::ScopedFeatureList memory_feature;
   memory_feature.InitAndEnableFeatureWithParameters(
-      features::kSitePerProcessOnlyForHighMemoryClients,
-      {{features::kSitePerProcessOnlyForHighMemoryClientsParamName, "128"}});
+      features::kSiteIsolationMemoryThresholds,
+      {{features::kPartialSiteIsolationMemoryThresholdParamName, "128"}});
 
   EXPECT_TRUE(SiteIsolationPolicy::IsIsolationForPasswordSitesEnabled());
 
@@ -834,8 +840,8 @@
   // this feature via command line.
   base::test::ScopedFeatureList memory_feature;
   memory_feature.InitAndEnableFeatureWithParameters(
-      features::kSitePerProcessOnlyForHighMemoryClients,
-      {{features::kSitePerProcessOnlyForHighMemoryClientsParamName, "768"}});
+      features::kSiteIsolationMemoryThresholds,
+      {{features::kPartialSiteIsolationMemoryThresholdParamName, "768"}});
 
   EXPECT_TRUE(SiteIsolationPolicy::IsIsolationForPasswordSitesEnabled());
 }
@@ -859,8 +865,8 @@
 
   base::test::ScopedFeatureList memory_feature;
   memory_feature.InitAndEnableFeatureWithParameters(
-      features::kSitePerProcessOnlyForHighMemoryClients,
-      {{features::kSitePerProcessOnlyForHighMemoryClientsParamName, "128"}});
+      features::kSiteIsolationMemoryThresholds,
+      {{features::kPartialSiteIsolationMemoryThresholdParamName, "128"}});
 
   EXPECT_TRUE(SiteIsolationPolicy::IsIsolationForPasswordSitesEnabled());
 }
@@ -958,8 +964,8 @@
   // still be enabled.
   base::test::ScopedFeatureList memory_feature;
   memory_feature.InitAndEnableFeatureWithParameters(
-      features::kSitePerProcessOnlyForHighMemoryClients,
-      {{features::kSitePerProcessOnlyForHighMemoryClientsParamName, "128"}});
+      features::kSiteIsolationMemoryThresholds,
+      {{features::kStrictSiteIsolationMemoryThresholdParamName, "128"}});
   EXPECT_TRUE(content::SiteIsolationPolicy::IsStrictOriginIsolationEnabled());
 
   // Simulate disabling strict origin isolation from command line.  (Note that
@@ -1001,8 +1007,8 @@
   // this feature via command line.
   base::test::ScopedFeatureList memory_feature;
   memory_feature.InitAndEnableFeatureWithParameters(
-      features::kSitePerProcessOnlyForHighMemoryClients,
-      {{features::kSitePerProcessOnlyForHighMemoryClientsParamName, "768"}});
+      features::kSiteIsolationMemoryThresholds,
+      {{features::kStrictSiteIsolationMemoryThresholdParamName, "768"}});
 
   EXPECT_TRUE(content::SiteIsolationPolicy::IsStrictOriginIsolationEnabled());
 }
@@ -1038,8 +1044,8 @@
   // effect.
   base::test::ScopedFeatureList memory_feature;
   memory_feature.InitAndEnableFeatureWithParameters(
-      features::kSitePerProcessOnlyForHighMemoryClients,
-      {{features::kSitePerProcessOnlyForHighMemoryClientsParamName, "128"}});
+      features::kSiteIsolationMemoryThresholds,
+      {{features::kPartialSiteIsolationMemoryThresholdParamName, "128"}});
 
   // Ensure that isolated origins that are normally loaded on browser
   // startup are applied.
@@ -1080,8 +1086,8 @@
   // take effect.
   base::test::ScopedFeatureList memory_feature;
   memory_feature.InitAndEnableFeatureWithParameters(
-      features::kSitePerProcessOnlyForHighMemoryClients,
-      {{features::kSitePerProcessOnlyForHighMemoryClientsParamName, "768"}});
+      features::kSiteIsolationMemoryThresholds,
+      {{features::kPartialSiteIsolationMemoryThresholdParamName, "768"}});
 
   // Ensure that isolated origins that are normally loaded on browser
   // startup are applied.
@@ -1112,8 +1118,8 @@
   // be disabled by the memory threshold.
   base::test::ScopedFeatureList memory_feature;
   memory_feature.InitAndEnableFeatureWithParameters(
-      features::kSitePerProcessOnlyForHighMemoryClients,
-      {{features::kSitePerProcessOnlyForHighMemoryClientsParamName, "128"}});
+      features::kSiteIsolationMemoryThresholds,
+      {{features::kPartialSiteIsolationMemoryThresholdParamName, "128"}});
 
   // Ensure that isolated origins that are normally loaded on browser
   // startup are applied.
@@ -1177,8 +1183,8 @@
   // should still take effect.
   base::test::ScopedFeatureList memory_feature;
   memory_feature.InitAndEnableFeatureWithParameters(
-      features::kSitePerProcessOnlyForHighMemoryClients,
-      {{features::kSitePerProcessOnlyForHighMemoryClientsParamName, "768"}});
+      features::kSiteIsolationMemoryThresholds,
+      {{features::kPartialSiteIsolationMemoryThresholdParamName, "768"}});
 
   EXPECT_FALSE(content::SiteIsolationPolicy::
                    IsProcessIsolationForOriginAgentClusterEnabled());
@@ -1227,8 +1233,8 @@
   // enabled.
   base::test::ScopedFeatureList memory_feature;
   memory_feature.InitAndEnableFeatureWithParameters(
-      features::kSitePerProcessOnlyForHighMemoryClients,
-      {{features::kSitePerProcessOnlyForHighMemoryClientsParamName, "128"}});
+      features::kSiteIsolationMemoryThresholds,
+      {{features::kPartialSiteIsolationMemoryThresholdParamName, "128"}});
 
   EXPECT_TRUE(content::SiteIsolationPolicy::
                   IsProcessIsolationForOriginAgentClusterEnabled());
diff --git a/components/vector_icons/BUILD.gn b/components/vector_icons/BUILD.gn
index 1d09028..c404a2c1 100644
--- a/components/vector_icons/BUILD.gn
+++ b/components/vector_icons/BUILD.gn
@@ -92,6 +92,7 @@
     "sensors.icon",
     "serial_port.icon",
     "settings.icon",
+    "sms.icon",
     "submenu_arrow.icon",
     "sync.icon",
     "troubleshoot.icon",
diff --git a/components/vector_icons/sms.icon b/components/vector_icons/sms.icon
new file mode 100644
index 0000000..a668ddc
--- /dev/null
+++ b/components/vector_icons/sms.icon
@@ -0,0 +1,37 @@
+// 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.
+
+CANVAS_DIMENSIONS, 24,
+MOVE_TO, 20, 2,
+H_LINE_TO, 4,
+R_CUBIC_TO, -1.1f, 0, -2, 0.9f, -2, 2,
+R_V_LINE_TO, 18,
+R_LINE_TO, 4, -4,
+R_H_LINE_TO, 14,
+R_CUBIC_TO, 1.1f, 0, 2, -0.9f, 2, -2,
+V_LINE_TO, 4,
+R_CUBIC_TO, 0, -1.1f, -0.9f, -2, -2, -2,
+CLOSE,
+R_MOVE_TO, 0, 14,
+H_LINE_TO, 6,
+R_LINE_TO, -2, 2,
+V_LINE_TO, 4,
+R_H_LINE_TO, 16,
+R_V_LINE_TO, 12,
+CLOSE,
+MOVE_TO, 7, 9,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, 2,
+H_LINE_TO, 7,
+CLOSE,
+R_MOVE_TO, 4, 0,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, 2,
+R_H_LINE_TO, -2,
+CLOSE,
+R_MOVE_TO, 4, 0,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, 2,
+R_H_LINE_TO, -2,
+CLOSE
\ No newline at end of file
diff --git a/components/winhttp/BUILD.gn b/components/winhttp/BUILD.gn
new file mode 100644
index 0000000..2d3b83e
--- /dev/null
+++ b/components/winhttp/BUILD.gn
@@ -0,0 +1,50 @@
+# 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.
+
+static_library("winhttp") {
+  friend = [ ":unit_tests" ]
+
+  public = [
+    "network_fetcher.h",
+    "proxy_configuration.h",
+    "proxy_info.h",
+    "scoped_hinternet.h",
+  ]
+
+  sources = [
+    "net_util.cc",
+    "net_util.h",
+    "network_fetcher.cc",
+    "proxy_configuration.cc",
+    "proxy_info.cc",
+    "scoped_hinternet.cc",
+    "scoped_winttp_proxy_info.h",
+  ]
+
+  public_deps = [
+    "//base",
+    "//third_party/abseil-cpp:absl",
+    "//url",
+  ]
+
+  defines = [ "SECURITY_WIN32" ]
+
+  libs = [ "winhttp.lib" ]
+}
+
+source_set("unit_tests") {
+  testonly = true
+  sources = [
+    "net_util_unittest.cc",
+    "proxy_configuration_unittest.cc",
+    "proxy_info_unittest.cc",
+  ]
+
+  deps = [
+    ":winhttp",
+    "//base",
+    "//base/test:test_support",
+    "//testing/gtest",
+  ]
+}
diff --git a/components/winhttp/DIR_METADATA b/components/winhttp/DIR_METADATA
new file mode 100644
index 0000000..e4f369d8
--- /dev/null
+++ b/components/winhttp/DIR_METADATA
@@ -0,0 +1,5 @@
+monorail {
+  component: "Internals>Updater"
+}
+
+team_email: "chrome-updates-dev@chromium.org"
diff --git a/components/winhttp/OWNERS b/components/winhttp/OWNERS
new file mode 100644
index 0000000..feb97cb
--- /dev/null
+++ b/components/winhttp/OWNERS
@@ -0,0 +1,3 @@
+rogerta@chromium.org
+sorin@chromium.org
+waffles@chromium.org
diff --git a/components/winhttp/README.md b/components/winhttp/README.md
new file mode 100644
index 0000000..de576e0
--- /dev/null
+++ b/components/winhttp/README.md
@@ -0,0 +1,9 @@
+//components/winhttp
+
+This component is a wrapper around the Microsoft Windows WinHTTP API.  This
+component is meant to be used in contexts where Chrome's regular network stack
+is not available, like in the Chrome updater and installer.
+
+This component is designed to have minimal dependencies.  For the moment, it
+depends only on //base and //url.  It's not anticipated that more dependencies
+will be required.  To keep things simple, new dependencies are not desired.
diff --git a/chrome/updater/win/net/net_util.cc b/components/winhttp/net_util.cc
similarity index 86%
rename from chrome/updater/win/net/net_util.cc
rename to components/winhttp/net_util.cc
index be12860..29e0c0f 100644
--- a/chrome/updater/win/net/net_util.cc
+++ b/components/winhttp/net_util.cc
@@ -2,11 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/updater/win/net/net_util.h"
+#include "components/winhttp/net_util.h"
 
 #include <vector>
 
-namespace updater {
+namespace winhttp {
+
+HRESULT HRESULTFromLastError() {
+  const auto error_code = ::GetLastError();
+  return (error_code != NO_ERROR) ? HRESULT_FROM_WIN32(error_code) : E_FAIL;
+}
 
 HRESULT QueryHeadersString(HINTERNET request_handle,
                            uint32_t info_level,
@@ -44,4 +49,4 @@
   return S_OK;
 }
 
-}  // namespace updater
+}  // namespace winhttp
diff --git a/chrome/updater/win/net/net_util.h b/components/winhttp/net_util.h
similarity index 69%
rename from chrome/updater/win/net/net_util.h
rename to components/winhttp/net_util.h
index 46e4faa..450c4e2 100644
--- a/chrome/updater/win/net/net_util.h
+++ b/components/winhttp/net_util.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_UPDATER_WIN_NET_NET_UTIL_H_
-#define CHROME_UPDATER_WIN_NET_NET_UTIL_H_
+#ifndef COMPONENTS_WINHTTP_NET_UTIL_H_
+#define COMPONENTS_WINHTTP_NET_UTIL_H_
 
 #include <windows.h>
 #include <winhttp.h>
@@ -13,15 +13,22 @@
 #include <string>
 
 #include "base/check_op.h"
-#include "chrome/updater/win/win_util.h"
 
-namespace updater {
+namespace winhttp {
 
+// Returns the last error as an HRESULT or E_FAIL if last error is NO_ERROR.
+// This is not a drop in replacement for the HRESULT_FROM_WIN32 macro.
+// The macro maps a NO_ERROR to S_OK, whereas the HRESULTFromLastError maps a
+// NO_ERROR to E_FAIL.
+HRESULT HRESULTFromLastError();
+
+// Returns HTTP response headers from the given request as strings.
 HRESULT QueryHeadersString(HINTERNET request_handle,
                            uint32_t info_level,
                            const wchar_t* name,
                            std::wstring* value);
 
+// Returns HTTP response headers from the given request as integers.
 HRESULT QueryHeadersInt(HINTERNET request_handle,
                         uint32_t info_level,
                         const wchar_t* name,
@@ -48,6 +55,6 @@
   return S_OK;
 }
 
-}  // namespace updater
+}  // namespace winhttp
 
-#endif  // CHROME_UPDATER_WIN_NET_NET_UTIL_H_
+#endif  // COMPONENTS_WINHTTP_NET_UTIL_H_
diff --git a/components/winhttp/net_util_unittest.cc b/components/winhttp/net_util_unittest.cc
new file mode 100644
index 0000000..297a97f
--- /dev/null
+++ b/components/winhttp/net_util_unittest.cc
@@ -0,0 +1,17 @@
+// Copyright 2019 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 "components/winhttp/net_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace winhttp {
+
+TEST(WinHttpUtil, HRESULTFromLastError) {
+  ::SetLastError(ERROR_ACCESS_DENIED);
+  EXPECT_EQ(E_ACCESSDENIED, HRESULTFromLastError());
+  ::SetLastError(ERROR_SUCCESS);
+  EXPECT_EQ(E_FAIL, HRESULTFromLastError());
+}
+
+}  // namespace winhttp
diff --git a/chrome/updater/win/net/network_winhttp.cc b/components/winhttp/network_fetcher.cc
similarity index 74%
rename from chrome/updater/win/net/network_winhttp.cc
rename to components/winhttp/network_fetcher.cc
index 1f93054..5fd6d6ba 100644
--- a/chrome/updater/win/net/network_winhttp.cc
+++ b/components/winhttp/network_fetcher.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/updater/win/net/network_winhttp.h"
+#include "components/winhttp/network_fetcher.h"
 
 #include <limits>
 #include <string>
@@ -24,15 +24,13 @@
 #include "base/task/thread_pool.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/win/windows_version.h"
-#include "chrome/updater/win/net/net_util.h"
-#include "chrome/updater/win/net/network.h"
-#include "chrome/updater/win/net/proxy_info.h"
-#include "chrome/updater/win/net/scoped_hinternet.h"
-#include "chrome/updater/win/net/scoped_winttp_proxy_info.h"
-#include "chrome/updater/win/win_util.h"
+#include "components/winhttp/net_util.h"
+#include "components/winhttp/proxy_info.h"
+#include "components/winhttp/scoped_hinternet.h"
+#include "components/winhttp/scoped_winttp_proxy_info.h"
 #include "url/url_constants.h"
 
-namespace updater {
+namespace winhttp {
 
 namespace {
 
@@ -57,25 +55,25 @@
 
 }  // namespace
 
-NetworkFetcherWinHTTP::NetworkFetcherWinHTTP(
+NetworkFetcher::NetworkFetcher(
     const HINTERNET& session_handle,
     scoped_refptr<ProxyConfiguration> proxy_configuration)
     : main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()),
       session_handle_(session_handle),
       proxy_configuration_(proxy_configuration) {}
 
-NetworkFetcherWinHTTP::~NetworkFetcherWinHTTP() {
-  DVLOG(3) << "~NetworkFetcherWinHTTP";
+NetworkFetcher::~NetworkFetcher() {
+  DVLOG(3) << "~NetworkFetcher";
 }
 
-void NetworkFetcherWinHTTP::Close() {
+void NetworkFetcher::Close() {
   // |write_data_callback_| maintains an outstanding reference to this object
   // and the reference must be released to avoid leaking the object.
   write_data_callback_.Reset();
   request_handle_.reset();
 }
 
-void NetworkFetcherWinHTTP::CompleteFetch() {
+void NetworkFetcher::CompleteFetch() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (!file_.IsValid()) {
     std::move(fetch_complete_callback_).Run();
@@ -84,45 +82,42 @@
   base::ThreadPool::PostTaskAndReply(
       FROM_HERE, kTaskTraits,
       base::BindOnce([](base::File& file) { file.Close(); }, std::ref(file_)),
-      base::BindOnce(&NetworkFetcherWinHTTP::CompleteFetch, this));
+      base::BindOnce(&NetworkFetcher::CompleteFetch, this));
 }
 
-std::string NetworkFetcherWinHTTP::GetResponseBody() const {
+HRESULT NetworkFetcher::QueryHeaderString(const std::wstring& name,
+                                          std::wstring* value) const {
+  return QueryHeadersString(request_handle_.get(), WINHTTP_QUERY_CUSTOM,
+                            name.c_str(), value);
+}
+
+HRESULT NetworkFetcher::QueryHeaderInt(const std::wstring& name,
+                                       int* value) const {
+  return QueryHeadersInt(request_handle_.get(), WINHTTP_QUERY_CUSTOM,
+                         name.c_str(), value);
+}
+
+std::string NetworkFetcher::GetResponseBody() const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return post_response_body_;
 }
 
-HRESULT NetworkFetcherWinHTTP::GetNetError() const {
+HRESULT NetworkFetcher::GetNetError() const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return net_error_;
 }
 
-std::string NetworkFetcherWinHTTP::GetHeaderETag() const {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  return header_etag_;
-}
-
-std::string NetworkFetcherWinHTTP::GetHeaderXCupServerProof() const {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  return header_x_cup_server_proof_;
-}
-
-int64_t NetworkFetcherWinHTTP::GetHeaderXRetryAfterSec() const {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  return header_x_retry_after_sec_;
-}
-
-base::FilePath NetworkFetcherWinHTTP::GetFilePath() const {
+base::FilePath NetworkFetcher::GetFilePath() const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return file_path_;
 }
 
-int64_t NetworkFetcherWinHTTP::GetContentSize() const {
+int64_t NetworkFetcher::GetContentSize() const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return content_size_;
 }
 
-void NetworkFetcherWinHTTP::PostRequest(
+void NetworkFetcher::PostRequest(
     const GURL& url,
     const std::string& post_data,
     const std::string& content_type,
@@ -143,7 +138,7 @@
   verb_ = L"POST";
   content_type_ = content_type;
   write_data_callback_ =
-      base::BindRepeating(&NetworkFetcherWinHTTP::WriteDataToMemory, this);
+      base::BindRepeating(&NetworkFetcher::WriteDataToMemory, this);
 
   net_error_ = BeginFetch(post_data, post_additional_headers);
 
@@ -151,7 +146,7 @@
     CompleteFetch();
 }
 
-void NetworkFetcherWinHTTP::DownloadToFile(
+void NetworkFetcher::DownloadToFile(
     const GURL& url,
     const base::FilePath& file_path,
     FetchStartedCallback fetch_started_callback,
@@ -170,7 +165,7 @@
 
   verb_ = L"GET";
   write_data_callback_ =
-      base::BindRepeating(&NetworkFetcherWinHTTP::WriteDataToFile, this);
+      base::BindRepeating(&NetworkFetcher::WriteDataToFile, this);
 
   net_error_ = BeginFetch({}, {});
 
@@ -178,7 +173,7 @@
     CompleteFetch();
 }
 
-HRESULT NetworkFetcherWinHTTP::BeginFetch(
+HRESULT NetworkFetcher::BeginFetch(
     const std::string& data,
     base::flat_map<std::string, std::string> additional_headers) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -197,7 +192,7 @@
   SetProxyForRequest(request_handle_.get(), winhttp_proxy_info);
 
   const auto winhttp_callback = ::WinHttpSetStatusCallback(
-      request_handle_.get(), &NetworkFetcherWinHTTP::WinHttpStatusCallback,
+      request_handle_.get(), &NetworkFetcher::WinHttpStatusCallback,
       WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, 0);
   if (winhttp_callback == WINHTTP_INVALID_STATUS_CALLBACK)
     return HRESULTFromLastError();
@@ -235,24 +230,24 @@
   return S_OK;
 }
 
-scoped_hinternet NetworkFetcherWinHTTP::Connect() {
+ScopedHInternet NetworkFetcher::Connect() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  return scoped_hinternet(::WinHttpConnect(
+  return ScopedHInternet(::WinHttpConnect(
       session_handle_, base::SysUTF8ToWide(host_).c_str(), port_, 0));
 }
 
-scoped_hinternet NetworkFetcherWinHTTP::OpenRequest() {
+ScopedHInternet NetworkFetcher::OpenRequest() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   uint32_t flags = WINHTTP_FLAG_REFRESH;
   if (is_https_)
     flags |= WINHTTP_FLAG_SECURE;
-  return scoped_hinternet(::WinHttpOpenRequest(
+  return ScopedHInternet(::WinHttpOpenRequest(
       connect_handle_.get(), verb_.data(),
       base::SysUTF8ToWide(path_for_request_).c_str(), nullptr,
       WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, flags));
 }
 
-HRESULT NetworkFetcherWinHTTP::SendRequest(const std::string& data) {
+HRESULT NetworkFetcher::SendRequest(const std::string& data) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   VLOG(2) << data;
@@ -269,7 +264,7 @@
   return S_OK;
 }
 
-void NetworkFetcherWinHTTP::SendRequestComplete() {
+void NetworkFetcher::SendRequestComplete() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   std::wstring all;
@@ -284,14 +279,14 @@
     CompleteFetch();
 }
 
-HRESULT NetworkFetcherWinHTTP::ReceiveResponse() {
+HRESULT NetworkFetcher::ReceiveResponse() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (!::WinHttpReceiveResponse(request_handle_.get(), nullptr))
     return HRESULTFromLastError();
   return S_OK;
 }
 
-void NetworkFetcherWinHTTP::HeadersAvailable() {
+void NetworkFetcher::HeadersAvailable() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   std::wstring all;
@@ -316,31 +311,6 @@
     return;
   }
 
-  std::wstring etag;
-  if (SUCCEEDED(QueryHeadersString(request_handle_.get(), WINHTTP_QUERY_ETAG,
-                                   WINHTTP_HEADER_NAME_BY_INDEX, &etag))) {
-    header_etag_ = base::SysWideToUTF8(etag);
-  }
-
-  std::wstring xheader_cup_server_proof;
-  if (SUCCEEDED(QueryHeadersString(
-          request_handle_.get(), WINHTTP_QUERY_CUSTOM,
-          base::SysUTF8ToWide(
-              update_client::NetworkFetcher::kHeaderXCupServerProof)
-              .c_str(),
-          &xheader_cup_server_proof))) {
-    header_x_cup_server_proof_ = base::SysWideToUTF8(xheader_cup_server_proof);
-  }
-
-  int xheader_retry_after_sec = 0;
-  if (SUCCEEDED(QueryHeadersInt(
-          request_handle_.get(), WINHTTP_QUERY_CUSTOM,
-          base::SysUTF8ToWide(update_client::NetworkFetcher::kHeaderXRetryAfter)
-              .c_str(),
-          &xheader_retry_after_sec))) {
-    header_x_retry_after_sec_ = xheader_retry_after_sec;
-  }
-
   std::move(fetch_started_callback_).Run(response_code, content_length);
 
   // Start reading the body of response.
@@ -349,7 +319,7 @@
     CompleteFetch();
 }
 
-HRESULT NetworkFetcherWinHTTP::ReadData() {
+HRESULT NetworkFetcher::ReadData() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // Use a fixed buffer size, larger than the internal WinHTTP buffer size (8K),
@@ -366,28 +336,28 @@
   return S_OK;
 }
 
-void NetworkFetcherWinHTTP::ReadDataComplete(size_t num_bytes_read) {
+void NetworkFetcher::ReadDataComplete(size_t num_bytes_read) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   read_buffer_.resize(num_bytes_read);
   write_data_callback_.Run();
 }
 
-void NetworkFetcherWinHTTP::RequestError(const WINHTTP_ASYNC_RESULT* result) {
+void NetworkFetcher::RequestError(const WINHTTP_ASYNC_RESULT* result) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  net_error_ = HRESULTFromUpdaterError(result->dwError);
+  net_error_ = HRESULT_FROM_WIN32(result->dwError);
   CompleteFetch();
 }
 
-void NetworkFetcherWinHTTP::WriteDataToFile() {
+void NetworkFetcher::WriteDataToFile() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   base::ThreadPool::PostTaskAndReplyWithResult(
       FROM_HERE, kTaskTraits,
-      base::BindOnce(&NetworkFetcherWinHTTP::WriteDataToFileBlocking, this),
-      base::BindOnce(&NetworkFetcherWinHTTP::WriteDataToFileComplete, this));
+      base::BindOnce(&NetworkFetcher::WriteDataToFileBlocking, this),
+      base::BindOnce(&NetworkFetcher::WriteDataToFileComplete, this));
 }
 
 // Returns true if EOF is reached.
-bool NetworkFetcherWinHTTP::WriteDataToFileBlocking() {
+bool NetworkFetcher::WriteDataToFileBlocking() {
   if (read_buffer_.empty()) {
     file_.Close();
     net_error_ = S_OK;
@@ -399,7 +369,7 @@
                                      base::File::Flags::FLAG_WRITE |
                                      base::File::Flags::FLAG_SEQUENTIAL_SCAN);
     if (!file_.IsValid()) {
-      net_error_ = HRESULTFromUpdaterError(file_.error_details());
+      net_error_ = HRESULTFromLastError();
       return false;
     }
   }
@@ -407,7 +377,7 @@
   DCHECK(file_.IsValid());
   if (file_.WriteAtCurrentPos(&read_buffer_.front(), read_buffer_.size()) ==
       -1) {
-    net_error_ = HRESULTFromUpdaterError(base::File::GetLastFileError());
+    net_error_ = HRESULTFromLastError();
     file_.Close();
     base::DeleteFile(file_path_);
     return false;
@@ -417,7 +387,7 @@
   return false;
 }
 
-void NetworkFetcherWinHTTP::WriteDataToFileComplete(bool is_eof) {
+void NetworkFetcher::WriteDataToFileComplete(bool is_eof) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   fetch_progress_callback_.Run(base::saturated_cast<int64_t>(content_size_));
@@ -432,7 +402,7 @@
     CompleteFetch();
 }
 
-void NetworkFetcherWinHTTP::WriteDataToMemory() {
+void NetworkFetcher::WriteDataToMemory() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (read_buffer_.empty()) {
@@ -451,25 +421,24 @@
     CompleteFetch();
 }
 
-void __stdcall NetworkFetcherWinHTTP::WinHttpStatusCallback(HINTERNET handle,
-                                                            DWORD_PTR context,
-                                                            DWORD status,
-                                                            void* info,
-                                                            DWORD info_len) {
+void __stdcall NetworkFetcher::WinHttpStatusCallback(HINTERNET handle,
+                                                     DWORD_PTR context,
+                                                     DWORD status,
+                                                     void* info,
+                                                     DWORD info_len) {
   DCHECK(handle);
   DCHECK(context);
-  NetworkFetcherWinHTTP* network_fetcher =
-      reinterpret_cast<NetworkFetcherWinHTTP*>(context);
+  NetworkFetcher* network_fetcher = reinterpret_cast<NetworkFetcher*>(context);
   network_fetcher->main_thread_task_runner_->PostTask(
       FROM_HERE,
-      base::BindOnce(&NetworkFetcherWinHTTP::StatusCallback, network_fetcher,
-                     handle, status, info, info_len));
+      base::BindOnce(&NetworkFetcher::StatusCallback, network_fetcher, handle,
+                     status, info, info_len));
 }
 
-void NetworkFetcherWinHTTP::StatusCallback(HINTERNET handle,
-                                           uint32_t status,
-                                           void* info,
-                                           uint32_t info_len) {
+void NetworkFetcher::StatusCallback(HINTERNET handle,
+                                    uint32_t status,
+                                    void* info,
+                                    uint32_t info_len) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   base::StringPiece status_string;
   std::wstring info_string;
@@ -580,4 +549,4 @@
   }
 }
 
-}  // namespace updater
+}  // namespace winhttp
diff --git a/chrome/updater/win/net/network_winhttp.h b/components/winhttp/network_fetcher.h
similarity index 71%
rename from chrome/updater/win/net/network_winhttp.h
rename to components/winhttp/network_fetcher.h
index 962d201..0265922 100644
--- a/chrome/updater/win/net/network_winhttp.h
+++ b/components/winhttp/network_fetcher.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_UPDATER_WIN_NET_NETWORK_WINHTTP_H_
-#define CHROME_UPDATER_WIN_NET_NETWORK_WINHTTP_H_
+#ifndef COMPONENTS_WINHTTP_NETWORK_FETCHER_H_
+#define COMPONENTS_WINHTTP_NETWORK_FETCHER_H_
 
 #include <windows.h>
 
@@ -14,36 +14,35 @@
 #include <vector>
 
 #include "base/callback.h"
+#include "base/containers/flat_map.h"
 #include "base/files/file.h"
 #include "base/files/file_path.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/sequence_checker.h"
 #include "base/strings/string_piece_forward.h"
-#include "chrome/updater/win/net/proxy_configuration.h"
-#include "chrome/updater/win/net/scoped_hinternet.h"
-#include "components/update_client/network.h"
+#include "components/winhttp/proxy_configuration.h"
+#include "components/winhttp/scoped_hinternet.h"
 #include "url/gurl.h"
 
 namespace base {
 class SingleThreadTaskRunner;
 }
 
-namespace updater {
+namespace winhttp {
 
 // Implements a network fetcher in terms of WinHTTP. The class is ref-counted
 // as it is accessed from the main thread and the worker threads in WinHTTP.
-class NetworkFetcherWinHTTP
-    : public base::RefCountedThreadSafe<NetworkFetcherWinHTTP> {
+class NetworkFetcher : public base::RefCountedThreadSafe<NetworkFetcher> {
  public:
   using FetchCompleteCallback = base::OnceCallback<void()>;
   using FetchStartedCallback =
-      update_client::NetworkFetcher::ResponseStartedCallback;
-  using FetchProgressCallback = update_client::NetworkFetcher::ProgressCallback;
+      base::OnceCallback<void(int response_code, int64_t content_length)>;
+  using FetchProgressCallback = base::RepeatingCallback<void(int64_t current)>;
 
-  NetworkFetcherWinHTTP(const HINTERNET& session_handle,
-                        scoped_refptr<ProxyConfiguration> proxy_configuration);
-  NetworkFetcherWinHTTP(const NetworkFetcherWinHTTP&) = delete;
-  NetworkFetcherWinHTTP& operator=(const NetworkFetcherWinHTTP&) = delete;
+  NetworkFetcher(const HINTERNET& session_handle,
+                 scoped_refptr<ProxyConfiguration> proxy_configuration);
+  NetworkFetcher(const NetworkFetcher&) = delete;
+  NetworkFetcher& operator=(const NetworkFetcher&) = delete;
 
   void Close();
 
@@ -65,11 +64,11 @@
                       FetchProgressCallback fetch_progress_callback,
                       FetchCompleteCallback fetch_complete_callback);
 
+  HRESULT QueryHeaderString(const std::wstring& name,
+                            std::wstring* value) const;
+  HRESULT QueryHeaderInt(const std::wstring& name, int* value) const;
   std::string GetResponseBody() const;
   HRESULT GetNetError() const;
-  std::string GetHeaderETag() const;
-  std::string GetHeaderXCupServerProof() const;
-  int64_t GetHeaderXRetryAfterSec() const;
   base::FilePath GetFilePath() const;
 
   // Returns the number of bytes retrieved from the network. This may be
@@ -77,10 +76,10 @@
   int64_t GetContentSize() const;
 
  private:
-  friend class base::RefCountedThreadSafe<NetworkFetcherWinHTTP>;
+  friend class base::RefCountedThreadSafe<NetworkFetcher>;
   using WriteDataCallback = base::RepeatingCallback<void()>;
 
-  ~NetworkFetcherWinHTTP();
+  ~NetworkFetcher();
 
   static void __stdcall WinHttpStatusCallback(HINTERNET handle,
                                               DWORD_PTR context,
@@ -98,8 +97,8 @@
   HRESULT BeginFetch(
       const std::string& data,
       base::flat_map<std::string, std::string> additional_headers);
-  scoped_hinternet Connect();
-  scoped_hinternet OpenRequest();
+  ScopedHInternet Connect();
+  ScopedHInternet OpenRequest();
   HRESULT SendRequest(const std::string& data);
   void SendRequestComplete();
   HRESULT ReceiveResponse();
@@ -117,15 +116,15 @@
   SEQUENCE_CHECKER(sequence_checker_);
   scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
 
-  const HINTERNET& session_handle_;  // Owned by NetworkFetcherWinHTTPFactory.
+  const HINTERNET& session_handle_;  // Owned by NetworkFetcherFactory.
   scoped_refptr<ProxyConfiguration> proxy_configuration_;
-  scoped_hinternet connect_handle_;
-  scoped_hinternet request_handle_;
+  ScopedHInternet connect_handle_;
+  ScopedHInternet request_handle_;
 
   // Keeps an outstanding reference count on itself as long as there is a
   // valid request handle and the context for the handle is set to this
   // instance.
-  scoped_refptr<NetworkFetcherWinHTTP> self_;
+  scoped_refptr<NetworkFetcher> self_;
 
   GURL url_;
   bool is_https_ = false;
@@ -138,9 +137,6 @@
   std::string content_type_;
   WriteDataCallback write_data_callback_;
   HRESULT net_error_ = S_OK;
-  std::string header_etag_;
-  std::string header_x_cup_server_proof_;
-  int64_t header_x_retry_after_sec_ = -1;
   std::vector<char> read_buffer_;
   std::string post_response_body_;
   base::FilePath file_path_;
@@ -150,10 +146,8 @@
   FetchStartedCallback fetch_started_callback_;
   FetchProgressCallback fetch_progress_callback_;
   FetchCompleteCallback fetch_complete_callback_;
-
-  scoped_refptr<update_client::NetworkFetcherFactory> network_fetcher_factory_;
 };
 
-}  // namespace updater
+}  // namespace winhttp
 
-#endif  // CHROME_UPDATER_WIN_NET_NETWORK_WINHTTP_H_
+#endif  // COMPONENTS_WINHTTP_NETWORK_FETCHER_H_
diff --git a/components/winhttp/proxy_configuration.cc b/components/winhttp/proxy_configuration.cc
new file mode 100644
index 0000000..eb3716c
--- /dev/null
+++ b/components/winhttp/proxy_configuration.cc
@@ -0,0 +1,124 @@
+// 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 "components/winhttp/proxy_configuration.h"
+
+#include "base/logging.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/strings/sys_string_conversions.h"
+#include "base/win/scoped_handle.h"
+#include "base/win/windows_version.h"
+#include "components/winhttp/net_util.h"
+#include "components/winhttp/proxy_info.h"
+#include "components/winhttp/scoped_winttp_proxy_info.h"
+#include "url/gurl.h"
+
+namespace winhttp {
+
+ProxyConfiguration::ProxyConfiguration(const ProxyInfo& proxy_info)
+    : proxy_info_(proxy_info) {}
+
+int ProxyConfiguration::access_type() const {
+  return DoGetAccessType();
+}
+
+int ProxyConfiguration::DoGetAccessType() const {
+  const bool is_using_named_proxy = !proxy_info_.auto_detect &&
+                                    proxy_info_.auto_config_url.empty() &&
+                                    !proxy_info_.proxy.empty();
+
+  return is_using_named_proxy ? WINHTTP_ACCESS_TYPE_NAMED_PROXY
+                              : WINHTTP_ACCESS_TYPE_DEFAULT_PROXY;
+}
+
+absl::optional<ScopedWinHttpProxyInfo> ProxyConfiguration::GetProxyForUrl(
+    HINTERNET session_handle,
+    const GURL& url) const {
+  return DoGetProxyForUrl(session_handle, url);
+}
+
+absl::optional<ScopedWinHttpProxyInfo> ProxyConfiguration::DoGetProxyForUrl(
+    HINTERNET session_handle,
+    const GURL& url) const {
+  // Detect proxy settings using Web Proxy Auto Detection (WPAD).
+  WINHTTP_AUTOPROXY_OPTIONS auto_proxy_options = {0};
+
+  // Per MSDN, setting fAutoLogonIfChallenged to false first may work
+  // if Windows cached the proxy config.
+  auto_proxy_options.fAutoLogonIfChallenged = false;
+
+  bool try_auto_proxy = false;
+
+  if (proxy_info_.auto_detect) {
+    auto_proxy_options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
+    auto_proxy_options.dwAutoDetectFlags =
+        WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A;
+    try_auto_proxy = true;
+  }
+
+  // PAC Url was specified, let system auto detect given the PAC url.
+  if (!proxy_info_.auto_config_url.empty()) {
+    auto_proxy_options.dwFlags |= WINHTTP_AUTOPROXY_CONFIG_URL;
+    auto_proxy_options.lpszAutoConfigUrl = proxy_info_.auto_config_url.c_str();
+    try_auto_proxy = true;
+  }
+
+  // Find the proxy server for the url.
+  ScopedWinHttpProxyInfo winhttp_proxy_info = {};
+  if (try_auto_proxy) {
+    const std::wstring url_str = base::SysUTF8ToWide(url.spec());
+    bool success = ::WinHttpGetProxyForUrl(session_handle, url_str.c_str(),
+                                           &auto_proxy_options,
+                                           winhttp_proxy_info.receive());
+    if (!success && ::GetLastError() == ERROR_WINHTTP_LOGIN_FAILURE) {
+      auto_proxy_options.fAutoLogonIfChallenged = true;
+      success = ::WinHttpGetProxyForUrl(session_handle, url_str.c_str(),
+                                        &auto_proxy_options,
+                                        winhttp_proxy_info.receive());
+    }
+
+    if (!success) {
+      PLOG(ERROR) << "Failed to get proxy for url";
+      return {};
+    }
+  } else {
+    winhttp_proxy_info.set_proxy(proxy_info_.proxy);
+    winhttp_proxy_info.set_proxy_bypass(proxy_info_.proxy_bypass);
+  }
+
+  if (!winhttp_proxy_info.IsValid())
+    return {};
+
+  return winhttp_proxy_info;
+}
+
+void SetProxyForRequest(
+    const HINTERNET request_handle,
+    const absl::optional<ScopedWinHttpProxyInfo>& winhttp_proxy_info) {
+  // Set the proxy option on the request handle.
+  if (winhttp_proxy_info.has_value() && winhttp_proxy_info.value().IsValid()) {
+    const ScopedWinHttpProxyInfo& proxy_info = winhttp_proxy_info.value();
+    VLOG(1) << "Setting proxy " << proxy_info.proxy();
+    auto hr = SetOption(request_handle, WINHTTP_OPTION_PROXY,
+                        const_cast<WINHTTP_PROXY_INFO*>(proxy_info.get()));
+    if (FAILED(hr)) {
+      PLOG(ERROR) << "Failed to set WINHTTP_OPTION_PROXY: 0x" << std::hex << hr;
+    }
+  }
+}
+
+int AutoProxyConfiguration::DoGetAccessType() const {
+  return WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY;
+}
+
+absl::optional<ScopedWinHttpProxyInfo> AutoProxyConfiguration::DoGetProxyForUrl(
+    HINTERNET,
+    const GURL&) const {
+  // When using automatic proxy settings, Windows will resolve the proxy
+  // for us.
+  DVLOG(3) << "Auto-proxy: skip getting proxy for a url";
+  return {};
+}
+
+}  // namespace winhttp
diff --git a/chrome/updater/win/net/proxy_configuration.h b/components/winhttp/proxy_configuration.h
similarity index 80%
rename from chrome/updater/win/net/proxy_configuration.h
rename to components/winhttp/proxy_configuration.h
index 6b09926..b10bde6 100644
--- a/chrome/updater/win/net/proxy_configuration.h
+++ b/components/winhttp/proxy_configuration.h
@@ -2,24 +2,21 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_UPDATER_WIN_NET_PROXY_CONFIGURATION_H_
-#define CHROME_UPDATER_WIN_NET_PROXY_CONFIGURATION_H_
+#ifndef COMPONENTS_WINHTTP_PROXY_CONFIGURATION_H_
+#define COMPONENTS_WINHTTP_PROXY_CONFIGURATION_H_
 
 #include <windows.h>
 #include <winhttp.h>
 
 #include "base/memory/ref_counted.h"
-#include "chrome/updater/win/net/proxy_info.h"
-#include "chrome/updater/win/net/scoped_winttp_proxy_info.h"
+#include "components/winhttp/proxy_info.h"
+#include "components/winhttp/scoped_winttp_proxy_info.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 class GURL;
 
-namespace updater {
+namespace winhttp {
 
-class PolicyService;
-
-// Classes in this module represent sources of system proxy configuration.
 // On Windows 8.1 and above, we can use Auto Proxy mode in WinHTTP and let
 // the OS configure the proxy.
 // This is represented by the AutoProxyConfiguration class.
@@ -75,11 +72,6 @@
 void SetProxyForRequest(
     const HINTERNET request_handle,
     const absl::optional<ScopedWinHttpProxyInfo>& winhttp_proxy_info);
+}  // namespace winhttp
 
-// Factory method for the proxy configuration strategy.
-scoped_refptr<ProxyConfiguration> GetProxyConfiguration(
-    scoped_refptr<PolicyService> policy_service);
-
-}  // namespace updater
-
-#endif  // CHROME_UPDATER_WIN_NET_PROXY_CONFIGURATION_H_
+#endif  // COMPONENTS_WINHTTP_PROXY_CONFIGURATION_H_
diff --git a/chrome/updater/win/net/proxy_configuration_unittest.cc b/components/winhttp/proxy_configuration_unittest.cc
similarity index 82%
rename from chrome/updater/win/net/proxy_configuration_unittest.cc
rename to components/winhttp/proxy_configuration_unittest.cc
index 69821bb..6d5885fc 100644
--- a/chrome/updater/win/net/proxy_configuration_unittest.cc
+++ b/components/winhttp/proxy_configuration_unittest.cc
@@ -2,22 +2,21 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/updater/win/net/proxy_configuration.h"
+#include "components/winhttp/proxy_configuration.h"
 
 #include "base/memory/scoped_refptr.h"
-
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
-namespace updater {
+namespace winhttp {
 
-TEST(ProxyConfiguration, DirectProxy) {
+TEST(WinHttpProxyConfiguration, DirectProxy) {
   auto proxy_configuration = base::MakeRefCounted<ProxyConfiguration>();
   EXPECT_EQ(proxy_configuration->access_type(),
             WINHTTP_ACCESS_TYPE_DEFAULT_PROXY);
 }
 
-TEST(ProxyConfiguration, AutoProxy) {
+TEST(WinHttpProxyConfiguration, AutoProxy) {
   auto proxy_configuration = base::MakeRefCounted<AutoProxyConfiguration>();
   EXPECT_EQ(proxy_configuration->access_type(),
             WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY);
@@ -26,14 +25,14 @@
   EXPECT_FALSE(winhttp_proxy_info.has_value());
 }
 
-TEST(ProxyConfiguration, NamedProxy) {
+TEST(WinHttpProxyConfiguration, NamedProxy) {
   auto proxy_configuration = base::MakeRefCounted<ProxyConfiguration>(
       ProxyInfo(false, L"", L"http://192.168.0.1", L""));
   EXPECT_EQ(proxy_configuration->access_type(),
             WINHTTP_ACCESS_TYPE_NAMED_PROXY);
 }
 
-TEST(ProxyConfiguration, WPADProxyGetProxyForUrl) {
+TEST(WinHttpProxyConfiguration, WPADProxyGetProxyForUrl) {
   auto proxy_configuration =
       base::MakeRefCounted<ProxyConfiguration>(ProxyInfo(true, L"", L"", L""));
   EXPECT_EQ(proxy_configuration->access_type(),
@@ -43,4 +42,4 @@
   EXPECT_FALSE(winhttp_proxy_info.has_value());
 }
 
-}  // namespace updater
+}  // namespace winhttp
\ No newline at end of file
diff --git a/chrome/updater/win/net/proxy_info.cc b/components/winhttp/proxy_info.cc
similarity index 89%
rename from chrome/updater/win/net/proxy_info.cc
rename to components/winhttp/proxy_info.cc
index 8b23ecf..7cc803d 100644
--- a/chrome/updater/win/net/proxy_info.cc
+++ b/components/winhttp/proxy_info.cc
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/updater/win/net/proxy_info.h"
+#include "components/winhttp/proxy_info.h"
 
-namespace updater {
+namespace winhttp {
 
 ProxyInfo::ProxyInfo() = default;
 ProxyInfo::~ProxyInfo() = default;
@@ -23,4 +23,4 @@
 ProxyInfo::ProxyInfo(ProxyInfo&& proxy_info) = default;
 ProxyInfo& ProxyInfo::operator=(ProxyInfo&& proxy_info) = default;
 
-}  // namespace updater
+}  // namespace winhttp
diff --git a/chrome/updater/win/net/proxy_info.h b/components/winhttp/proxy_info.h
similarity index 85%
rename from chrome/updater/win/net/proxy_info.h
rename to components/winhttp/proxy_info.h
index 56dd20cd..a61fcc29 100644
--- a/chrome/updater/win/net/proxy_info.h
+++ b/components/winhttp/proxy_info.h
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_UPDATER_WIN_NET_PROXY_INFO_H_
-#define CHROME_UPDATER_WIN_NET_PROXY_INFO_H_
+#ifndef COMPONENTS_WINHTTP_PROXY_INFO_H_
+#define COMPONENTS_WINHTTP_PROXY_INFO_H_
 
 #include <string>
 
-namespace updater {
+namespace winhttp {
 
 struct ProxyInfo {
   ProxyInfo();
@@ -37,6 +37,6 @@
   std::wstring proxy_bypass;
 };
 
-}  // namespace updater
+}  // namespace winhttp
 
-#endif  // CHROME_UPDATER_WIN_NET_PROXY_INFO_H_
+#endif  // COMPONENTS_WINHTTP_PROXY_INFO_H_
diff --git a/chrome/updater/win/net/proxy_info_unittest.cc b/components/winhttp/proxy_info_unittest.cc
similarity index 86%
rename from chrome/updater/win/net/proxy_info_unittest.cc
rename to components/winhttp/proxy_info_unittest.cc
index 7194ca8..6b94c54 100644
--- a/chrome/updater/win/net/proxy_info_unittest.cc
+++ b/components/winhttp/proxy_info_unittest.cc
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/updater/win/net/proxy_info.h"
+#include "components/winhttp/proxy_info.h"
 
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace updater {
+namespace winhttp {
 
-TEST(ProxyInfoTest, DefaultIsDirectConnection) {
+TEST(WinHttpProxyInfoTest, DefaultIsDirectConnection) {
   ProxyInfo proxy_info;
   EXPECT_FALSE(proxy_info.auto_detect);
   EXPECT_TRUE(proxy_info.auto_config_url.empty());
@@ -16,7 +16,7 @@
   EXPECT_TRUE(proxy_info.proxy_bypass.empty());
 }
 
-TEST(ProxyInfoTest, CanCopy) {
+TEST(WinHttpProxyInfoTest, CanCopy) {
   ProxyInfo proxy_info(true, L"Foo", L"Bar", L"Baz");
   ProxyInfo proxy_info2(proxy_info);
 
@@ -30,7 +30,7 @@
   EXPECT_STREQ(L"Baz", proxy_info2.proxy_bypass.c_str());
 }
 
-TEST(ProxyInfoTest, CanMove) {
+TEST(WinHttpProxyInfoTest, CanMove) {
   ProxyInfo proxy_info{true, L"Foo", L"Bar", L"Baz"};
   ProxyInfo proxy_info2 = std::move(proxy_info);
 
@@ -43,4 +43,4 @@
   EXPECT_TRUE(proxy_info.proxy_bypass.empty());
 }
 
-}  // namespace updater
+}  // namespace winhttp
diff --git a/components/winhttp/scoped_hinternet.cc b/components/winhttp/scoped_hinternet.cc
new file mode 100644
index 0000000..d65c248e
--- /dev/null
+++ b/components/winhttp/scoped_hinternet.cc
@@ -0,0 +1,31 @@
+// 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 "components/winhttp/scoped_hinternet.h"
+
+#include <versionhelpers.h>
+#include <windows.h>
+
+namespace winhttp {
+
+ScopedHInternet CreateSessionHandle(const wchar_t* user_agent,
+                                    int proxy_access_type) {
+  ScopedHInternet session_handle(
+      ::WinHttpOpen(user_agent, proxy_access_type, WINHTTP_NO_PROXY_NAME,
+                    WINHTTP_NO_PROXY_BYPASS, WINHTTP_FLAG_ASYNC));
+
+  // Allow TLS1.2 on Windows 7 and Windows 8. See KB3140245. TLS 1.2 is enabled
+  // by default on Windows 8.1 and Windows 10.
+  if (session_handle.is_valid() && ::IsWindows7OrGreater() &&
+      !::IsWindows8Point1OrGreater()) {
+    DWORD protocols = WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 |
+                      WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 |
+                      WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2;
+    ::WinHttpSetOption(session_handle.get(), WINHTTP_OPTION_SECURE_PROTOCOLS,
+                       &protocols, sizeof(protocols));
+  }
+  return session_handle;
+}
+
+}  // namespace winhttp
diff --git a/components/winhttp/scoped_hinternet.h b/components/winhttp/scoped_hinternet.h
new file mode 100644
index 0000000..3e1a87e
--- /dev/null
+++ b/components/winhttp/scoped_hinternet.h
@@ -0,0 +1,38 @@
+// Copyright 2019 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 COMPONENTS_WINHTTP_SCOPED_HINTERNET_H_
+#define COMPONENTS_WINHTTP_SCOPED_HINTERNET_H_
+
+#include <windows.h>
+#include <winhttp.h>
+
+#include "base/scoped_generic.h"
+
+namespace winhttp {
+
+namespace internal {
+
+struct ScopedHInternetTraits {
+  static HINTERNET InvalidValue() { return nullptr; }
+  static void Free(HINTERNET handle) {
+    if (handle != InvalidValue())
+      WinHttpCloseHandle(handle);
+  }
+};
+
+}  // namespace internal
+
+// Manages the lifetime of HINTERNET handles allocated by WinHTTP.
+using ScopedHInternet =
+    base::ScopedGeneric<HINTERNET, internal::ScopedHInternetTraits>;
+
+// Creates a new WinHttp session using the given user agent and properly
+// configured for the Windows OS version.
+ScopedHInternet CreateSessionHandle(const wchar_t* user_agent,
+                                    int proxy_access_type);
+
+}  // namespace winhttp
+
+#endif  // COMPONENTS_WINHTTP_SCOPED_HINTERNET_H_
diff --git a/chrome/updater/win/net/scoped_winttp_proxy_info.h b/components/winhttp/scoped_winttp_proxy_info.h
similarity index 91%
rename from chrome/updater/win/net/scoped_winttp_proxy_info.h
rename to components/winhttp/scoped_winttp_proxy_info.h
index eef68f0d..2b22af4 100644
--- a/chrome/updater/win/net/scoped_winttp_proxy_info.h
+++ b/components/winhttp/scoped_winttp_proxy_info.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_UPDATER_WIN_NET_SCOPED_WINTTP_PROXY_INFO_H_
-#define CHROME_UPDATER_WIN_NET_SCOPED_WINTTP_PROXY_INFO_H_
+#ifndef COMPONENTS_WINHTTP_SCOPED_WINTTP_PROXY_INFO_H_
+#define COMPONENTS_WINHTTP_SCOPED_WINTTP_PROXY_INFO_H_
 
 #include <windows.h>
 #include <winhttp.h>
@@ -12,7 +12,7 @@
 
 #include "base/logging.h"
 
-namespace updater {
+namespace winhttp {
 
 // Wrapper class for the WINHTTP_PROXY_INFO structure.
 // Note that certain Win32 APIs expected the strings to be allocated with
@@ -94,6 +94,6 @@
   WINHTTP_PROXY_INFO proxy_info_ = {};
 };
 
-}  // namespace updater
+}  // namespace winhttp
 
-#endif  // CHROME_UPDATER_WIN_NET_SCOPED_WINTTP_PROXY_INFO_H_
+#endif  // COMPONENTS_WINHTTP_SCOPED_WINTTP_PROXY_INFO_H_
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 51a7f04..fa8a39e 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -1330,6 +1330,8 @@
     "portal/portal.h",
     "portal/portal_navigation_throttle.cc",
     "portal/portal_navigation_throttle.h",
+    "prerender/prerender_attributes.cc",
+    "prerender/prerender_attributes.h",
     "prerender/prerender_commit_deferring_condition.cc",
     "prerender/prerender_commit_deferring_condition.h",
     "prerender/prerender_host.cc",
diff --git a/content/browser/browser_context_impl.cc b/content/browser/browser_context_impl.cc
index 21380f5..f67e4855 100644
--- a/content/browser/browser_context_impl.cc
+++ b/content/browser/browser_context_impl.cc
@@ -226,6 +226,8 @@
 void BrowserContext::Impl::SetDownloadManagerForTesting(
     std::unique_ptr<DownloadManager> download_manager) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  if (download_manager_)
+    download_manager_->Shutdown();
   download_manager_ = std::move(download_manager);
 }
 
diff --git a/content/browser/child_process_security_policy_impl.cc b/content/browser/child_process_security_policy_impl.cc
index a95bfc1a2..8e36ca7 100644
--- a/content/browser/child_process_security_policy_impl.cc
+++ b/content/browser/child_process_security_policy_impl.cc
@@ -19,6 +19,7 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
@@ -161,12 +162,19 @@
   return keep_alive_duration_key;
 }
 
+base::debug::CrashKeyString* GetCanAccessDataShutdownDelayRefCountKey() {
+  static auto* shutdown_delay_key = base::debug::AllocateCrashKeyString(
+      "shutdown_delay_ref_count", base::debug::CrashKeySize::Size32);
+  return shutdown_delay_key;
+}
+
 void LogCanAccessDataForOriginCrashKeys(
     const std::string& expected_process_lock,
     const std::string& killed_process_origin_lock,
     const std::string& requested_origin,
     const std::string& failure_reason,
-    const std::string& keep_alive_durations) {
+    const std::string& keep_alive_durations,
+    const std::string& shutdown_delay_ref_count) {
   base::debug::SetCrashKeyString(GetExpectedProcessLockKey(),
                                  expected_process_lock);
   base::debug::SetCrashKeyString(GetKilledProcessOriginLockKey(),
@@ -177,6 +185,8 @@
                                  failure_reason);
   base::debug::SetCrashKeyString(GetCanAccessDataKeepAliveDurationKey(),
                                  keep_alive_durations);
+  base::debug::SetCrashKeyString(GetCanAccessDataShutdownDelayRefCountKey(),
+                                 shutdown_delay_ref_count);
 }
 
 }  // namespace
@@ -388,7 +398,7 @@
   if (child_id_ == ChildProcessHost::kInvalidUniqueID) {
     LogCanAccessDataForOriginCrashKeys(
         "(unknown)", "(unknown)", origin.GetDebugString(), "handle_not_valid",
-        "no_keep_alive_durations");
+        "no_keep_alive_durations", "no shutdown delay ref count");
     return false;
   }
 
@@ -1827,9 +1837,13 @@
 
   // Record the duration of KeepAlive requests to include in the crash keys.
   std::string keep_alive_durations;
+  std::string shutdown_delay_ref_count;
   if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
-    if (auto* process = RenderProcessHostImpl::FromID(child_id)) {
+    if (auto* process = static_cast<RenderProcessHostImpl*>(
+            RenderProcessHostImpl::FromID(child_id))) {
       keep_alive_durations = process->GetKeepAliveDurations();
+      shutdown_delay_ref_count =
+          base::NumberToString(process->shutdown_delay_ref_count());
     }
   } else {
     keep_alive_durations = "no durations available: on IO thread.";
@@ -1837,10 +1851,10 @@
 
   // Returning false here will result in a renderer kill.  Set some crash
   // keys that will help understand the circumstances of that kill.
-  LogCanAccessDataForOriginCrashKeys(expected_process_lock.ToString(),
-                                     GetKilledProcessOriginLock(security_state),
-                                     url.GetOrigin().spec(), failure_reason,
-                                     keep_alive_durations);
+  LogCanAccessDataForOriginCrashKeys(
+      expected_process_lock.ToString(),
+      GetKilledProcessOriginLock(security_state), url.GetOrigin().spec(),
+      failure_reason, keep_alive_durations, shutdown_delay_ref_count);
   return false;
 }
 
diff --git a/content/browser/devtools/protocol/target_handler.cc b/content/browser/devtools/protocol/target_handler.cc
index 0ef5dcd86..6f3dd11e 100644
--- a/content/browser/devtools/protocol/target_handler.cc
+++ b/content/browser/devtools/protocol/target_handler.cc
@@ -543,7 +543,12 @@
   DevToolsSession* devtools_session_ = nullptr;
   Throttle* throttle_ = nullptr;
   scoped_refptr<DevToolsThrottleHandle> service_worker_throttle_;
-  TargetAutoAttacher* auto_attacher_ = nullptr;
+  // This is needed to identify sessions associated with given
+  // AutoAttacher to properly support SetAttachedTargetsOfType()
+  // for a TargetHandler that serves as a client to multiple
+  // different TargetAttachers. We don't want a pointer here,
+  // because a session may survive the source AutoAttacher.
+  uintptr_t auto_attacher_id_ = 0;
 };
 
 void TargetHandler::Throttle::CleanupPointers() {
@@ -691,10 +696,8 @@
     auto_attacher_->AddClient(this, wait_for_debugger_on_start,
                               std::move(callback));
   } else {
-    while (!auto_attached_sessions_.empty()) {
-      auto it = auto_attached_sessions_.begin();
-      AutoDetach(it->second->auto_attacher_, it->first);
-    }
+    while (!auto_attached_sessions_.empty())
+      auto_attached_sessions_.begin()->second->Detach(false);
     ClearThrottles();
     std::move(callback).Run();
   }
@@ -722,7 +725,7 @@
   std::string session_id =
       Session::Attach(this, host, waiting_for_debugger, flatten_auto_attach_);
   Session* session = attached_sessions_[session_id].get();
-  session->auto_attacher_ = source;
+  session->auto_attacher_id_ = reinterpret_cast<uintptr_t>(source);
   auto_attached_sessions_[host] = session;
   return true;
 }
@@ -744,7 +747,9 @@
   for (auto& entry : old_sessions) {
     scoped_refptr<DevToolsAgentHost> host(entry.first);
     bool matches_type = type.empty() || host->GetType() == type;
-    if (matches_type && entry.second->auto_attacher_ == source &&
+    if (matches_type &&
+        entry.second->auto_attacher_id_ ==
+            reinterpret_cast<uintptr_t>(source) &&
         new_hosts.find(host) == new_hosts.end()) {
       AutoDetach(source, host.get());
     }
@@ -761,7 +766,12 @@
     if (throttle->auto_attacher() == auto_attacher)
       throttle->Clear();
   }
-
+  for (auto& entry : auto_attached_sessions_) {
+    if (entry.second->auto_attacher_id_ ==
+        reinterpret_cast<uintptr_t>(auto_attacher)) {
+      entry.second->auto_attacher_id_ = 0;
+    }
+  }
   auto_attach_related_targets_.erase(auto_attacher);
 }
 
diff --git a/content/browser/network_service_instance_impl.cc b/content/browser/network_service_instance_impl.cc
index 2b9a5d12..c722f26 100644
--- a/content/browser/network_service_instance_impl.cc
+++ b/content/browser/network_service_instance_impl.cc
@@ -312,7 +312,7 @@
     return false;
 #if defined(OS_WIN)
   // On platforms that don't support the LPAC sandbox, do nothing.
-  if (!sandbox::policy::features::IsNetworkServiceSandboxLPACSupported())
+  if (!sandbox::policy::features::IsWinNetworkServiceSandboxSupported())
     return true;
   DCHECK(!sandbox_params.lpac_capability_name.empty());
   auto ac_sids = base::win::Sid::FromNamedCapabilityVector(
@@ -610,39 +610,6 @@
   return net::NetLogCaptureMode::kDefault;
 }
 
-#if defined(OS_WIN)
-// This enum is used to record a histogram and should not be renumbered.
-enum class ServiceStatus {
-  kUnknown = 0,
-  kNotFound = 1,
-  kFound = 2,
-  kMaxValue = kFound
-};
-
-ServiceStatus DetectSecurityProviders() {
-  // https://docs.microsoft.com/en-us/windows/win32/secauthn/writing-and-installing-a-security-support-provider
-  base::win::RegKey key(HKEY_LOCAL_MACHINE,
-                        L"SYSTEM\\CurrentControlSet\\Control\\Lsa", KEY_READ);
-  if (!key.Valid())
-    return ServiceStatus::kUnknown;
-
-  std::vector<std::wstring> packages;
-  if (key.ReadValues(L"Security Packages", &packages) != ERROR_SUCCESS)
-    return ServiceStatus::kUnknown;
-
-  for (const auto& package : packages) {
-    // Security Packages can be empty or just "". Anything else indicates
-    // there is potentially a third party SSP/APs DLL installed, and network
-    // sandbox should not be engaged.
-    if (package.empty())
-      continue;
-    if (package != L"\"\"")
-      return ServiceStatus::kFound;
-  }
-  return ServiceStatus::kNotFound;
-}
-#endif  // defined(OS_WIN)
-
 // Attempts to grant the sandbox access to the file data specified in the
 // `params`. This function will also perform a migration of existing data from
 // `unsandboxed_data_path` to `data_path` as necessary.
@@ -720,9 +687,9 @@
 
   if (!params->file_paths->unsandboxed_data_path.has_value()) {
 #if defined(OS_WIN)
-    // On Windows, if network LPAC sandbox is enabled then there a migration
-    // must happen, so a `unsandboxed_data_path` must be specified.
-    DCHECK(!sandbox::policy::features::IsNetworkServiceSandboxLPACEnabled());
+    // On Windows, if network sandbox is enabled then there a migration must
+    // happen, so a `unsandboxed_data_path` must be specified.
+    DCHECK(!IsNetworkSandboxEnabled());
 #endif
     // Trigger migration should never be requested if `unsandboxed_data_path` is
     // not set.
@@ -759,9 +726,10 @@
   // Case 1. above where nothing is done.
   if (!params->file_paths->trigger_migration && !migration_already_happened) {
 #if defined(OS_WIN)
-    // On Windows, if network LPAC sandbox is enabled then there a migration
-    // must happen, so `trigger_migration` must be true.
-    DCHECK(!sandbox::policy::features::IsNetworkServiceSandboxLPACEnabled());
+    // On Windows, if network sandbox is enabled then there a migration must
+    // happen, so `trigger_migration` must be true, or a migration must have
+    // already happened.
+    DCHECK(!IsNetworkSandboxEnabled());
 #endif
     return SandboxGrantResult::kNoMigrationRequested;
   }
@@ -1262,24 +1230,12 @@
 bool IsNetworkSandboxEnabled() {
 #if defined(OS_MAC) || defined(OS_FUCHSIA)
   return true;
+#elif defined(OS_WIN)
+  return sandbox::policy::features::IsWinNetworkServiceSandboxEnabled();
 #else
-#if defined(OS_WIN)
-  if (base::win::GetVersion() < base::win::Version::WIN10)
-    return false;
-  auto ssp_status = DetectSecurityProviders();
-  base::UmaHistogramEnumeration("Windows.ServiceStatus.SSP", ssp_status);
-  switch (ssp_status) {
-    case ServiceStatus::kUnknown:
-      return false;
-    case ServiceStatus::kNotFound:
-      break;
-    case ServiceStatus::kFound:
-      return false;
-  }
-#endif  // defined(OS_WIN)
   return base::FeatureList::IsEnabled(
       sandbox::policy::features::kNetworkServiceSandbox);
-#endif  // defined(OS_MAC) || defined(OS_FUCHSIA)
+#endif
 }
 
 void CreateNetworkContextInNetworkService(
diff --git a/content/browser/notifications/platform_notification_service_proxy.cc b/content/browser/notifications/platform_notification_service_proxy.cc
index bbd10a4..6a95bb8 100644
--- a/content/browser/notifications/platform_notification_service_proxy.cc
+++ b/content/browser/notifications/platform_notification_service_proxy.cc
@@ -61,7 +61,7 @@
     DisplayResultCallback callback,
     blink::ServiceWorkerStatusCode status,
     scoped_refptr<ServiceWorkerRegistration> registration) {
-  DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   base::OnceClosure task;
 
   if (status == blink::ServiceWorkerStatusCode::kOk &&
@@ -84,27 +84,17 @@
     return;
   }
 
-  scoped_refptr<base::SingleThreadTaskRunner> core_thread_task_runner;
-  constexpr BrowserTaskTraits traits = {base::TaskPriority::USER_VISIBLE};
-  switch (ServiceWorkerContext::GetCoreThreadId()) {
-    case BrowserThread::UI:
-      core_thread_task_runner = GetUIThreadTaskRunner(traits);
-      break;
-    case BrowserThread::IO:
-      core_thread_task_runner = GetIOThreadTaskRunner(traits);
-      break;
-    case BrowserThread::ID_COUNT:
-      NOTREACHED();
-  }
-  core_thread_task_runner->PostTask(
-      FROM_HERE,
-      base::BindOnce(
-          &ServiceWorkerContextWrapper::FindReadyRegistrationForId,
-          service_worker_context_, data.service_worker_registration_id,
-          blink::StorageKey(url::Origin::Create(data.origin)),
+  GetUIThreadTaskRunner({base::TaskPriority::USER_VISIBLE})
+      ->PostTask(
+          FROM_HERE,
           base::BindOnce(
-              &PlatformNotificationServiceProxy::VerifyServiceWorkerScope,
-              weak_ptr_factory_io_.GetWeakPtr(), data, std::move(callback))));
+              &ServiceWorkerContextWrapper::FindReadyRegistrationForId,
+              service_worker_context_, data.service_worker_registration_id,
+              blink::StorageKey(url::Origin::Create(data.origin)),
+              base::BindOnce(
+                  &PlatformNotificationServiceProxy::VerifyServiceWorkerScope,
+                  weak_ptr_factory_io_.GetWeakPtr(), data,
+                  std::move(callback))));
 }
 
 void PlatformNotificationServiceProxy::CloseNotifications(
diff --git a/content/browser/prerender/prerender_attributes.cc b/content/browser/prerender/prerender_attributes.cc
new file mode 100644
index 0000000..5df7246
--- /dev/null
+++ b/content/browser/prerender/prerender_attributes.cc
@@ -0,0 +1,17 @@
+// 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 "content/browser/prerender/prerender_attributes.h"
+#include "third_party/perfetto/include/perfetto/tracing/traced_value.h"
+
+namespace content {
+
+void PrerenderAttributes::WriteIntoTrace(
+    perfetto::TracedValue trace_context) const {
+  auto dict = std::move(trace_context).WriteDictionary();
+  dict.Add("url", url);
+  dict.Add("trigger_type", trigger_type);
+}
+
+}  // namespace content
diff --git a/content/browser/prerender/prerender_attributes.h b/content/browser/prerender/prerender_attributes.h
new file mode 100644
index 0000000..868fc88f
--- /dev/null
+++ b/content/browser/prerender/prerender_attributes.h
@@ -0,0 +1,30 @@
+// 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.
+
+#ifndef CONTENT_BROWSER_PRERENDER_PRERENDER_ATTRIBUTES_H_
+#define CONTENT_BROWSER_PRERENDER_PRERENDER_ATTRIBUTES_H_
+
+#include "content/public/common/referrer.h"
+#include "third_party/perfetto/include/perfetto/tracing/traced_value_forward.h"
+
+namespace content {
+
+enum class PrerenderTriggerType {
+  // https://jeremyroman.github.io/alternate-loading-modes/#speculation-rules
+  kSpeculationRule,
+};
+
+// Records the basic attributes of a prerender request.
+struct PrerenderAttributes {
+  GURL url;
+  PrerenderTriggerType trigger_type;
+  Referrer referrer;
+
+  // Serialises this struct into a trace.
+  void WriteIntoTrace(perfetto::TracedValue trace_context) const;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_PRERENDER_PRERENDER_ATTRIBUTES_H_
diff --git a/content/browser/prerender/prerender_host.cc b/content/browser/prerender/prerender_host.cc
index dc6b3cc..ded4eab5 100644
--- a/content/browser/prerender/prerender_host.cc
+++ b/content/browser/prerender/prerender_host.cc
@@ -27,6 +27,7 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_delegate.h"
 #include "content/public/browser/web_contents_observer.h"
+#include "content/public/common/referrer.h"
 #include "net/base/load_flags.h"
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/mojom/loader/referrer.mojom.h"
@@ -309,9 +310,9 @@
   std::unique_ptr<FrameTree> frame_tree_;
 };
 
-PrerenderHost::PrerenderHost(blink::mojom::PrerenderAttributesPtr attributes,
+PrerenderHost::PrerenderHost(const PrerenderAttributes& attributes,
                              RenderFrameHostImpl& initiator_render_frame_host)
-    : attributes_(std::move(attributes)),
+    : attributes_(attributes),
       initiator_origin_(initiator_render_frame_host.GetLastCommittedOrigin()),
       initiator_process_id_(initiator_render_frame_host.GetProcess()->GetID()),
       initiator_frame_token_(initiator_render_frame_host.GetFrameToken()) {
@@ -344,7 +345,7 @@
   Observe(page_holder_->GetWebContents());
 
   // Start prerendering navigation.
-  NavigationController::LoadURLParams load_url_params(attributes_->url);
+  NavigationController::LoadURLParams load_url_params(attributes_.url);
   load_url_params.initiator_origin = initiator_origin_;
   load_url_params.initiator_process_id = initiator_process_id_;
   load_url_params.initiator_frame_token = initiator_frame_token_;
@@ -352,8 +353,7 @@
   // Just use the referrer from attributes, as NoStatePrefetch does.
   // TODO(crbug.com/1176054): For cross-origin prerender, follow the spec steps
   // for "sufficiently-strict speculative navigation referrer policies".
-  if (attributes_->referrer)
-    load_url_params.referrer = Referrer(*attributes_->referrer);
+  load_url_params.referrer = attributes_.referrer;
 
   // TODO(https://crbug.com/1189034): Should we set `override_user_agent` here?
   // Things seem to work without it.
@@ -798,7 +798,7 @@
 }
 
 const GURL& PrerenderHost::GetInitialUrl() const {
-  return attributes_->url;
+  return attributes_.url;
 }
 
 void PrerenderHost::AddObserver(Observer* observer) {
diff --git a/content/browser/prerender/prerender_host.h b/content/browser/prerender/prerender_host.h
index 8107e25..caf5467 100644
--- a/content/browser/prerender/prerender_host.h
+++ b/content/browser/prerender/prerender_host.h
@@ -9,6 +9,7 @@
 
 #include "base/observer_list_types.h"
 #include "base/types/pass_key.h"
+#include "content/browser/prerender/prerender_attributes.h"
 #include "content/browser/renderer_host/back_forward_cache_impl.h"
 #include "content/browser/renderer_host/stored_page.h"
 #include "content/common/content_export.h"
@@ -18,7 +19,6 @@
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/common/tokens/tokens.h"
 #include "third_party/blink/public/mojom/navigation/navigation_params.mojom.h"
-#include "third_party/blink/public/mojom/prerender/prerender.mojom.h"
 #include "url/gurl.h"
 
 namespace content {
@@ -86,7 +86,7 @@
     kMaxValue = kTriggerBackgrounded,
   };
 
-  PrerenderHost(blink::mojom::PrerenderAttributesPtr attributes,
+  PrerenderHost(const PrerenderAttributes& attributes,
                 RenderFrameHostImpl& initiator_render_frame_host);
   ~PrerenderHost() override;
 
@@ -174,9 +174,7 @@
   bool AreCommonNavigationParamsCompatibleWithNavigation(
       const blink::mojom::CommonNavigationParams& potential_activation);
 
-  // TODO(https://crbug.com/1217045): Flatten the params and do not rely on
-  // PrerenderAttributesPtr.
-  const blink::mojom::PrerenderAttributesPtr attributes_;
+  const PrerenderAttributes attributes_;
   const url::Origin initiator_origin_;
   const int initiator_process_id_;
   const blink::LocalFrameToken initiator_frame_token_;
diff --git a/content/browser/prerender/prerender_host_registry.cc b/content/browser/prerender/prerender_host_registry.cc
index 352ecc57..2e16078 100644
--- a/content/browser/prerender/prerender_host_registry.cc
+++ b/content/browser/prerender/prerender_host_registry.cc
@@ -71,10 +71,8 @@
 }
 
 int PrerenderHostRegistry::CreateAndStartHost(
-    blink::mojom::PrerenderAttributesPtr attributes,
+    const PrerenderAttributes& attributes,
     RenderFrameHostImpl& initiator_render_frame_host) {
-  DCHECK(attributes);
-
   // The prerender request from a page being prerendered should be deferred
   // until activation by the Mojo capability control.
   DCHECK_NE(RenderFrameHostImpl::LifecycleStateImpl::kPrerendering,
@@ -88,7 +86,7 @@
   // Ensure observers are notified that a trigger occurred.
   base::ScopedClosureRunner notify_trigger(
       base::BindOnce(&PrerenderHostRegistry::NotifyTrigger,
-                     base::Unretained(this), attributes->url));
+                     base::Unretained(this), attributes.url));
 
   // Don't prerender when the trigger is in the background.
   auto* web_contents =
@@ -113,7 +111,7 @@
 
   // TODO(crbug.com/1176054): Support cross-origin prerendering.
   if (!initiator_render_frame_host.GetLastCommittedOrigin().IsSameOriginWith(
-          url::Origin::Create(attributes->url))) {
+          url::Origin::Create(attributes.url))) {
     base::UmaHistogramEnumeration(
         "Prerender.Experimental.PrerenderHostFinalStatus",
         PrerenderHost::FinalStatus::kCrossOriginNavigation);
@@ -122,7 +120,7 @@
 
   // Ignore prerendering requests for the same URL.
   for (auto& iter : prerender_host_by_frame_tree_node_id_) {
-    if (iter.second->GetInitialUrl() == attributes->url)
+    if (iter.second->GetInitialUrl() == attributes.url)
       return iter.first;
   }
 
@@ -136,8 +134,8 @@
     return RenderFrameHost::kNoFrameTreeNodeId;
   }
 
-  auto prerender_host = std::make_unique<PrerenderHost>(
-      std::move(attributes), initiator_render_frame_host);
+  auto prerender_host =
+      std::make_unique<PrerenderHost>(attributes, initiator_render_frame_host);
   const int frame_tree_node_id = prerender_host->frame_tree_node_id();
 
   CHECK(!base::Contains(prerender_host_by_frame_tree_node_id_,
diff --git a/content/browser/prerender/prerender_host_registry.h b/content/browser/prerender/prerender_host_registry.h
index 2ac200f..13eab44f 100644
--- a/content/browser/prerender/prerender_host_registry.h
+++ b/content/browser/prerender/prerender_host_registry.h
@@ -11,11 +11,11 @@
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list_types.h"
 #include "base/types/pass_key.h"
+#include "content/browser/prerender/prerender_attributes.h"
 #include "content/browser/prerender/prerender_host.h"
 #include "content/browser/renderer_host/back_forward_cache_impl.h"
 #include "content/common/content_export.h"
 #include "third_party/blink/public/common/tokens/tokens.h"
-#include "third_party/blink/public/mojom/prerender/prerender.mojom.h"
 #include "url/gurl.h"
 #include "url/origin.h"
 
@@ -66,9 +66,7 @@
   // For triggers.
   // Creates and starts a host. Returns the root frame tree node id of the
   // prerendered page, which can be used as the id of the host.
-  // TODO(https://crbug.com/1217045): Flatten the params and do not rely on
-  // PrerenderAttributesPtr.
-  int CreateAndStartHost(blink::mojom::PrerenderAttributesPtr attributes,
+  int CreateAndStartHost(const PrerenderAttributes& attributes,
                          RenderFrameHostImpl& initiator_render_frame_host);
 
   // Cancels the host registered for `frame_tree_node_id`. The host is
diff --git a/content/browser/prerender/prerender_host_registry_unittest.cc b/content/browser/prerender/prerender_host_registry_unittest.cc
index 8487ac6..d1b34da 100644
--- a/content/browser/prerender/prerender_host_registry_unittest.cc
+++ b/content/browser/prerender/prerender_host_registry_unittest.cc
@@ -181,11 +181,11 @@
     RenderFrameHostImpl* render_frame_host = web_contents->GetMainFrame();
 
     const GURL kPrerenderingUrl("https://example.com/next");
-    auto attributes = blink::mojom::PrerenderAttributes::New();
-    attributes->url = kPrerenderingUrl;
+    PrerenderAttributes attributes{
+        kPrerenderingUrl, PrerenderTriggerType::kSpeculationRule, Referrer()};
 
     PrerenderHostRegistry* registry = web_contents->GetPrerenderHostRegistry();
-    registry->CreateAndStartHost(std::move(attributes), *render_frame_host);
+    registry->CreateAndStartHost(attributes, *render_frame_host);
     PrerenderHost* prerender_host =
         registry->FindHostByUrlForTesting(kPrerenderingUrl);
     CommitPrerenderNavigation(*prerender_host);
@@ -229,12 +229,12 @@
     ASSERT_TRUE(render_frame_host);
 
     const GURL kPrerenderingUrl("https://example.com/next");
-    auto attributes = blink::mojom::PrerenderAttributes::New();
-    attributes->url = kPrerenderingUrl;
+    PrerenderAttributes attributes{
+        kPrerenderingUrl, PrerenderTriggerType::kSpeculationRule, Referrer()};
 
     PrerenderHostRegistry* registry = wc->GetPrerenderHostRegistry();
     const int prerender_frame_tree_node_id =
-        registry->CreateAndStartHost(std::move(attributes), *render_frame_host);
+        registry->CreateAndStartHost(attributes, *render_frame_host);
     ASSERT_NE(prerender_frame_tree_node_id, kNoFrameTreeNodeId);
     PrerenderHost* prerender_host =
         registry->FindNonReservedHostById(prerender_frame_tree_node_id);
@@ -265,12 +265,12 @@
   ASSERT_TRUE(render_frame_host);
 
   const GURL kPrerenderingUrl("https://example.com/next");
-  auto attributes = blink::mojom::PrerenderAttributes::New();
-  attributes->url = kPrerenderingUrl;
+  PrerenderAttributes attributes{
+      kPrerenderingUrl, PrerenderTriggerType::kSpeculationRule, Referrer()};
 
   PrerenderHostRegistry* registry = web_contents->GetPrerenderHostRegistry();
   const int prerender_frame_tree_node_id =
-      registry->CreateAndStartHost(std::move(attributes), *render_frame_host);
+      registry->CreateAndStartHost(attributes, *render_frame_host);
   ASSERT_NE(prerender_frame_tree_node_id, kNoFrameTreeNodeId);
   PrerenderHost* prerender_host =
       registry->FindHostByUrlForTesting(kPrerenderingUrl);
@@ -288,22 +288,21 @@
 
   const GURL kPrerenderingUrl("https://example.com/next");
 
-  auto attributes1 = blink::mojom::PrerenderAttributes::New();
-  attributes1->url = kPrerenderingUrl;
-
-  auto attributes2 = blink::mojom::PrerenderAttributes::New();
-  attributes2->url = kPrerenderingUrl;
+  PrerenderAttributes attributes1{
+      kPrerenderingUrl, PrerenderTriggerType::kSpeculationRule, Referrer()};
+  PrerenderAttributes attributes2{
+      kPrerenderingUrl, PrerenderTriggerType::kSpeculationRule, Referrer()};
 
   PrerenderHostRegistry* registry = web_contents->GetPrerenderHostRegistry();
   const int frame_tree_node_id1 =
-      registry->CreateAndStartHost(std::move(attributes1), *render_frame_host);
+      registry->CreateAndStartHost(attributes1, *render_frame_host);
   PrerenderHost* prerender_host1 =
       registry->FindHostByUrlForTesting(kPrerenderingUrl);
 
   // Start the prerender host for the same URL. This second host should be
   // ignored, and the first host should still be findable.
   const int frame_tree_node_id2 =
-      registry->CreateAndStartHost(std::move(attributes2), *render_frame_host);
+      registry->CreateAndStartHost(attributes2, *render_frame_host);
   EXPECT_EQ(frame_tree_node_id1, frame_tree_node_id2);
   EXPECT_EQ(registry->FindHostByUrlForTesting(kPrerenderingUrl),
             prerender_host1);
@@ -325,18 +324,17 @@
   // After the first prerender page was activated, PrerenderHostRegistry can
   // start prerendering a new one.
   const GURL kPrerenderingUrl1("https://example.com/next1");
-  auto attributes1 = blink::mojom::PrerenderAttributes::New();
-  attributes1->url = kPrerenderingUrl1;
-
   const GURL kPrerenderingUrl2("https://example.com/next2");
-  auto attributes2 = blink::mojom::PrerenderAttributes::New();
-  attributes2->url = kPrerenderingUrl2;
+  PrerenderAttributes attributes1{
+      kPrerenderingUrl1, PrerenderTriggerType::kSpeculationRule, Referrer()};
+  PrerenderAttributes attributes2{
+      kPrerenderingUrl2, PrerenderTriggerType::kSpeculationRule, Referrer()};
 
   PrerenderHostRegistry* registry = web_contents->GetPrerenderHostRegistry();
   int frame_tree_node_id1 =
-      registry->CreateAndStartHost(std::move(attributes1), *render_frame_host);
+      registry->CreateAndStartHost(attributes1, *render_frame_host);
   int frame_tree_node_id2 =
-      registry->CreateAndStartHost(std::move(attributes2), *render_frame_host);
+      registry->CreateAndStartHost(attributes2, *render_frame_host);
   histogram_tester.ExpectUniqueSample(
       "Prerender.Experimental.PrerenderHostFinalStatus",
       PrerenderHost::FinalStatus::kMaxNumOfRunningPrerendersExceeded, 1);
@@ -353,10 +351,8 @@
 
   // After the first prerender page was activated, PrerenderHostRegistry can
   // start prerendering a new one.
-  attributes2 = blink::mojom::PrerenderAttributes::New();
-  attributes2->url = kPrerenderingUrl2;
   frame_tree_node_id2 =
-      registry->CreateAndStartHost(std::move(attributes2), *render_frame_host);
+      registry->CreateAndStartHost(attributes2, *render_frame_host);
   EXPECT_NE(frame_tree_node_id2, kNoFrameTreeNodeId);
   histogram_tester.ExpectBucketCount(
       "Prerender.Experimental.PrerenderHostFinalStatus",
@@ -465,12 +461,12 @@
   ASSERT_TRUE(render_frame_host);
 
   const GURL kPrerenderingUrl("https://example.com/next");
-  auto attributes = blink::mojom::PrerenderAttributes::New();
-  attributes->url = kPrerenderingUrl;
+  PrerenderAttributes attributes{
+      kPrerenderingUrl, PrerenderTriggerType::kSpeculationRule, Referrer()};
 
   PrerenderHostRegistry* registry = web_contents->GetPrerenderHostRegistry();
   const int prerender_frame_tree_node_id =
-      registry->CreateAndStartHost(std::move(attributes), *render_frame_host);
+      registry->CreateAndStartHost(attributes, *render_frame_host);
   ASSERT_NE(prerender_frame_tree_node_id, kNoFrameTreeNodeId);
   PrerenderHost* prerender_host =
       registry->FindHostByUrlForTesting(kPrerenderingUrl);
@@ -523,12 +519,12 @@
   ASSERT_TRUE(render_frame_host);
 
   const GURL kPrerenderingUrl("https://example.com/next");
-  auto attributes = blink::mojom::PrerenderAttributes::New();
-  attributes->url = kPrerenderingUrl;
+  PrerenderAttributes attributes{
+      kPrerenderingUrl, PrerenderTriggerType::kSpeculationRule, Referrer()};
 
   PrerenderHostRegistry* registry = web_contents->GetPrerenderHostRegistry();
   const int prerender_frame_tree_node_id =
-      registry->CreateAndStartHost(std::move(attributes), *render_frame_host);
+      registry->CreateAndStartHost(attributes, *render_frame_host);
   EXPECT_NE(registry->FindHostByUrlForTesting(kPrerenderingUrl), nullptr);
 
   registry->CancelHost(prerender_frame_tree_node_id,
@@ -548,12 +544,12 @@
 
   // Start prerendering.
   const GURL kPrerenderingUrl("https://example.com/next");
-  auto attributes = blink::mojom::PrerenderAttributes::New();
-  attributes->url = kPrerenderingUrl;
+  PrerenderAttributes attributes{
+      kPrerenderingUrl, PrerenderTriggerType::kSpeculationRule, Referrer()};
 
   PrerenderHostRegistry* registry = web_contents->GetPrerenderHostRegistry();
   const int prerender_frame_tree_node_id =
-      registry->CreateAndStartHost(std::move(attributes), *render_frame_host);
+      registry->CreateAndStartHost(attributes, *render_frame_host);
   ASSERT_NE(prerender_frame_tree_node_id, kNoFrameTreeNodeId);
   PrerenderHost* prerender_host =
       registry->FindHostByUrlForTesting(kPrerenderingUrl);
@@ -613,12 +609,12 @@
   ASSERT_TRUE(render_frame_host);
 
   const GURL kPrerenderingUrl("https://example.com/next");
-  auto attributes = blink::mojom::PrerenderAttributes::New();
-  attributes->url = kPrerenderingUrl;
+  PrerenderAttributes attributes{
+      kPrerenderingUrl, PrerenderTriggerType::kSpeculationRule, Referrer()};
 
   PrerenderHostRegistry* registry = web_contents->GetPrerenderHostRegistry();
   const int prerender_frame_tree_node_id =
-      registry->CreateAndStartHost(std::move(attributes), *render_frame_host);
+      registry->CreateAndStartHost(attributes, *render_frame_host);
   ASSERT_NE(prerender_frame_tree_node_id, kNoFrameTreeNodeId);
   PrerenderHost* prerender_host =
       registry->FindHostByUrlForTesting(kPrerenderingUrl);
@@ -660,11 +656,11 @@
   EXPECT_EQ(registry->FindHostByUrlForTesting(kPrerenderingUrl), nullptr);
 
   // Start the second prerender for the same URL.
-  auto attributes2 = blink::mojom::PrerenderAttributes::New();
-  attributes2->url = kPrerenderingUrl;
+  PrerenderAttributes attributes2{
+      kPrerenderingUrl, PrerenderTriggerType::kSpeculationRule, Referrer()};
 
   const int prerender_frame_tree_node_id2 =
-      registry->CreateAndStartHost(std::move(attributes2), *render_frame_host);
+      registry->CreateAndStartHost(attributes2, *render_frame_host);
   ASSERT_NE(prerender_frame_tree_node_id2, kNoFrameTreeNodeId);
   PrerenderHost* prerender_host2 =
       registry->FindHostByUrlForTesting(kPrerenderingUrl);
@@ -694,10 +690,10 @@
   const GURL kPrerenderingUrl = GURL("https://example.com/empty.html");
   RenderFrameHostImpl* initiator_rfh = web_contents->GetMainFrame();
   PrerenderHostRegistry* registry = web_contents->GetPrerenderHostRegistry();
-  auto attributes = blink::mojom::PrerenderAttributes::New();
-  attributes->url = kPrerenderingUrl;
+  PrerenderAttributes attributes{
+      kPrerenderingUrl, PrerenderTriggerType::kSpeculationRule, Referrer()};
   const int prerender_frame_tree_node_id =
-      registry->CreateAndStartHost(std::move(attributes), *initiator_rfh);
+      registry->CreateAndStartHost(attributes, *initiator_rfh);
   EXPECT_EQ(prerender_frame_tree_node_id, RenderFrameHost::kNoFrameTreeNodeId);
   PrerenderHost* prerender_host =
       registry->FindNonReservedHostById(prerender_frame_tree_node_id);
diff --git a/content/browser/prerender/prerender_host_unittest.cc b/content/browser/prerender/prerender_host_unittest.cc
index 6285e45c..91b6c94 100644
--- a/content/browser/prerender/prerender_host_unittest.cc
+++ b/content/browser/prerender/prerender_host_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/test/scoped_feature_list.h"
 #include "build/build_config.h"
+#include "content/browser/prerender/prerender_attributes.h"
 #include "content/browser/prerender/prerender_host_registry.h"
 #include "content/browser/site_instance_impl.h"
 #include "content/public/test/mock_web_contents_observer.h"
@@ -273,10 +274,10 @@
 
   // Start prerendering a page.
   const GURL kPrerenderingUrl("https://example.com/next");
-  auto attributes = blink::mojom::PrerenderAttributes::New();
-  attributes->url = kPrerenderingUrl;
+  PrerenderAttributes attributes{
+      kPrerenderingUrl, PrerenderTriggerType::kSpeculationRule, Referrer()};
   const int prerender_frame_tree_node_id =
-      registry->CreateAndStartHost(std::move(attributes), *initiator_rfh);
+      registry->CreateAndStartHost(attributes, *initiator_rfh);
   PrerenderHost* prerender_host =
       registry->FindNonReservedHostById(prerender_frame_tree_node_id);
   CommitPrerenderNavigation(*prerender_host);
@@ -383,10 +384,10 @@
   const GURL kPrerenderingUrl = GURL("https://example.com/empty.html");
   RenderFrameHostImpl* initiator_rfh = web_contents->GetMainFrame();
   PrerenderHostRegistry* registry = web_contents->GetPrerenderHostRegistry();
-  auto attributes = blink::mojom::PrerenderAttributes::New();
-  attributes->url = kPrerenderingUrl;
+  PrerenderAttributes attributes{
+      kPrerenderingUrl, PrerenderTriggerType::kSpeculationRule, Referrer()};
   const int prerender_frame_tree_node_id =
-      registry->CreateAndStartHost(std::move(attributes), *initiator_rfh);
+      registry->CreateAndStartHost(attributes, *initiator_rfh);
   PrerenderHost* prerender_host =
       registry->FindNonReservedHostById(prerender_frame_tree_node_id);
   ASSERT_NE(prerender_host, nullptr);
@@ -403,10 +404,10 @@
   const GURL kPrerenderingUrl = GURL("https://example.com/empty.html");
   RenderFrameHostImpl* initiator_rfh = web_contents->GetMainFrame();
   PrerenderHostRegistry* registry = web_contents->GetPrerenderHostRegistry();
-  auto attributes = blink::mojom::PrerenderAttributes::New();
-  attributes->url = kPrerenderingUrl;
+  PrerenderAttributes attributes{
+      kPrerenderingUrl, PrerenderTriggerType::kSpeculationRule, Referrer()};
   const int prerender_frame_tree_node_id =
-      registry->CreateAndStartHost(std::move(attributes), *initiator_rfh);
+      registry->CreateAndStartHost(attributes, *initiator_rfh);
   PrerenderHost* prerender_host =
       registry->FindNonReservedHostById(prerender_frame_tree_node_id);
   ASSERT_NE(prerender_host, nullptr);
@@ -426,10 +427,10 @@
   const GURL kPrerenderingUrl = GURL("https://example.com/empty.html");
   RenderFrameHostImpl* initiator_rfh = web_contents->GetMainFrame();
   PrerenderHostRegistry* registry = web_contents->GetPrerenderHostRegistry();
-  auto attributes = blink::mojom::PrerenderAttributes::New();
-  attributes->url = kPrerenderingUrl;
+  PrerenderAttributes attributes{
+      kPrerenderingUrl, PrerenderTriggerType::kSpeculationRule, Referrer()};
   const int prerender_frame_tree_node_id =
-      registry->CreateAndStartHost(std::move(attributes), *initiator_rfh);
+      registry->CreateAndStartHost(attributes, *initiator_rfh);
   PrerenderHost* prerender_host =
       registry->FindNonReservedHostById(prerender_frame_tree_node_id);
   ASSERT_NE(prerender_host, nullptr);
diff --git a/content/browser/renderer_host/back_forward_cache_metrics.cc b/content/browser/renderer_host/back_forward_cache_metrics.cc
index ea81c80..4d348da 100644
--- a/content/browser/renderer_host/back_forward_cache_metrics.cc
+++ b/content/browser/renderer_host/back_forward_cache_metrics.cc
@@ -114,9 +114,8 @@
 void BackForwardCacheMetrics::DidCommitNavigation(
     NavigationRequest* navigation,
     bool back_forward_cache_allowed) {
-  // TODO(https://crbug.com/1218946): With MPArch there may be multiple main
-  // frames. This caller was converted automatically to the primary main frame
-  // to preserve its semantics. Follow up to confirm correctness.
+  // "Back-forward cache in enabled only for primary frame trees, so we need to
+  // record metrics only for primary main frame navigations".
   if (!navigation->IsInPrimaryMainFrame() || navigation->IsSameDocument())
     return;
 
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h
index 30916df..5669655e 100644
--- a/content/browser/renderer_host/render_process_host_impl.h
+++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -683,6 +683,7 @@
 
   size_t keep_alive_ref_count() const { return keep_alive_ref_count_; }
   size_t worker_ref_count() const { return worker_ref_count_; }
+  size_t shutdown_delay_ref_count() const { return shutdown_delay_ref_count_; }
 
   // Allows overriding the URLLoaderFactory creation via CreateURLLoaderFactory.
   // Passing a null callback will restore the default behavior.
diff --git a/content/browser/service_worker/service_worker_context_core.cc b/content/browser/service_worker/service_worker_context_core.cc
index 2b82c26..13e85b1e 100644
--- a/content/browser/service_worker/service_worker_context_core.cc
+++ b/content/browser/service_worker/service_worker_context_core.cc
@@ -371,9 +371,6 @@
     return;
   }
 
-  std::unique_ptr<std::vector<std::pair<int, int>>> render_frames(
-      new std::vector<std::pair<int, int>>());
-
   bool has_main_frame = false;
   while (!container_host_iterator->IsAtEnd()) {
     ServiceWorkerContainerHost* container_host =
diff --git a/content/browser/speculation_rules/speculation_host_impl.cc b/content/browser/speculation_rules/speculation_host_impl.cc
index 05aaa86..b60b883 100644
--- a/content/browser/speculation_rules/speculation_host_impl.cc
+++ b/content/browser/speculation_rules/speculation_host_impl.cc
@@ -4,12 +4,14 @@
 
 #include "content/browser/speculation_rules/speculation_host_impl.h"
 
+#include "content/browser/prerender/prerender_attributes.h"
 #include "content/browser/prerender/prerender_host_registry.h"
 #include "content/browser/renderer_host/render_frame_host_delegate.h"
 #include "content/browser/renderer_host/render_frame_host_impl.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/web_contents_delegate.h"
 #include "content/public/common/content_client.h"
+#include "content/public/common/referrer.h"
 #include "mojo/public/cpp/bindings/message.h"
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/mojom/web_feature/web_feature.mojom.h"
@@ -126,14 +128,10 @@
     GetContentClient()->browser()->LogWebFeatureForCurrentPage(
         rfhi, blink::mojom::WebFeature::kSpeculationRulesPrerender);
 
-    // TODO(https://crbug.com/1217903): Set up `attributes->size`.
-    auto attributes = blink::mojom::PrerenderAttributes::New();
-    attributes->url = it->url;
-    attributes->referrer = std::move(it->referrer);
-    attributes->trigger_type =
-        blink::mojom::PrerenderTriggerType::kSpeculationRule;
-    int prerender_host_id =
-        registry_->CreateAndStartHost(std::move(attributes), *rfhi);
+    PrerenderAttributes attributes{it->url,
+                                   PrerenderTriggerType::kSpeculationRule,
+                                   Referrer(*(it->referrer))};
+    int prerender_host_id = registry_->CreateAndStartHost(attributes, *rfhi);
     if (prerender_host_id != RenderFrameHost::kNoFrameTreeNodeId)
       started_prerender_host_ids_.insert(prerender_host_id);
   }
diff --git a/content/browser/utility_sandbox_delegate_win.cc b/content/browser/utility_sandbox_delegate_win.cc
index ed2915e9..b97cb12 100644
--- a/content/browser/utility_sandbox_delegate_win.cc
+++ b/content/browser/utility_sandbox_delegate_win.cc
@@ -64,66 +64,26 @@
 
 // Sets the sandbox policy for the network service process.
 bool NetworkPreSpawnTarget(sandbox::TargetPolicy* policy) {
-  if (sandbox::policy::features::IsNetworkServiceSandboxLPACEnabled()) {
-    // LPAC sandbox is enabled, so do not use a restricted token.
-    if (sandbox::SBOX_ALL_OK !=
-        policy->SetTokenLevel(sandbox::USER_UNPROTECTED,
-                              sandbox::USER_UNPROTECTED)) {
-      return false;
-    }
-
-    // Network Sandbox in LPAC sandbox needs access to its data files. These
-    // files are marked on disk with an ACE that permits this access.
-    auto lpacCapability =
-        GetContentClient()->browser()->GetLPACCapabilityNameForNetworkService();
-    if (lpacCapability.empty())
-      return false;
-    auto app_container = policy->GetAppContainer();
-    if (!app_container)
-      return false;
-    app_container->AddCapability(lpacCapability.c_str());
-
-    // All other app container policies are set in
-    // SandboxWin::StartSandboxedProcess.
-    return true;
-  }
-
-  // USER_LIMITED is as tight as this sandbox can be, because
-  // DNS running in-process is blocked by USER_RESTRICTED and
-  // below as it can't connect to the service.
-  if (policy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS,
-                            sandbox::USER_LIMITED) != sandbox::SBOX_ALL_OK)
-    return false;
-
-  auto permitted_paths =
-      GetContentClient()->browser()->GetNetworkContextsParentDirectory();
-
-  for (auto permitted_path : permitted_paths) {
-    permitted_path = permitted_path.Append(FILE_PATH_LITERAL("*"));
-    if (policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
-                        sandbox::TargetPolicy::FILES_ALLOW_ANY,
-                        permitted_path.value().c_str()) !=
-        sandbox::SBOX_ALL_OK) {
-      return false;
-    }
-  }
-
-  // DNS needs to read policies which are ACLed NT AUTHORITY\Authenticated Users
-  // Allow ReadKey unlike the rest of HKLM which is BUILTIN\Users Allow ReadKey.
-  if (policy->AddRule(
-          sandbox::TargetPolicy::SUBSYS_REGISTRY,
-          sandbox::TargetPolicy::REG_ALLOW_READONLY,
-          L"HKEY_LOCAL_MACHINE\\Software\\Policies\\Microsoft\\*") !=
-      sandbox::SBOX_ALL_OK) {
+  // LPAC sandbox is enabled, so do not use a restricted token.
+  if (sandbox::SBOX_ALL_OK !=
+      policy->SetTokenLevel(sandbox::USER_UNPROTECTED,
+                            sandbox::USER_UNPROTECTED)) {
     return false;
   }
 
-  // Needed for ::GetAdaptersAddresses calls in //net.
-  if (policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
-                      sandbox::TargetPolicy::FILES_ALLOW_READONLY,
-                      L"\\DEVICE\\NETBT_TCPIP\\*") != sandbox::SBOX_ALL_OK) {
+  // Network Sandbox in LPAC sandbox needs access to its data files. These
+  // files are marked on disk with an ACE that permits this access.
+  auto lpac_capability =
+      GetContentClient()->browser()->GetLPACCapabilityNameForNetworkService();
+  if (lpac_capability.empty())
     return false;
-  }
+  auto app_container = policy->GetAppContainer();
+  if (!app_container)
+    return false;
+  app_container->AddCapability(lpac_capability.c_str());
+
+  // All other app container policies are set in
+  // SandboxWin::StartSandboxedProcess.
   return true;
 }
 
@@ -142,7 +102,7 @@
 bool UtilitySandboxedProcessLauncherDelegate::GetAppContainerId(
     std::string* appcontainer_id) {
   if (sandbox_type_ == sandbox::policy::SandboxType::kNetwork) {
-    DCHECK(sandbox::policy::features::IsNetworkServiceSandboxLPACEnabled());
+    DCHECK(sandbox::policy::features::IsWinNetworkServiceSandboxEnabled());
     *appcontainer_id = base::WideToUTF8(cmd_line_.GetProgram().value());
     return true;
   }
@@ -170,9 +130,9 @@
       // of specific LPAC sandbox policies.
       return true;
     case sandbox::policy::SandboxType::kNetwork:
-      // If LPAC is enabled for network sandbox then LPAC-specific policy is set
-      // elsewhere.
-      return sandbox::policy::features::IsNetworkServiceSandboxLPACEnabled();
+      // An LPAC specific policy for network service is set elsewhere.
+      DCHECK(sandbox::policy::features::IsWinNetworkServiceSandboxEnabled());
+      return true;
     default:
       return false;
   }
diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn
index 8561b088..84568bc 100644
--- a/content/public/android/BUILD.gn
+++ b/content/public/android/BUILD.gn
@@ -99,6 +99,7 @@
     "java/src/org/chromium/content/app/PrivilegedProcessService3.java",
     "java/src/org/chromium/content/app/PrivilegedProcessService4.java",
     "java/src/org/chromium/content/app/SandboxedProcessService.java",
+    "java/src/org/chromium/content/app/ZygotePreload.java",
     "java/src/org/chromium/content/browser/BrowserStartupControllerImpl.java",
     "java/src/org/chromium/content/browser/ChildProcessCreationParamsImpl.java",
     "java/src/org/chromium/content/browser/ContentChildProcessConstants.java",
@@ -109,7 +110,6 @@
     "java/src/org/chromium/content/common/ContentSwitchUtils.java",
     "java/src/org/chromium/content/common/SurfaceWrapper.java",
     "java/src/org/chromium/content_public/app/ChildProcessServiceFactory.java",
-    "java/src/org/chromium/content_public/app/ZygotePreload.java",
     "java/src/org/chromium/content_public/browser/BrowserStartupController.java",
     "java/src/org/chromium/content_public/browser/BrowserTaskExecutor.java",
     "java/src/org/chromium/content_public/browser/ChildProcessCreationParams.java",
diff --git a/content/public/android/java/src/org/chromium/content_public/app/ZygotePreload.java b/content/public/android/java/src/org/chromium/content/app/ZygotePreload.java
similarity index 74%
rename from content/public/android/java/src/org/chromium/content_public/app/ZygotePreload.java
rename to content/public/android/java/src/org/chromium/content/app/ZygotePreload.java
index 92e30da..83067291 100644
--- a/content/public/android/java/src/org/chromium/content_public/app/ZygotePreload.java
+++ b/content/public/android/java/src/org/chromium/content/app/ZygotePreload.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.content_public.app;
+package org.chromium.content.app;
 
 import android.annotation.SuppressLint;
 import android.annotation.TargetApi;
@@ -32,19 +32,13 @@
     @SuppressLint("Override")
     @Override
     public void doPreload(ApplicationInfo appInfo) {
-        // Non-trichrome zygotes always use the system linker.
-        doPreloadCommon(appInfo, /* useModernLinker= */ false);
-    }
-
-    protected final void doPreloadCommon(ApplicationInfo appInfo, boolean useModernLinker) {
-        // Using concatenation rather than %s to allow values to be inlined by R8.
-        Log.i(TAG,
-                "Loaded Zygote. version=" + VersionConstants.PRODUCT_VERSION
-                        + " minSdkVersion=" + BuildConfig.MIN_SDK_VERSION
-                        + " isBundle=" + BuildConfig.BUNDLES_SUPPORTED);
         try {
-            LibraryLoader.getInstance().setLinkerImplementation(
-                    /* useChromiumLinker= */ useModernLinker, useModernLinker);
+            // Using concatenation rather than %s to allow values to be inlined by R8.
+            Log.i(TAG,
+                    "Loaded Zygote. version=" + VersionConstants.PRODUCT_VERSION
+                            + " minSdkVersion=" + BuildConfig.MIN_SDK_VERSION
+                            + " isBundle=" + BuildConfig.BUNDLES_SUPPORTED);
+
             // The current thread time is the best approximation we have of the zygote start time
             // since Process.getStartUptimeMillis() is not reliable in the zygote process. This will
             // be the total CPU time the current thread has been running, and is reset on fork so
diff --git a/content/public/browser/BUILD.gn b/content/public/browser/BUILD.gn
index 55117b6..bfe324c 100644
--- a/content/public/browser/BUILD.gn
+++ b/content/public/browser/BUILD.gn
@@ -347,6 +347,7 @@
     "shared_worker_service.h",
     "site_instance.h",
     "site_instance_process_assignment.h",
+    "site_isolation_mode.h",
     "site_isolation_policy.cc",
     "site_isolation_policy.h",
     "sms_fetcher.h",
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc
index 0cf1f77..2256ce9 100644
--- a/content/public/browser/content_browser_client.cc
+++ b/content/public/browser/content_browser_client.cc
@@ -297,7 +297,8 @@
 #endif
 }
 
-bool ContentBrowserClient::ShouldDisableSiteIsolation() {
+bool ContentBrowserClient::ShouldDisableSiteIsolation(
+    SiteIsolationMode site_isolation_mode) {
   return false;
 }
 
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
index b6dae008..802c6bc 100644
--- a/content/public/browser/content_browser_client.h
+++ b/content/public/browser/content_browser_client.h
@@ -196,6 +196,7 @@
 
 namespace content {
 enum class PermissionType;
+enum class SiteIsolationMode;
 enum class SmsFetchFailureType;
 class AuthenticatorRequestClientDelegate;
 class BluetoothDelegate;
@@ -588,9 +589,14 @@
   // Allows the embedder to programmatically control whether Site Isolation
   // should be disabled.  Note that this takes precedence over
   // ShouldEnableStrictSiteIsolation() if both return true.
+  // `site_isolation_mode` specifies the site isolation mode to check; this
+  // allows strict site isolation and partial site isolation to be disabled
+  // according to different policies (e.g., different memory thresholds) on
+  // Android.
   //
   // Note that for correctness, the same value should be consistently returned.
-  virtual bool ShouldDisableSiteIsolation();
+  virtual bool ShouldDisableSiteIsolation(
+      SiteIsolationMode site_isolation_mode);
 
   // Retrieves names of any additional site isolation modes from the embedder.
   virtual std::vector<std::string> GetAdditionalSiteIsolationModes();
diff --git a/content/public/browser/site_isolation_mode.h b/content/public/browser/site_isolation_mode.h
new file mode 100644
index 0000000..e1894f1
--- /dev/null
+++ b/content/public/browser/site_isolation_mode.h
@@ -0,0 +1,25 @@
+// 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.
+
+#ifndef CONTENT_PUBLIC_BROWSER_SITE_ISOLATION_MODE_H_
+#define CONTENT_PUBLIC_BROWSER_SITE_ISOLATION_MODE_H_
+
+namespace content {
+
+// Refers to particular kinds of site isolation which may be active. This is
+// used to specify different memory thresholds for different kinds of site
+// isolation.
+enum class SiteIsolationMode {
+  // This specifies a mode where every site requires a dedicated process,
+  // a.k.a. --site-per-process.
+  kStrictSiteIsolation,
+  // This specifies modes where only some sites require a dedicated process.
+  // This is primarily used on Android and includes isolation of login sites
+  // and COOP sites.
+  kPartialSiteIsolation
+};
+
+}  // namespace content
+
+#endif  // CONTENT_PUBLIC_BROWSER_SITE_ISOLATION_MODE_H_
diff --git a/content/public/browser/site_isolation_policy.cc b/content/public/browser/site_isolation_policy.cc
index b0a3088c..f68a778 100644
--- a/content/public/browser/site_isolation_policy.cc
+++ b/content/public/browser/site_isolation_policy.cc
@@ -52,7 +52,7 @@
 }
 #endif
 
-bool IsSiteIsolationDisabled() {
+bool IsSiteIsolationDisabled(SiteIsolationMode site_isolation_mode) {
   if (IsDisableSiteIsolationFlagPresent()) {
     return true;
   }
@@ -67,7 +67,8 @@
   // Check with the embedder.  In particular, chrome/ uses this to disable site
   // isolation when below a memory threshold.
   return GetContentClient() &&
-         GetContentClient()->browser()->ShouldDisableSiteIsolation();
+         GetContentClient()->browser()->ShouldDisableSiteIsolation(
+             site_isolation_mode);
 }
 
 }  // namespace
@@ -79,7 +80,7 @@
     return true;
   }
 
-  if (IsSiteIsolationDisabled())
+  if (IsSiteIsolationDisabled(SiteIsolationMode::kStrictSiteIsolation))
     return false;
 
   // The switches above needs to be checked first, because if the
@@ -100,7 +101,7 @@
     return true;
   }
 
-  if (IsSiteIsolationDisabled())
+  if (IsSiteIsolationDisabled(SiteIsolationMode::kPartialSiteIsolation))
     return false;
 
   // The feature needs to be checked last, because checking the feature
@@ -123,7 +124,11 @@
 
   // TODO(wjmaclean): Figure out what should happen when this feature is
   // combined with --isolate-origins.
-  if (IsSiteIsolationDisabled())
+  //
+  // TODO(alexmos): For now, use the same memory threshold for strict origin
+  // isolation and strict site isolation.  In the future, strict origin
+  // isolation may need its own memory threshold.
+  if (IsSiteIsolationDisabled(SiteIsolationMode::kStrictSiteIsolation))
     return false;
 
   // The feature needs to be checked last, because checking the feature
@@ -139,12 +144,12 @@
 
 // static
 bool SiteIsolationPolicy::AreDynamicIsolatedOriginsEnabled() {
-  return !IsSiteIsolationDisabled();
+  return !IsSiteIsolationDisabled(SiteIsolationMode::kPartialSiteIsolation);
 }
 
 // static
 bool SiteIsolationPolicy::ArePreloadedIsolatedOriginsEnabled() {
-  if (IsSiteIsolationDisabled())
+  if (IsSiteIsolationDisabled(SiteIsolationMode::kPartialSiteIsolation))
     return false;
 
   // Currently, preloaded isolated origins are redundant when full site
@@ -165,7 +170,7 @@
 
   // Otherwise, if site isolation is disabled (e.g., on Android due to being
   // under a memory threshold), turn off opt-in origin isolation.
-  if (IsSiteIsolationDisabled())
+  if (IsSiteIsolationDisabled(SiteIsolationMode::kPartialSiteIsolation))
     return false;
 
   return IsOriginAgentClusterEnabled();
@@ -227,7 +232,7 @@
 
   // Check if site isolation modes are turned off (e.g., due to an opt-out
   // flag).
-  if (IsSiteIsolationDisabled())
+  if (IsSiteIsolationDisabled(SiteIsolationMode::kPartialSiteIsolation))
     return origins;
 
   // The feature needs to be checked after the opt-out, because checking the
diff --git a/content/public/browser/site_isolation_policy.h b/content/public/browser/site_isolation_policy.h
index 430bdc7..da0059e 100644
--- a/content/public/browser/site_isolation_policy.h
+++ b/content/public/browser/site_isolation_policy.h
@@ -12,6 +12,7 @@
 #include "base/macros.h"
 #include "base/strings/string_piece_forward.h"
 #include "content/common/content_export.h"
+#include "content/public/browser/site_isolation_mode.h"
 #include "url/origin.h"
 
 namespace content {
diff --git a/content/renderer/java/gin_java_bridge_value_converter_unittest.cc b/content/renderer/java/gin_java_bridge_value_converter_unittest.cc
index 08153854..82058249 100644
--- a/content/renderer/java/gin_java_bridge_value_converter_unittest.cc
+++ b/content/renderer/java/gin_java_bridge_value_converter_unittest.cc
@@ -16,6 +16,7 @@
 #include "v8/include/v8-array-buffer.h"
 #include "v8/include/v8-context.h"
 #include "v8/include/v8-isolate.h"
+#include "v8/include/v8-locker.h"
 #include "v8/include/v8-microtask-queue.h"
 #include "v8/include/v8-persistent-handle.h"
 #include "v8/include/v8-primitive.h"
@@ -32,6 +33,7 @@
 
  protected:
   void SetUp() override {
+    v8::Locker locked(isolate_);
     v8::HandleScope handle_scope(isolate_);
     v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate_);
     context_.Reset(isolate_, v8::Context::New(isolate_, NULL, global));
@@ -46,6 +48,7 @@
 };
 
 TEST_F(GinJavaBridgeValueConverterTest, BasicValues) {
+  v8::Locker locked(isolate_);
   v8::HandleScope handle_scope(isolate_);
   v8::Local<v8::Context> context =
       v8::Local<v8::Context>::New(isolate_, context_);
@@ -82,6 +85,7 @@
 }
 
 TEST_F(GinJavaBridgeValueConverterTest, ArrayBuffer) {
+  v8::Locker locked(isolate_);
   v8::HandleScope handle_scope(isolate_);
   v8::Local<v8::Context> context =
       v8::Local<v8::Context>::New(isolate_, context_);
@@ -103,6 +107,7 @@
 }
 
 TEST_F(GinJavaBridgeValueConverterTest, TypedArrays) {
+  v8::Locker locked(isolate_);
   v8::HandleScope handle_scope(isolate_);
   v8::Local<v8::Context> context =
       v8::Local<v8::Context>::New(isolate_, context_);
diff --git a/content/renderer/v8_value_converter_impl_unittest.cc b/content/renderer/v8_value_converter_impl_unittest.cc
index 4645d09..2582c2d 100644
--- a/content/renderer/v8_value_converter_impl_unittest.cc
+++ b/content/renderer/v8_value_converter_impl_unittest.cc
@@ -22,6 +22,7 @@
 #include "v8/include/v8-date.h"
 #include "v8/include/v8-isolate.h"
 #include "v8/include/v8-local-handle.h"
+#include "v8/include/v8-locker.h"
 #include "v8/include/v8-microtask-queue.h"
 #include "v8/include/v8-object.h"
 #include "v8/include/v8-persistent-handle.h"
@@ -75,6 +76,7 @@
 
  protected:
   void SetUp() override {
+    v8::Locker locked(isolate_);
     v8::HandleScope handle_scope(isolate_);
     v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate_);
     context_.Reset(isolate_, v8::Context::New(isolate_, nullptr, global));
@@ -286,6 +288,7 @@
       "  \"empty-list\": [], \n"
       "}");
 
+  v8::Locker locked(isolate_);
   v8::HandleScope handle_scope(isolate_);
   v8::Local<v8::Context> context =
       v8::Local<v8::Context>::New(isolate_, context_);
@@ -407,6 +410,7 @@
   std::unique_ptr<base::Value> original =
       base::test::ParseJsonDeprecated("{ \"foo.bar\": \"baz\" }");
 
+  v8::Locker locked(isolate_);
   v8::HandleScope handle_scope(isolate_);
   v8::Local<v8::Context> context =
       v8::Local<v8::Context>::New(isolate_, context_);
@@ -420,6 +424,7 @@
 }
 
 TEST_F(V8ValueConverterImplTest, ObjectExceptions) {
+  v8::Locker locked(isolate_);
   v8::HandleScope handle_scope(isolate_);
   v8::Local<v8::Context> context =
       v8::Local<v8::Context>::New(isolate_, context_);
@@ -464,6 +469,7 @@
 }
 
 TEST_F(V8ValueConverterImplTest, ArrayExceptions) {
+  v8::Locker locked(isolate_);
   v8::HandleScope handle_scope(isolate_);
   v8::Local<v8::Context> context =
       v8::Local<v8::Context>::New(isolate_, context_);
@@ -506,6 +512,7 @@
 }
 
 TEST_F(V8ValueConverterImplTest, WeirdTypes) {
+  v8::Locker locked(isolate_);
   v8::HandleScope handle_scope(isolate_);
   v8::Local<v8::Context> context =
       v8::Local<v8::Context>::New(isolate_, context_);
@@ -538,6 +545,7 @@
 }
 
 TEST_F(V8ValueConverterImplTest, Prototype) {
+  v8::Locker locked(isolate_);
   v8::HandleScope handle_scope(isolate_);
   v8::Local<v8::Context> context =
       v8::Local<v8::Context>::New(isolate_, context_);
@@ -563,6 +571,7 @@
   std::unique_ptr<base::Value> original =
       base::test::ParseJsonDeprecated("{ \"foo\": \"good value\" }");
 
+  v8::Locker locked(isolate_);
   v8::HandleScope handle_scope(isolate_);
   v8::Local<v8::Context> context =
       v8::Local<v8::Context>::New(isolate_, context_);
@@ -631,6 +640,7 @@
   std::unique_ptr<base::Value> original =
       base::test::ParseJsonDeprecated("[100, 200, 300]");
 
+  v8::Locker locked(isolate_);
   v8::HandleScope handle_scope(isolate_);
   v8::Local<v8::Context> context =
       v8::Local<v8::Context>::New(isolate_, context_);
@@ -696,6 +706,7 @@
 }
 
 TEST_F(V8ValueConverterImplTest, StripNullFromObjects) {
+  v8::Locker locked(isolate_);
   v8::HandleScope handle_scope(isolate_);
   v8::Local<v8::Context> context =
       v8::Local<v8::Context>::New(isolate_, context_);
@@ -719,6 +730,7 @@
 }
 
 TEST_F(V8ValueConverterImplTest, RecursiveObjects) {
+  v8::Locker locked(isolate_);
   v8::HandleScope handle_scope(isolate_);
   v8::Local<v8::Context> context =
       v8::Local<v8::Context>::New(isolate_, context_);
@@ -764,6 +776,7 @@
 }
 
 TEST_F(V8ValueConverterImplTest, WeirdProperties) {
+  v8::Locker locked(isolate_);
   v8::HandleScope handle_scope(isolate_);
   v8::Local<v8::Context> context =
       v8::Local<v8::Context>::New(isolate_, context_);
@@ -801,6 +814,7 @@
 }
 
 TEST_F(V8ValueConverterImplTest, ArrayGetters) {
+  v8::Locker locked(isolate_);
   v8::HandleScope handle_scope(isolate_);
   v8::Local<v8::Context> context =
       v8::Local<v8::Context>::New(isolate_, context_);
@@ -824,6 +838,7 @@
 }
 
 TEST_F(V8ValueConverterImplTest, UndefinedValueBehavior) {
+  v8::Locker locked(isolate_);
   v8::HandleScope handle_scope(isolate_);
   v8::Local<v8::Context> context =
       v8::Local<v8::Context>::New(isolate_, context_);
@@ -875,6 +890,7 @@
 }
 
 TEST_F(V8ValueConverterImplTest, ObjectsWithClashingIdentityHash) {
+  v8::Locker locked(isolate_);
   v8::HandleScope handle_scope(isolate_);
   v8::Local<v8::Context> context =
       v8::Local<v8::Context>::New(isolate_, context_);
@@ -911,6 +927,7 @@
 }
 
 TEST_F(V8ValueConverterImplTest, DetectCycles) {
+  v8::Locker locked(isolate_);
   v8::HandleScope handle_scope(isolate_);
   v8::Local<v8::Context> context =
       v8::Local<v8::Context>::New(isolate_, context_);
@@ -960,6 +977,7 @@
 
 // Tests that reused object values with no cycles do not get nullified.
 TEST_F(V8ValueConverterImplTest, ReuseObjects) {
+  v8::Locker locked(isolate_);
   v8::HandleScope handle_scope(isolate_);
   v8::Local<v8::Context> context =
       v8::Local<v8::Context>::New(isolate_, context_);
@@ -1021,6 +1039,7 @@
 }
 
 TEST_F(V8ValueConverterImplTest, MaxRecursionDepth) {
+  v8::Locker locked(isolate_);
   v8::HandleScope handle_scope(isolate_);
   v8::Local<v8::Context> context =
       v8::Local<v8::Context>::New(isolate_, context_);
@@ -1067,6 +1086,7 @@
 }
 
 TEST_F(V8ValueConverterImplTest, NegativeZero) {
+  v8::Locker locked(isolate_);
   v8::HandleScope handle_scope(isolate_);
   v8::Local<v8::Context> context =
       v8::Local<v8::Context>::New(isolate_, context_);
@@ -1136,6 +1156,7 @@
 };
 
 TEST_F(V8ValueConverterImplTest, StrategyOverrides) {
+  v8::Locker locked(isolate_);
   v8::HandleScope handle_scope(isolate_);
   v8::Local<v8::Context> context =
       v8::Local<v8::Context>::New(isolate_, context_);
@@ -1213,6 +1234,7 @@
 // Verify that having a strategy that fallbacks to default behaviour
 // actually preserves it.
 TEST_F(V8ValueConverterImplTest, StrategyBypass) {
+  v8::Locker locked(isolate_);
   v8::HandleScope handle_scope(isolate_);
   v8::Local<v8::Context> context =
       v8::Local<v8::Context>::New(isolate_, context_);
diff --git a/content/shell/android/shell_apk/AndroidManifest.xml.jinja2 b/content/shell/android/shell_apk/AndroidManifest.xml.jinja2
index d89c3906..2722488 100644
--- a/content/shell/android/shell_apk/AndroidManifest.xml.jinja2
+++ b/content/shell/android/shell_apk/AndroidManifest.xml.jinja2
@@ -24,7 +24,7 @@
 
     <application android:name="org.chromium.content_shell_apk.ContentShellApplication"
             android:icon="@mipmap/app_icon"
-            android:zygotePreloadName="org.chromium.content_public.app.ZygotePreload"
+            android:zygotePreloadName="org.chromium.content.app.ZygotePreload"
             android:label="{% block application_label %}Content Shell{% endblock %}">
         <activity android:name="org.chromium.content_shell_apk.ContentShellActivity"
                   android:launchMode="singleTask"
diff --git a/content/test/gpu/gpu_tests/color_profile_manager_mac.py b/content/test/gpu/gpu_tests/color_profile_manager_mac.py
index c1714e3..19d451d 100644
--- a/content/test/gpu/gpu_tests/color_profile_manager_mac.py
+++ b/content/test/gpu/gpu_tests/color_profile_manager_mac.py
@@ -68,7 +68,7 @@
 def GetSRGBProfileURL():
   srgb_profile_path = '/System/Library/ColorSync/Profiles/sRGB Profile.icc'
   srgb_profile_url = Foundation.CFURLCreateFromFileSystemRepresentation(
-      None, srgb_profile_path, len(srgb_profile_path), False)
+      None, srgb_profile_path.encode('utf-8'), len(srgb_profile_path), False)
   return srgb_profile_url
 
 
diff --git a/content/test/gpu/gpu_tests/gpu_helper.py b/content/test/gpu/gpu_tests/gpu_helper.py
index 60fcda7..6064658 100644
--- a/content/test/gpu/gpu_tests/gpu_helper.py
+++ b/content/test/gpu/gpu_tests/gpu_helper.py
@@ -177,7 +177,7 @@
   # display server.
   if browser_type in REMOTE_BROWSER_TYPES:
     return None
-  if sys.platform == 'linux2':
+  if sys.platform.startswith('linux'):
     if 'WAYLAND_DISPLAY' in os.environ:
       return 'display-server-wayland'
     else:
diff --git a/content/test/gpu/gpu_tests/gpu_integration_test_unittest.py b/content/test/gpu/gpu_tests/gpu_integration_test_unittest.py
index 9761ad95..3992e01b 100644
--- a/content/test/gpu/gpu_tests/gpu_integration_test_unittest.py
+++ b/content/test/gpu/gpu_tests/gpu_integration_test_unittest.py
@@ -262,6 +262,7 @@
       for t in tags:
         self.assertFalse(t.startswith('display-server'))
 
+    # Python 2's return value.
     with mock.patch('sys.platform', 'linux2'):
       tags = gpu_integration_test.GpuIntegrationTest.GetPlatformTags(browser)
       self.assertIn('display-server-x', tags)
@@ -270,6 +271,16 @@
       tags = gpu_integration_test.GpuIntegrationTest.GetPlatformTags(browser)
       self.assertIn('display-server-wayland', tags)
 
+    # Python 3's return value.
+    with mock.patch('sys.platform', 'linux'):
+      del os.environ['WAYLAND_DISPLAY']
+      tags = gpu_integration_test.GpuIntegrationTest.GetPlatformTags(browser)
+      self.assertIn('display-server-x', tags)
+
+      os.environ['WAYLAND_DISPLAY'] = 'wayland-0'
+      tags = gpu_integration_test.GpuIntegrationTest.GetPlatformTags(browser)
+      self.assertIn('display-server-wayland', tags)
+
   def testSimpleIntegrationTest(self):
     test_args = _IntegrationTestArgs('simple_integration_unittest')
     test_args.failures = [
diff --git a/content/test/gpu/gpu_tests/info_collection_test.py b/content/test/gpu/gpu_tests/info_collection_test.py
index 5dd9aa8..ac1c3f5 100644
--- a/content/test/gpu/gpu_tests/info_collection_test.py
+++ b/content/test/gpu/gpu_tests/info_collection_test.py
@@ -109,7 +109,7 @@
       aux_attributes = test_args.gpu.aux_attributes
       if not aux_attributes:
         self.fail('GPU info does not have aux_attributes.')
-      for field, expected in overlay_bot_config.iteritems():
+      for field, expected in overlay_bot_config.items():
         detected = aux_attributes.get(field, 'NONE')
         if expected != detected:
           self.fail(
@@ -133,7 +133,7 @@
         self.fail('GPU info does not have aux_attributes.')
 
       dx12_vulkan_bot_config = self.GetDx12VulkanBotConfig()
-      for field, expected in dx12_vulkan_bot_config.iteritems():
+      for field, expected in dx12_vulkan_bot_config.items():
         detected = aux_attributes.get(field)
         if expected != detected:
           self.fail(
diff --git a/content/test/gpu/gpu_tests/ipg_utils.py b/content/test/gpu/gpu_tests/ipg_utils.py
index 78cc97d7..dd1e6a8 100644
--- a/content/test/gpu/gpu_tests/ipg_utils.py
+++ b/content/test/gpu/gpu_tests/ipg_utils.py
@@ -163,7 +163,7 @@
       the 'mean' and 'stdev' for the metric.
     """
     summary = {}
-    for key, data in metrics.iteritems():
+    for key, data in metrics.items():
       assert data and len(data) > 1
       n = len(data)
       if outliers > 0:
diff --git a/content/test/gpu/gpu_tests/maps_integration_test.py b/content/test/gpu/gpu_tests/maps_integration_test.py
index a11ac07f..deb3ac94e 100644
--- a/content/test/gpu/gpu_tests/maps_integration_test.py
+++ b/content/test/gpu/gpu_tests/maps_integration_test.py
@@ -113,10 +113,13 @@
     # The bottom corners of Mac screenshots have black triangles due to the
     # rounded corners of Mac windows. So, crop the bottom few rows off now to
     # get rid of those. The triangles appear to be 5 pixels wide and tall
-    # regardless of DPI, so 10 pixels should be sufficient.
+    # regardless of DPI, so 10 pixels should be sufficient. However, when
+    # running under Python 3, 10 isn't quite enough for some reason, so use
+    # 20 instead.
     if self.browser.platform.GetOSName() == 'mac':
-      img_height, img_width = screenshot.shape[:2]
-      screenshot = image_util.Crop(screenshot, 0, 0, img_width, img_height - 10)
+      img_height = image_util.Height(screenshot)
+      img_width = image_util.Width(screenshot)
+      screenshot = image_util.Crop(screenshot, 0, 0, img_width, img_height - 20)
     x1, y1, x2, y2 = _GetCropBoundaries(screenshot)
     screenshot = image_util.Crop(screenshot, x1, y1, x2 - x1, y2 - y1)
 
@@ -163,7 +166,8 @@
     A 4-tuple (x1, y1, x2, y2) denoting the top left and bottom right
     coordinates to crop to.
   """
-  img_height, img_width = screenshot.shape[:2]
+  img_height = image_util.Height(screenshot)
+  img_width = image_util.Width(screenshot)
 
   def RowIsWhite(row):
     for col in range(img_width):
diff --git a/content/test/gpu/unexpected_pass_finder.py b/content/test/gpu/unexpected_pass_finder.py
index 1497765c..7e94185f 100755
--- a/content/test/gpu/unexpected_pass_finder.py
+++ b/content/test/gpu/unexpected_pass_finder.py
@@ -206,7 +206,7 @@
   stale_message = ''
   if args.remove_stale_expectations:
     stale_expectations = []
-    for _, expectation_map in stale.iteritems():
+    for _, expectation_map in stale.items():
       stale_expectations.extend(expectation_map.keys())
     stale_expectations.extend(unused_expectations)
     affected_urls |= expectations_instance.RemoveExpectationsFromFile(
diff --git a/content/test/test_web_contents.cc b/content/test/test_web_contents.cc
index b07c700..981542dd 100644
--- a/content/test/test_web_contents.cc
+++ b/content/test/test_web_contents.cc
@@ -411,9 +411,9 @@
 }
 
 int TestWebContents::AddPrerender(const GURL& url) {
-  auto attributes = blink::mojom::PrerenderAttributes::New();
-  attributes->url = url;
-  return GetPrerenderHostRegistry()->CreateAndStartHost(std::move(attributes),
+  PrerenderAttributes attributes{url, PrerenderTriggerType::kSpeculationRule,
+                                 Referrer()};
+  return GetPrerenderHostRegistry()->CreateAndStartHost(attributes,
                                                         *GetMainFrame());
 }
 
diff --git a/extensions/browser/BUILD.gn b/extensions/browser/BUILD.gn
index 2d1ba96..70f1a9b2 100644
--- a/extensions/browser/BUILD.gn
+++ b/extensions/browser/BUILD.gn
@@ -151,6 +151,7 @@
     "api/hid/hid_connection_resource.h",
     "api/hid/hid_device_manager.cc",
     "api/hid/hid_device_manager.h",
+    "api/scripting/constants.h",
     "api/system_display/display_info_provider.cc",
     "api/system_display/display_info_provider.h",
     "api/system_display/system_display_api.cc",
diff --git a/extensions/browser/api/scripting/constants.h b/extensions/browser/api/scripting/constants.h
new file mode 100644
index 0000000..c7ba4ebe
--- /dev/null
+++ b/extensions/browser/api/scripting/constants.h
@@ -0,0 +1,31 @@
+// 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.
+
+#ifndef EXTENSIONS_BROWSER_API_SCRIPTING_CONSTANTS_H_
+#define EXTENSIONS_BROWSER_API_SCRIPTING_CONSTANTS_H_
+
+namespace extensions {
+namespace scripting {
+
+// TODO(crbug.com/1168627): The can_execute_script_everywhere flag is currently
+// only used by the legacy version Chromevox extension. We can assume it will
+// always be false here, but it may be added back if needed.
+constexpr bool kScriptsCanExecuteEverywhere = false;
+
+// The all_urls_includes_chrome_urls flag is only true for the legacy ChromeVox
+// extension, which does not call this API. Therefore we can assume it to be
+// always false.
+constexpr bool kAllUrlsIncludesChromeUrls = false;
+
+// The key for the field in the extension's StateStore for dynamic content
+// script metadata that persists across sessions.
+constexpr char kRegisteredScriptsStorageKey[] = "dynamic_scripts";
+
+// The key for storing a dynamic content script's id.
+constexpr char kId[] = "id";
+
+}  // namespace scripting
+}  // namespace extensions
+
+#endif  // EXTENSIONS_BROWSER_API_SCRIPTING_CONSTANTS_H_
diff --git a/extensions/browser/extension_system.h b/extensions/browser/extension_system.h
index 24f0ca5..a2a15673 100644
--- a/extensions/browser/extension_system.h
+++ b/extensions/browser/extension_system.h
@@ -97,6 +97,9 @@
   // The rules store is created at startup.
   virtual StateStore* rules_store() = 0;
 
+  // The dynamic user scripts store is created at startup.
+  virtual StateStore* dynamic_user_scripts_store() = 0;
+
   // Returns the |ValueStore| factory created at startup.
   virtual scoped_refptr<value_store::ValueStoreFactory> store_factory() = 0;
 
diff --git a/extensions/browser/extension_user_script_loader.cc b/extensions/browser/extension_user_script_loader.cc
index 02b87fe..209df94 100644
--- a/extensions/browser/extension_user_script_loader.cc
+++ b/extensions/browser/extension_user_script_loader.cc
@@ -16,6 +16,7 @@
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "base/containers/contains.h"
+#include "base/containers/cxx20_erase_set.h"
 #include "base/containers/cxx20_erase_vector.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
@@ -29,14 +30,19 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/render_process_host.h"
+#include "extensions/browser/api/scripting/constants.h"
 #include "extensions/browser/component_extension_resource_manager.h"
 #include "extensions/browser/content_verifier.h"
 #include "extensions/browser/extension_file_task_runner.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/browser/extensions_browser_client.h"
+#include "extensions/browser/state_store.h"
+#include "extensions/common/api/content_scripts.h"
 #include "extensions/common/file_util.h"
+#include "extensions/common/manifest_handlers/content_scripts_handler.h"
 #include "extensions/common/manifest_handlers/default_locale_handler.h"
 #include "extensions/common/message_bundle.h"
+#include "extensions/common/utils/content_script_utils.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/base/resource/resource_bundle.h"
 
@@ -223,21 +229,121 @@
                                 std::move(memory)));
 }
 
+UserScriptList ConvertValueToScripts(const Extension& extension,
+                                     const base::Value& list) {
+  const int valid_schemes = UserScript::ValidUserScriptSchemes(
+      scripting::kScriptsCanExecuteEverywhere);
+
+  UserScriptList scripts;
+  for (const base::Value& value : list.GetList()) {
+    std::u16string error;
+    std::unique_ptr<api::content_scripts::ContentScript> content_script =
+        api::content_scripts::ContentScript::FromValue(value, &error);
+
+    if (!content_script)
+      continue;
+
+    std::unique_ptr<UserScript> script = std::make_unique<UserScript>();
+    const auto* dict = static_cast<const base::DictionaryValue*>(&value);
+    const base::Value* id_value = dict->FindKey(scripting::kId);
+    auto* id = id_value->GetIfString();
+    if (!id)
+      continue;
+
+    script->set_id(*id);
+    script->set_host_id(
+        mojom::HostID(mojom::HostID::HostType::kExtensions, extension.id()));
+
+    if (content_script->all_frames)
+      script->set_match_all_frames(*content_script->all_frames);
+    script->set_run_location(
+        script_parsing::ConvertManifestRunLocation(content_script->run_at));
+
+    if (!script_parsing::ParseMatchPatterns(
+            content_script->matches, content_script->exclude_matches.get(),
+            /*definition_index=*/0, extension.creation_flags(),
+            scripting::kScriptsCanExecuteEverywhere, valid_schemes,
+            scripting::kAllUrlsIncludesChromeUrls, script.get(), &error,
+            /*wants_file_access=*/nullptr)) {
+      continue;
+    }
+
+    if (!script_parsing::ParseFileSources(
+            &extension, content_script->js.get(), content_script->css.get(),
+            /*definition_index=*/0, script.get(), &error)) {
+      continue;
+    }
+
+    scripts.push_back(std::move(script));
+  }
+
+  return scripts;
+}
+
+// TODO(crbug.com/1248314): Eventually use
+// api::scripting::RegisteredContentScript instead as an intermediate type which
+// then gets converted to base::Value.
+api::content_scripts::ContentScript CreateContentScriptObject(
+    const UserScript& script) {
+  api::content_scripts::ContentScript content_script;
+
+  content_script.matches.reserve(script.url_patterns().size());
+  for (const URLPattern& pattern : script.url_patterns())
+    content_script.matches.push_back(pattern.GetAsString());
+
+  if (!script.exclude_url_patterns().is_empty()) {
+    content_script.exclude_matches =
+        std::make_unique<std::vector<std::string>>();
+    content_script.exclude_matches->reserve(
+        script.exclude_url_patterns().size());
+    for (const URLPattern& pattern : script.exclude_url_patterns())
+      content_script.exclude_matches->push_back(pattern.GetAsString());
+  }
+
+  // File paths may be normalized in the returned object and can differ slightly
+  // compared to what was originally passed into registerContentScripts.
+  if (!script.js_scripts().empty()) {
+    content_script.js = std::make_unique<std::vector<std::string>>();
+    content_script.js->reserve(script.js_scripts().size());
+    for (const auto& js_script : script.js_scripts())
+      content_script.js->push_back(js_script->relative_path().AsUTF8Unsafe());
+  }
+
+  if (!script.css_scripts().empty()) {
+    content_script.css = std::make_unique<std::vector<std::string>>();
+    content_script.css->reserve(script.css_scripts().size());
+    for (const auto& css_script : script.css_scripts())
+      content_script.css->push_back(css_script->relative_path().AsUTF8Unsafe());
+  }
+
+  content_script.all_frames = std::make_unique<bool>(script.match_all_frames());
+  content_script.match_origin_as_fallback =
+      std::make_unique<bool>(script.match_origin_as_fallback() ==
+                             MatchOriginAsFallbackBehavior::kAlways);
+
+  content_script.run_at =
+      script_parsing::ConvertRunLocationToManifestType(script.run_location());
+  return content_script;
+}
+
 }  // namespace
 
 ExtensionUserScriptLoader::ExtensionUserScriptLoader(
     BrowserContext* browser_context,
     const Extension& extension,
+    StateStore* state_store,
     bool listen_for_extension_system_loaded)
     : ExtensionUserScriptLoader(
           browser_context,
           extension,
+          state_store,
           listen_for_extension_system_loaded,
           ExtensionSystem::Get(browser_context)->content_verifier()) {}
 
 ExtensionUserScriptLoader::ExtensionUserScriptLoader(
     BrowserContext* browser_context,
     const Extension& extension,
+    StateStore* state_store,
     bool listen_for_extension_system_loaded,
     scoped_refptr<ContentVerifier> content_verifier)
     : UserScriptLoader(
@@ -246,6 +352,7 @@
       host_info_({extension.path(), LocaleInfo::GetDefaultLocale(&extension),
                   extension_l10n_util::GetGzippedMessagesPermissionForExtension(
                       &extension)}),
+      helper_(browser_context, extension.id(), state_store),
       content_verifier_(std::move(content_verifier)) {
   if (listen_for_extension_system_loaded) {
     ExtensionSystem::Get(browser_context)
@@ -274,8 +381,23 @@
     pending_dynamic_script_ids_.erase(id);
 }
 
+void ExtensionUserScriptLoader::AddScriptsForExtensionLoad(
+    std::unique_ptr<UserScriptList> manifest_scripts,
+    UserScriptLoader::ScriptsLoadedCallback callback) {
+  AddScripts(std::move(manifest_scripts), std::move(callback));
+
+  // Manifest scripts and persistent dynamic scripts are not loaded as part of
+  // the same list to ensure `callback` will be not orphaned while persistent
+  // scripts are being fetched, which prevents `callback` from never being
+  // called if the extension is unloaded early.
+  helper_.GetDynamicScripts(base::BindOnce(
+      &ExtensionUserScriptLoader::OnInitialDynamicScriptsReadFromStateStore,
+      weak_factory_.GetWeakPtr()));
+}
+
 void ExtensionUserScriptLoader::AddDynamicScripts(
     std::unique_ptr<UserScriptList> scripts,
+    std::set<std::string> persistent_script_ids,
     DynamicScriptsModifiedCallback callback) {
   auto scripts_metadata = std::make_unique<UserScriptList>();
   for (const std::unique_ptr<UserScript>& script : *scripts) {
@@ -291,10 +413,11 @@
     return;
   }
 
-  AddScripts(std::move(scripts),
-             base::BindOnce(&ExtensionUserScriptLoader::OnDynamicScriptsAdded,
-                            weak_factory_.GetWeakPtr(),
-                            std::move(scripts_metadata), std::move(callback)));
+  AddScripts(
+      std::move(scripts),
+      base::BindOnce(&ExtensionUserScriptLoader::OnDynamicScriptsAdded,
+                     weak_factory_.GetWeakPtr(), std::move(scripts_metadata),
+                     std::move(persistent_script_ids), std::move(callback)));
 }
 
 void ExtensionUserScriptLoader::RemoveDynamicScripts(
@@ -320,7 +443,7 @@
   RemoveDynamicScripts(GetDynamicScriptIDs(), std::move(callback));
 }
 
-std::set<std::string> ExtensionUserScriptLoader::GetDynamicScriptIDs() {
+std::set<std::string> ExtensionUserScriptLoader::GetDynamicScriptIDs() const {
   std::set<std::string> dynamic_script_ids;
   dynamic_script_ids.insert(pending_dynamic_script_ids_.begin(),
                             pending_dynamic_script_ids_.end());
@@ -331,10 +454,16 @@
   return dynamic_script_ids;
 }
 
-const UserScriptList& ExtensionUserScriptLoader::GetLoadedDynamicScripts() {
+const UserScriptList& ExtensionUserScriptLoader::GetLoadedDynamicScripts()
+    const {
   return loaded_dynamic_scripts_;
 }
 
+std::set<std::string> ExtensionUserScriptLoader::GetPersistentDynamicScriptIDs()
+    const {
+  return persistent_dynamic_script_ids_;
+}
+
 std::unique_ptr<UserScriptList> ExtensionUserScriptLoader::LoadScriptsForTest(
     std::unique_ptr<UserScriptList> user_scripts) {
   std::set<std::string> added_script_ids;
@@ -361,6 +490,73 @@
   return result;
 }
 
+ExtensionUserScriptLoader::DynamicScriptsStorageHelper::
+    DynamicScriptsStorageHelper(BrowserContext* browser_context,
+                                const ExtensionId& extension_id,
+                                StateStore* state_store)
+    : browser_context_(browser_context),
+      extension_id_(extension_id),
+      state_store_(state_store) {}
+ExtensionUserScriptLoader::DynamicScriptsStorageHelper::
+    ~DynamicScriptsStorageHelper() = default;
+
+void ExtensionUserScriptLoader::DynamicScriptsStorageHelper::GetDynamicScripts(
+    DynamicScriptsReadCallback callback) {
+  if (!state_store_) {
+    std::move(callback).Run(UserScriptList());
+    return;
+  }
+
+  state_store_->GetExtensionValue(
+      extension_id_, scripting::kRegisteredScriptsStorageKey,
+      base::BindOnce(&ExtensionUserScriptLoader::DynamicScriptsStorageHelper::
+                         OnDynamicScriptsReadFromStorage,
+                     weak_factory_.GetWeakPtr(), std::move(callback)));
+}
+
+void ExtensionUserScriptLoader::DynamicScriptsStorageHelper::SetDynamicScripts(
+    const UserScriptList& scripts,
+    const std::set<std::string>& persistent_dynamic_script_ids) {
+  if (!state_store_)
+    return;
+
+  auto scripts_value = std::make_unique<base::Value>(base::Value::Type::LIST);
+  for (const std::unique_ptr<UserScript>& script : scripts) {
+    if (!base::Contains(persistent_dynamic_script_ids, script->id()))
+      continue;
+
+    base::DictionaryValue value =
+        std::move(*CreateContentScriptObject(*script).ToValue());
+    value.SetStringPath(scripting::kId, script->id());
+
+    scripts_value->Append(std::move(value));
+  }
+
+  state_store_->SetExtensionValue(extension_id_,
+                                  scripting::kRegisteredScriptsStorageKey,
+                                  std::move(scripts_value));
+}
+
+void ExtensionUserScriptLoader::DynamicScriptsStorageHelper::
+    OnDynamicScriptsReadFromStorage(DynamicScriptsReadCallback callback,
+                                    std::unique_ptr<base::Value> value) {
+  const Extension* extension = ExtensionRegistry::Get(browser_context_)
+                                   ->enabled_extensions()
+                                   .GetByID(extension_id_);
+  DCHECK(extension) << "The ExtensionUserScriptLoader should have been cleaned "
+                       "up if the extension was disabled";
+
+  UserScriptList scripts;
+  if (value && value->type() == base::Value::Type::LIST) {
+    UserScriptList dynamic_scripts = ConvertValueToScripts(*extension, *value);
+    scripts.insert(scripts.end(),
+                   std::make_move_iterator(dynamic_scripts.begin()),
+                   std::make_move_iterator(dynamic_scripts.end()));
+  }
+
+  std::move(callback).Run(std::move(scripts));
+}
+
 void ExtensionUserScriptLoader::LoadScripts(
     std::unique_ptr<UserScriptList> user_scripts,
     const std::set<std::string>& added_script_ids,
@@ -386,8 +582,46 @@
   SetReady(true);
 }
 
+void ExtensionUserScriptLoader::OnInitialDynamicScriptsReadFromStateStore(
+    UserScriptList initial_dynamic_scripts) {
+  auto dynamic_scripts_metadata = std::make_unique<UserScriptList>();
+  auto scripts = std::make_unique<UserScriptList>();
+  for (const std::unique_ptr<UserScript>& script : initial_dynamic_scripts) {
+    dynamic_scripts_metadata->push_back(UserScript::CopyMetadataFrom(*script));
+    pending_dynamic_script_ids_.insert(script->id());
+  }
+
+  scripts->insert(scripts->end(),
+                  std::make_move_iterator(initial_dynamic_scripts.begin()),
+                  std::make_move_iterator(initial_dynamic_scripts.end()));
+
+  AddScripts(
+      std::move(scripts),
+      base::BindOnce(&ExtensionUserScriptLoader::OnInitialDynamicScriptsLoaded,
+                     weak_factory_.GetWeakPtr(),
+                     std::move(dynamic_scripts_metadata)));
+}
+
+void ExtensionUserScriptLoader::OnInitialDynamicScriptsLoaded(
+    std::unique_ptr<UserScriptList> initial_dynamic_scripts,
+    UserScriptLoader* loader,
+    const absl::optional<std::string>& error) {
+  for (const std::unique_ptr<UserScript>& script : *initial_dynamic_scripts)
+    pending_dynamic_script_ids_.erase(script->id());
+
+  if (!error.has_value()) {
+    for (const std::unique_ptr<UserScript>& script : *initial_dynamic_scripts)
+      persistent_dynamic_script_ids_.insert(script->id());
+    loaded_dynamic_scripts_.insert(
+        loaded_dynamic_scripts_.end(),
+        std::make_move_iterator(initial_dynamic_scripts->begin()),
+        std::make_move_iterator(initial_dynamic_scripts->end()));
+  }
+}
+
 void ExtensionUserScriptLoader::OnDynamicScriptsAdded(
     std::unique_ptr<UserScriptList> added_scripts,
+    std::set<std::string> new_persistent_script_ids,
     DynamicScriptsModifiedCallback callback,
     UserScriptLoader* loader,
     const absl::optional<std::string>& error) {
@@ -403,6 +637,13 @@
         loaded_dynamic_scripts_.end(),
         std::make_move_iterator(added_scripts->begin()),
         std::make_move_iterator(added_scripts->end()));
+
+    persistent_dynamic_script_ids_.insert(
+        std::make_move_iterator(new_persistent_script_ids.begin()),
+        std::make_move_iterator(new_persistent_script_ids.end()));
+
+    helper_.SetDynamicScripts(loaded_dynamic_scripts_,
+                              persistent_dynamic_script_ids_);
   }
 
   std::move(callback).Run(error);
@@ -422,6 +663,14 @@
         [&removed_script_ids](const std::unique_ptr<UserScript>& script) {
           return base::Contains(removed_script_ids, script->id());
         });
+
+    base::EraseIf(persistent_dynamic_script_ids_,
+                  [&removed_script_ids](const auto& id) {
+                    return base::Contains(removed_script_ids, id);
+                  });
+
+    helper_.SetDynamicScripts(loaded_dynamic_scripts_,
+                              persistent_dynamic_script_ids_);
   }
 
   std::move(callback).Run(error);
diff --git a/extensions/browser/extension_user_script_loader.h b/extensions/browser/extension_user_script_loader.h
index b17f1d82..671ab707 100644
--- a/extensions/browser/extension_user_script_loader.h
+++ b/extensions/browser/extension_user_script_loader.h
@@ -21,6 +21,7 @@
 namespace extensions {
 
 class ContentVerifier;
+class StateStore;
 
 // UserScriptLoader for extensions. To support the scripting API, user script
 // ids/metadata registered from that API are also stored.
@@ -40,9 +41,11 @@
   // ExtensionSystemImpl.
   ExtensionUserScriptLoader(content::BrowserContext* browser_context,
                             const Extension& extension,
+                            StateStore* state_store,
                             bool listen_for_extension_system_loaded);
   ExtensionUserScriptLoader(content::BrowserContext* browser_context,
                             const Extension& extension,
+                            StateStore* state_store,
                             bool listen_for_extension_system_loaded,
                             scoped_refptr<ContentVerifier> content_verifier);
 
@@ -62,10 +65,18 @@
   // to load its scripts.
   void RemovePendingDynamicScriptIDs(const std::set<std::string>& script_ids);
 
+  // Adds `manifest_scripts` and calls GetDynamicScripts for initial dynamic
+  // scripts, to the set of scripts managed by this loader. Once
+  // `manifest_scripts` are loaded, calls `callback`.
+  void AddScriptsForExtensionLoad(
+      std::unique_ptr<UserScriptList> manifest_scripts,
+      UserScriptLoader::ScriptsLoadedCallback callback);
+
   // Adds `scripts` to the set of scripts managed by this loader and once these
   // scripts are loaded, calls OnDynamicScriptsAdded, which also calls
   // `callback`.
   void AddDynamicScripts(std::unique_ptr<UserScriptList> scripts,
+                         std::set<std::string> persistent_script_ids,
                          DynamicScriptsModifiedCallback callback);
 
   // Removes all dynamic scripts with an id specified in `ids` from
@@ -79,9 +90,14 @@
 
   // Returns the IDs of all dynamic scripts for the extension, which includes
   // the IDs of all pending and loaded dynamic scripts.
-  std::set<std::string> GetDynamicScriptIDs();
+  std::set<std::string> GetDynamicScriptIDs() const;
 
-  const UserScriptList& GetLoadedDynamicScripts();
+  const UserScriptList& GetLoadedDynamicScripts() const;
+
+  // Returns the IDs of all the currently-loaded persistent dynamic scripts for
+  // the extension. Note that this does not include scripts currently in
+  // `pending_dynamic_script_ids_`.
+  std::set<std::string> GetPersistentDynamicScriptIDs() const;
 
   // A wrapper around the method to load user scripts. Waits for the user
   // scripts to load and returns the scripts that were loaded. Exposed only for
@@ -90,6 +106,52 @@
       std::unique_ptr<UserScriptList> user_scripts);
 
  private:
+  // A helper class which handles getting/setting script metadata from the
+  // StateStore, and serializing/deserializing between base::Value and
+  // UserScript.
+  class DynamicScriptsStorageHelper {
+   public:
+    using DynamicScriptsReadCallback =
+        base::OnceCallback<void(UserScriptList scripts)>;
+
+    DynamicScriptsStorageHelper(content::BrowserContext* browser_context,
+                                const ExtensionId& extension_id,
+                                StateStore* state_store);
+    ~DynamicScriptsStorageHelper();
+    DynamicScriptsStorageHelper(const DynamicScriptsStorageHelper& other) =
+        delete;
+    DynamicScriptsStorageHelper& operator=(
+        const DynamicScriptsStorageHelper& other) = delete;
+
+    // Retrieves dynamic scripts from the StateStore. Calls
+    // OnDynamicScriptsReadFromStorage when done, which then calls `callback`.
+    void GetDynamicScripts(DynamicScriptsReadCallback callback);
+
+    // Persists the metadata of the current set of loaded dynamic scripts into
+    // the StateStore.
+    void SetDynamicScripts(
+        const UserScriptList& scripts,
+        const std::set<std::string>& persistent_dynamic_script_ids);
+
+   private:
+    // Called when dynamic scripts have been retrieved from the StateStore.
+    // Deserializes `value` into a UserScriptList and calls `callback` with that
+    // list.
+    void OnDynamicScriptsReadFromStorage(DynamicScriptsReadCallback callback,
+                                         std::unique_ptr<base::Value> value);
+
+    content::BrowserContext* browser_context_;
+
+    ExtensionId extension_id_;
+
+    // A non-owning pointer to the StateStore which contains metadata of
+    // persistent dynamic scripts owned by this extension. Outlives this
+    // instance and the owning ExtensionUserScriptLoader.
+    StateStore* state_store_;
+
+    base::WeakPtrFactory<DynamicScriptsStorageHelper> weak_factory_{this};
+  };
+
   // UserScriptLoader:
   void LoadScripts(std::unique_ptr<UserScriptList> user_scripts,
                    const std::set<std::string>& added_script_ids,
@@ -99,11 +161,24 @@
   // to be ready.
   void OnExtensionSystemReady();
 
+  // Called when the extension's initial set of persistent dynamic scripts have
+  // been fetched right after the extension has been loaded.
+  void OnInitialDynamicScriptsReadFromStateStore(
+      UserScriptList initial_dynamic_scripts);
+
+  // Called when the extension's initial set of dynamic scripts have been
+  // loaded.
+  void OnInitialDynamicScriptsLoaded(
+      std::unique_ptr<UserScriptList> initial_dynamic_scripts,
+      UserScriptLoader* loader,
+      const absl::optional<std::string>& error);
+
   // Called when the scripts added by AddDynamicScripts have been loaded. Since
   // `added_scripts` corresponds to newly loaded scripts, their IDs are removed
   // from `pending_dynamic_script_ids_` and their metadata added to
   // `loaded_dynamic_scripts_`.
   void OnDynamicScriptsAdded(std::unique_ptr<UserScriptList> added_scripts,
+                             std::set<std::string> new_persistent_script_ids,
                              DynamicScriptsModifiedCallback callback,
                              UserScriptLoader* loader,
                              const absl::optional<std::string>& error);
@@ -129,9 +204,14 @@
   // The metadata of dynamic scripts from the extension that have been loaded.
   UserScriptList loaded_dynamic_scripts_;
 
+  // The IDs of loaded dynamic scripts that persist across sessions.
+  std::set<std::string> persistent_dynamic_script_ids_;
+
   // Contains info needed for localization for this loader's host.
   PathAndLocaleInfo host_info_;
 
+  DynamicScriptsStorageHelper helper_;
+
   // Manages content verification of the loaded user scripts.
   scoped_refptr<ContentVerifier> content_verifier_;
 
diff --git a/extensions/browser/mock_extension_system.cc b/extensions/browser/mock_extension_system.cc
index a58d917..fbbbf71f 100644
--- a/extensions/browser/mock_extension_system.cc
+++ b/extensions/browser/mock_extension_system.cc
@@ -49,6 +49,10 @@
   return nullptr;
 }
 
+StateStore* MockExtensionSystem::dynamic_user_scripts_store() {
+  return nullptr;
+}
+
 scoped_refptr<value_store::ValueStoreFactory>
 MockExtensionSystem::store_factory() {
   return nullptr;
diff --git a/extensions/browser/mock_extension_system.h b/extensions/browser/mock_extension_system.h
index a363d543..1445dad 100644
--- a/extensions/browser/mock_extension_system.h
+++ b/extensions/browser/mock_extension_system.h
@@ -43,6 +43,7 @@
   UserScriptManager* user_script_manager() override;
   StateStore* state_store() override;
   StateStore* rules_store() override;
+  StateStore* dynamic_user_scripts_store() override;
   scoped_refptr<value_store::ValueStoreFactory> store_factory() override;
   InfoMap* info_map() override;
   QuotaService* quota_service() override;
diff --git a/extensions/browser/state_store.cc b/extensions/browser/state_store.cc
index f98a9db..ea0a87dd 100644
--- a/extensions/browser/state_store.cc
+++ b/extensions/browser/state_store.cc
@@ -83,6 +83,11 @@
           store_factory, base::FilePath(kStateStoreName),
           kStateDatabaseUMAClientName, GetExtensionFileTaskRunner());
       break;
+    case BackendType::SCRIPTS:
+      store_ = std::make_unique<value_store::ValueStoreFrontend>(
+          store_factory, base::FilePath(kScriptsStoreName),
+          kScriptsDatabaseUMAClientName, GetExtensionFileTaskRunner());
+      break;
   }
 
   extension_registry_observation_.Observe(ExtensionRegistry::Get(context));
diff --git a/extensions/browser/state_store.h b/extensions/browser/state_store.h
index b7404116..b97832b1 100644
--- a/extensions/browser/state_store.h
+++ b/extensions/browser/state_store.h
@@ -35,7 +35,7 @@
   typedef value_store::ValueStoreFrontend::ReadCallback ReadCallback;
 
   // The kind of extensions data stored in a backend.
-  enum class BackendType { RULES, STATE };
+  enum class BackendType { RULES, STATE, SCRIPTS };
 
   class TestObserver {
    public:
diff --git a/extensions/browser/url_loader_factory_manager.cc b/extensions/browser/url_loader_factory_manager.cc
index 460a9c2..0c7979a 100644
--- a/extensions/browser/url_loader_factory_manager.cc
+++ b/extensions/browser/url_loader_factory_manager.cc
@@ -35,34 +35,70 @@
   kExtensionProcess,
 };
 
-bool DoExtensionPermissionsCoverHttpOrHttpsOrigins(const Extension& extension) {
-  // TODO(lukasza): https://crbug.com/1016904: Return false if the |extension|'s
-  // permissions do not actually cover http or https origins.  For now we
-  // conservatively return true so that *all* extensions get relaxed CORS
-  // treatment.
-  return true;
-}
-
-bool DoContentScriptsDependOnRelaxedCors(const Extension& extension) {
-  // Content scripts injected by Chrome Apps (e.g. into <webview> tag) may need
-  // to run with relaxed CORS.
+bool DoContentScriptsDependOnRelaxedCorbOrCors(const Extension& extension) {
+  // Content scripts injected by Chrome Apps (e.g. into <webview> tag) need to
+  // run with relaxed CORB.
   //
   // TODO(https://crbug.com/1152550): Remove this exception once Chrome Platform
   // Apps are gone.
   if (extension.is_platform_app())
-    return DoExtensionPermissionsCoverHttpOrHttpsOrigins(extension);
+    return true;
 
-  // Content scripts are not granted an ability to relax CORS.
+  // Content scripts are not granted an ability to relax CORB and/or CORS.
   return false;
 }
 
+bool DoExtensionPermissionsCoverHttpOrHttpsOrigins(const Extension& extension) {
+  // TODO(lukasza): https://crbug.com/1016904: Return false if the |extension|'s
+  // permissions do not actually cover http or https origins.  For now we
+  // conservatively return true so that *all* extensions get relaxed CORS/CORB
+  // treatment.
+  return true;
+}
+
+// Returns whether the default URLLoaderFactoryParams::is_corb_enabled should be
+// overridden and changed to false.
+bool ShouldDisableCorb(const Extension& extension, FactoryUser factory_user) {
+  if (!DoExtensionPermissionsCoverHttpOrHttpsOrigins(extension))
+    return false;
+
+  switch (factory_user) {
+    case FactoryUser::kContentScript:
+      return DoContentScriptsDependOnRelaxedCorbOrCors(extension);
+    case FactoryUser::kExtensionProcess:
+      return true;
+  }
+}
+
+// Returns whether URLLoaderFactoryParams::ignore_isolated_world_origin should
+// be overridden and changed to false.
+bool ShouldInspectIsolatedWorldOrigin(const Extension& extension,
+                                      FactoryUser factory_user) {
+  if (!DoExtensionPermissionsCoverHttpOrHttpsOrigins(extension))
+    return false;
+
+  switch (factory_user) {
+    case FactoryUser::kContentScript:
+      return DoContentScriptsDependOnRelaxedCorbOrCors(extension);
+    case FactoryUser::kExtensionProcess:
+      return false;
+  }
+}
+
+bool ShouldCreateSeparateFactoryForContentScripts(const Extension& extension) {
+  return ShouldDisableCorb(extension, FactoryUser::kContentScript) ||
+         ShouldInspectIsolatedWorldOrigin(extension,
+                                          FactoryUser::kContentScript);
+}
+
 void OverrideFactoryParams(const Extension& extension,
                            FactoryUser factory_user,
                            network::mojom::URLLoaderFactoryParams* params) {
-  if (factory_user == FactoryUser::kContentScript &&
-      DoContentScriptsDependOnRelaxedCors(extension)) {
+  if (ShouldDisableCorb(extension, factory_user))
+    params->is_corb_enabled = false;
+
+  if (ShouldInspectIsolatedWorldOrigin(extension, factory_user))
     params->ignore_isolated_world_origin = false;
-  }
 
   // TODO(lukasza): Do not override |unsafe_non_webby_initiator| unless
   // DoExtensionPermissionsCoverHttpOrHttpsOrigins(extension).
@@ -93,8 +129,7 @@
 
   std::vector<url::Origin> initiators_requiring_separate_factory;
   for (const Extension* extension : extensions) {
-    // Do nothing if a separate URLLoaderFactory is not needed.
-    if (!DoContentScriptsDependOnRelaxedCors(*extension))
+    if (!ShouldCreateSeparateFactoryForContentScripts(*extension))
       continue;
 
     initiators_requiring_separate_factory.push_back(extension->origin());
@@ -117,8 +152,7 @@
     base::PassKey<ContentScriptTracker> pass_key,
     content::RenderFrameHost* frame,
     const Extension& extension) {
-  // Do nothing if a separate URLLoaderFactory is not needed.
-  if (!DoContentScriptsDependOnRelaxedCors(extension))
+  if (!ShouldCreateSeparateFactoryForContentScripts(extension))
     return;
 
   // When WillExecuteCode runs, the frame already received the initial
@@ -145,7 +179,7 @@
 
   // Opaque origins normally don't inherit security properties of their
   // precursor origins, but here opaque origins (e.g. think data: URIs) created
-  // by an extension should inherit CORS treatment of the extension.
+  // by an extension should inherit CORS/CORB treatment of the extension.
   url::SchemeHostPort precursor_origin =
       origin.GetTupleOrPrecursorTupleIfOpaque();
 
diff --git a/extensions/browser/url_loader_factory_manager.h b/extensions/browser/url_loader_factory_manager.h
index 709e10b..6fd828b 100644
--- a/extensions/browser/url_loader_factory_manager.h
+++ b/extensions/browser/url_loader_factory_manager.h
@@ -27,7 +27,7 @@
 class ContentScriptTracker;
 
 // This class manages URLLoaderFactory objects that handle network requests that
-// require extension-specific permissions (related to relaxed CORS).
+// require extension-specific permissions (related to relaxed CORB and CORS).
 //
 // See also https://crbug.com/846346 for motivation for having separate
 // URLLoaderFactory objects for content scripts.
@@ -88,10 +88,9 @@
   //                                 |           |             |
   // URLLoaderFactoryParams:         |           |             |
   // - request_initiator_origin_lock |    web    |  extension  |     web
-  // - overridden properties?:       |           |             |
-  //    is_corb_enabled              |    always secure-default = true/enabled
-  //    ignore_isolated_world_origin | sec-default=true/ignore | if needed (app)
-  //    unsafe_non_webby_initiator   |   false   |    true     |    false
+  // - overridden properties?        |    no     |     yes     |  if needed
+  //    - is_corb_enabled            | secure-   |  ext-based  | ext-based for
+  //    - ..._access_patterns        |  -default |             | platform apps
   static void OverrideURLLoaderFactoryParams(
       content::BrowserContext* browser_context,
       const url::Origin& origin,
diff --git a/extensions/browser/user_script_manager.cc b/extensions/browser/user_script_manager.cc
index b693b97..2669f30 100644
--- a/extensions/browser/user_script_manager.cc
+++ b/extensions/browser/user_script_manager.cc
@@ -6,12 +6,18 @@
 
 #include "base/containers/contains.h"
 #include "content/public/browser/browser_context.h"
+#include "extensions/browser/api/scripting/constants.h"
 #include "extensions/browser/extension_registry.h"
+#include "extensions/browser/extension_system.h"
 #include "extensions/browser/extension_util.h"
 #include "extensions/browser/extensions_browser_client.h"
+#include "extensions/browser/state_store.h"
 #include "extensions/browser/user_script_loader.h"
+#include "extensions/common/api/content_scripts.h"
 #include "extensions/common/manifest_handlers/content_scripts_handler.h"
 #include "extensions/common/mojom/host_id.mojom.h"
+#include "extensions/common/mojom/run_location.mojom-shared.h"
+#include "extensions/common/utils/content_script_utils.h"
 
 namespace extensions {
 
@@ -19,6 +25,11 @@
     : browser_context_(browser_context) {
   extension_registry_observation_.Observe(
       ExtensionRegistry::Get(browser_context_));
+
+  StateStore* store =
+      ExtensionSystem::Get(browser_context_)->dynamic_user_scripts_store();
+  if (store)
+    store->RegisterKey(scripting::kRegisteredScriptsStorageKey);
 }
 
 UserScriptManager::~UserScriptManager() = default;
@@ -59,19 +70,14 @@
   ExtensionUserScriptLoader* loader =
       GetUserScriptLoaderForExtension(extension->id());
 
-  std::unique_ptr<UserScriptList> scripts =
-      GetManifestScriptsMetadata(extension);
+  pending_manifest_load_count_++;
 
-  // Don't bother adding scripts if this extension has none because adding an
-  // empty set of scripts will not trigger a load. This also prevents redundant
-  // calls to OnInitialExtensionLoadComplete.
-  if (!scripts->empty()) {
-    pending_manifest_load_count_++;
-    loader->AddScripts(
-        std::move(scripts),
-        base::BindOnce(&UserScriptManager::OnInitialExtensionLoadComplete,
-                       weak_factory_.GetWeakPtr()));
-  }
+  // TODO(crbug.com/1248276): Maybe abstract/move some more of this logic into
+  // ExtensionUserScriptLoader.
+  loader->AddScriptsForExtensionLoad(
+      GetManifestScriptsMetadata(extension),
+      base::BindOnce(&UserScriptManager::OnInitialExtensionLoadComplete,
+                     weak_factory_.GetWeakPtr()));
 }
 
 void UserScriptManager::OnExtensionUnloaded(
@@ -125,6 +131,8 @@
           .emplace(extension->id(),
                    std::make_unique<ExtensionUserScriptLoader>(
                        browser_context_, *extension,
+                       ExtensionSystem::Get(browser_context_)
+                           ->dynamic_user_scripts_store(),
                        /*listen_for_extension_system_loaded=*/true))
           .first->second.get();
 
diff --git a/extensions/browser/user_script_manager.h b/extensions/browser/user_script_manager.h
index f873763..300461e 100644
--- a/extensions/browser/user_script_manager.h
+++ b/extensions/browser/user_script_manager.h
@@ -11,6 +11,7 @@
 
 #include "base/memory/weak_ptr.h"
 #include "base/scoped_observation.h"
+#include "base/values.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_registry_observer.h"
 #include "extensions/browser/extension_user_script_loader.h"
@@ -55,8 +56,8 @@
                            const Extension* extension,
                            UnloadedExtensionReason reason) override;
 
-  // Called when the |loader| has finished loading its initial set of scripts.
-  // This is only fired for extension script loaders.
+  // Called when `loader` has finished loading its initial set of scripts. This
+  // is only fired for extension script loaders.
   void OnInitialExtensionLoadComplete(UserScriptLoader* loader,
                                       const absl::optional<std::string>& error);
 
diff --git a/extensions/common/constants.cc b/extensions/common/constants.cc
index 1388cb6..025753e 100644
--- a/extensions/common/constants.cc
+++ b/extensions/common/constants.cc
@@ -67,11 +67,14 @@
     FILE_PATH_LITERAL("Extension State");
 const base::FilePath::CharType kRulesStoreName[] =
     FILE_PATH_LITERAL("Extension Rules");
+const base::FilePath::CharType kScriptsStoreName[] =
+    FILE_PATH_LITERAL("Extension Scripts");
 const char kWebStoreAppId[] = "ahfgeienlihckogmohjhadlkjgocpleb";
 
 const char kSettingsDatabaseUMAClientName[] = "Settings";
 const char kRulesDatabaseUMAClientName[] = "Rules";
 const char kStateDatabaseUMAClientName[] = "State";
+const char kScriptsDatabaseUMAClientName[] = "Scripts";
 
 const uint8_t kWebstoreSignaturesPublicKey[] = {
     0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
diff --git a/extensions/common/constants.h b/extensions/common/constants.h
index d8343af..c9cc5228 100644
--- a/extensions/common/constants.h
+++ b/extensions/common/constants.h
@@ -102,6 +102,10 @@
 // rules are stored.
 extern const base::FilePath::CharType kRulesStoreName[];
 
+// The name of the database inside the profile where persistent dynamic user
+// script metadata is stored.
+extern const base::FilePath::CharType kScriptsStoreName[];
+
 // Statistics are logged to UMA with these strings as part of histogram name.
 // They can all be found under Extensions.Database.Open.<client>. Changing this
 // needs to synchronize with histograms.xml, AND will also become incompatible
@@ -109,6 +113,7 @@
 extern const char kSettingsDatabaseUMAClientName[];
 extern const char kRulesDatabaseUMAClientName[];
 extern const char kStateDatabaseUMAClientName[];
+extern const char kScriptsDatabaseUMAClientName[];
 
 // The URL query parameter key corresponding to multi-login user index.
 extern const char kAuthUserQueryKey[];
diff --git a/extensions/common/manifest_handlers/content_scripts_handler.cc b/extensions/common/manifest_handlers/content_scripts_handler.cc
index 5b5a4ea..2e4005d 100644
--- a/extensions/common/manifest_handlers/content_scripts_handler.cc
+++ b/extensions/common/manifest_handlers/content_scripts_handler.cc
@@ -42,20 +42,6 @@
 
 namespace {
 
-mojom::RunLocation ConvertRunLocation(content_scripts_api::RunAt run_at) {
-  switch (run_at) {
-    case content_scripts_api::RUN_AT_DOCUMENT_END:
-      return mojom::RunLocation::kDocumentEnd;
-    case content_scripts_api::RUN_AT_DOCUMENT_IDLE:
-      return mojom::RunLocation::kDocumentIdle;
-    case content_scripts_api::RUN_AT_DOCUMENT_START:
-      return mojom::RunLocation::kDocumentStart;
-    case content_scripts_api::RUN_AT_NONE:
-      NOTREACHED();
-      return mojom::RunLocation::kDocumentIdle;
-  }
-}
-
 void ParseGlobs(const std::vector<std::string>* include_globs,
                 const std::vector<std::string>* exclude_globs,
                 UserScript* result) {
@@ -83,8 +69,10 @@
   auto result = std::make_unique<UserScript>();
 
   // run_at
-  if (content_script.run_at != content_scripts_api::RUN_AT_NONE)
-    result->set_run_location(ConvertRunLocation(content_script.run_at));
+  if (content_script.run_at != content_scripts_api::RUN_AT_NONE) {
+    result->set_run_location(
+        script_parsing::ConvertManifestRunLocation(content_script.run_at));
+  }
 
   // all_frames
   if (content_script.all_frames)
diff --git a/extensions/common/utils/content_script_utils.cc b/extensions/common/utils/content_script_utils.cc
index ee2b992a..dbf914d 100644
--- a/extensions/common/utils/content_script_utils.cc
+++ b/extensions/common/utils/content_script_utils.cc
@@ -61,6 +61,42 @@
 
 }  // namespace
 
+mojom::RunLocation ConvertManifestRunLocation(
+    api::content_scripts::RunAt run_at) {
+  switch (run_at) {
+    case api::content_scripts::RUN_AT_DOCUMENT_END:
+      return mojom::RunLocation::kDocumentEnd;
+    case api::content_scripts::RUN_AT_DOCUMENT_IDLE:
+      return mojom::RunLocation::kDocumentIdle;
+    case api::content_scripts::RUN_AT_DOCUMENT_START:
+      return mojom::RunLocation::kDocumentStart;
+    case api::content_scripts::RUN_AT_NONE:
+      NOTREACHED();
+      return mojom::RunLocation::kDocumentIdle;
+  }
+}
+
+api::content_scripts::RunAt ConvertRunLocationToManifestType(
+    mojom::RunLocation run_at) {
+  // api::extension_types does not have analogues for kUndefined, kRunDeferred
+  // or kBrowserDriven. We don't expect to encounter them here.
+  switch (run_at) {
+    case mojom::RunLocation::kDocumentEnd:
+      return api::content_scripts::RUN_AT_DOCUMENT_END;
+    case mojom::RunLocation::kDocumentStart:
+      return api::content_scripts::RUN_AT_DOCUMENT_START;
+    case mojom::RunLocation::kDocumentIdle:
+      return api::content_scripts::RUN_AT_DOCUMENT_IDLE;
+    case mojom::RunLocation::kUndefined:
+    case mojom::RunLocation::kRunDeferred:
+    case mojom::RunLocation::kBrowserDriven:
+      break;
+  }
+
+  NOTREACHED();
+  return api::content_scripts::RUN_AT_DOCUMENT_IDLE;
+}
+
 bool ParseMatchPatterns(const std::vector<std::string>& matches,
                         const std::vector<std::string>* exclude_matches,
                         int definition_index,
diff --git a/extensions/common/utils/content_script_utils.h b/extensions/common/utils/content_script_utils.h
index 42d1073fd..04badf4f 100644
--- a/extensions/common/utils/content_script_utils.h
+++ b/extensions/common/utils/content_script_utils.h
@@ -9,6 +9,7 @@
 
 #include "base/callback.h"
 #include "base/macros.h"
+#include "extensions/common/api/content_scripts.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/extension_resource.h"
 #include "extensions/common/user_script.h"
@@ -18,6 +19,14 @@
 namespace extensions {
 namespace script_parsing {
 
+// Converts api::content_scripts::RunAt to mojom::RunLocation.
+mojom::RunLocation ConvertManifestRunLocation(
+    api::content_scripts::RunAt run_at);
+
+// Converts mojom::RunLocation to api::content_scripts::RunAt.
+api::content_scripts::RunAt ConvertRunLocationToManifestType(
+    mojom::RunLocation run_at);
+
 // Parses and validates `matches` and `exclude_matches`, and updates these
 // fields for `result`. If `wants_file_access` is not null, then it will be set
 // to signal to the caller that the extension is requesting file access based
diff --git a/extensions/shell/browser/shell_extension_system.cc b/extensions/shell/browser/shell_extension_system.cc
index 9f7a565..5de77614 100644
--- a/extensions/shell/browser/shell_extension_system.cc
+++ b/extensions/shell/browser/shell_extension_system.cc
@@ -111,6 +111,10 @@
   return nullptr;
 }
 
+StateStore* ShellExtensionSystem::dynamic_user_scripts_store() {
+  return nullptr;
+}
+
 scoped_refptr<value_store::ValueStoreFactory>
 ShellExtensionSystem::store_factory() {
   return store_factory_;
diff --git a/extensions/shell/browser/shell_extension_system.h b/extensions/shell/browser/shell_extension_system.h
index 6207def..c57eafc2 100644
--- a/extensions/shell/browser/shell_extension_system.h
+++ b/extensions/shell/browser/shell_extension_system.h
@@ -74,6 +74,7 @@
   UserScriptManager* user_script_manager() override;
   StateStore* state_store() override;
   StateStore* rules_store() override;
+  StateStore* dynamic_user_scripts_store() override;
   scoped_refptr<value_store::ValueStoreFactory> store_factory() override;
   InfoMap* info_map() override;
   QuotaService* quota_service() override;
diff --git a/fuchsia/base/test/BUILD.gn b/fuchsia/base/test/BUILD.gn
index b2b1259..8771cf9 100644
--- a/fuchsia/base/test/BUILD.gn
+++ b/fuchsia/base/test/BUILD.gn
@@ -14,7 +14,6 @@
     "fit_adapter.h",
     "frame_test_util.cc",
     "frame_test_util.h",
-    "result_receiver.h",
     "scoped_connection_checker.h",
     "test_devtools_list_fetcher.cc",
     "test_devtools_list_fetcher.h",
diff --git a/fuchsia/base/test/frame_test_util.cc b/fuchsia/base/test/frame_test_util.cc
index 75496ef..19ec92c 100644
--- a/fuchsia/base/test/frame_test_util.cc
+++ b/fuchsia/base/test/frame_test_util.cc
@@ -7,9 +7,9 @@
 #include "base/json/json_reader.h"
 #include "base/run_loop.h"
 #include "base/strings/string_piece.h"
+#include "base/test/test_future.h"
 #include "fuchsia/base/mem_buffer_util.h"
 #include "fuchsia/base/test/fit_adapter.h"
-#include "fuchsia/base/test/result_receiver.h"
 #include "fuchsia/base/test/test_navigation_listener.h"
 
 namespace cr_fuchsia {
@@ -19,14 +19,12 @@
     fuchsia::web::LoadUrlParams load_url_params,
     base::StringPiece url) {
   DCHECK(navigation_controller);
-  base::RunLoop run_loop;
-  ResultReceiver<fuchsia::web::NavigationController_LoadUrl_Result> result(
-      run_loop.QuitClosure());
-  navigation_controller->LoadUrl(
-      std::string(url), std::move(load_url_params),
-      CallbackToFitFunction(result.GetReceiveCallback()));
-  run_loop.Run();
-  return result->is_response();
+  base::test::TestFuture<fuchsia::web::NavigationController_LoadUrl_Result>
+      result;
+  navigation_controller->LoadUrl(std::string(url), std::move(load_url_params),
+                                 CallbackToFitFunction(result.GetCallback()));
+  DCHECK(result.Wait());
+  return result.Get().is_response();
 }
 
 bool LoadUrlAndExpectResponse(
@@ -38,18 +36,15 @@
 
 absl::optional<base::Value> ExecuteJavaScript(fuchsia::web::Frame* frame,
                                               base::StringPiece script) {
-  base::RunLoop run_loop;
-  ResultReceiver<fuchsia::web::Frame_ExecuteJavaScript_Result> result(
-      run_loop.QuitClosure());
+  base::test::TestFuture<fuchsia::web::Frame_ExecuteJavaScript_Result> result;
   frame->ExecuteJavaScript({"*"}, MemBufferFromString(script, "test"),
-                           CallbackToFitFunction(result.GetReceiveCallback()));
-  run_loop.Run();
+                           CallbackToFitFunction(result.GetCallback()));
 
-  if (!result.has_value() || !result->is_response())
+  if (!result.Wait() || !result.Get().is_response())
     return {};
 
   std::string result_json;
-  if (!StringFromMemBuffer(result->response().result, &result_json)) {
+  if (!StringFromMemBuffer(result.Get().response().result, &result_json)) {
     return {};
   }
 
diff --git a/fuchsia/base/test/result_receiver.h b/fuchsia/base/test/result_receiver.h
deleted file mode 100644
index c067b881..0000000
--- a/fuchsia/base/test/result_receiver.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2019 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 FUCHSIA_BASE_TEST_RESULT_RECEIVER_H_
-#define FUCHSIA_BASE_TEST_RESULT_RECEIVER_H_
-
-#include "base/bind.h"
-#include "base/callback_helpers.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
-
-namespace cr_fuchsia {
-
-// Helper for capturing a "result" of an asynchronous operation that is passed
-// via a Callback<ResultType>, for later retrieval. An optional Closure may also
-// be configured, to be called when the result is captured.
-//
-// This is primarily useful for tests, which use a ResultReceiver<> configured
-// with a RunLoop::QuitClosure() to pump a message-loop until an asynchronous
-// operation has completed.
-template <typename T>
-class ResultReceiver {
- public:
-  ResultReceiver() : on_result_received_() {}
-  explicit ResultReceiver(base::RepeatingClosure on_result_received)
-      : on_result_received_(std::move(on_result_received)) {}
-
-  ~ResultReceiver() = default;
-
-  // Returns a OnceCallback which will receive and store a result value.
-  base::OnceCallback<void(T)> GetReceiveCallback() {
-    return base::BindOnce(&ResultReceiver<T>::ReceiveResult,
-                          base::Unretained(this));
-  }
-
-  void ReceiveResult(T result) {
-    DCHECK(!result_.has_value());
-    result_ = std::move(result);
-    if (on_result_received_)
-      on_result_received_.Run();
-  }
-
-  bool has_value() const { return result_.has_value(); }
-
-  T& operator*() {
-    DCHECK(result_.has_value());
-    return *result_;
-  }
-
-  T* operator->() {
-    DCHECK(result_.has_value());
-    return &*result_;
-  }
-
- private:
-  absl::optional<T> result_;
-  const base::RepeatingClosure on_result_received_;
-
-  DISALLOW_COPY_AND_ASSIGN(ResultReceiver<T>);
-};
-
-}  // namespace cr_fuchsia
-
-#endif  // FUCHSIA_BASE_TEST_RESULT_RECEIVER_H_
diff --git a/fuchsia/engine/browser/frame_impl.cc b/fuchsia/engine/browser/frame_impl.cc
index 2863abb..ea353ed 100644
--- a/fuchsia/engine/browser/frame_impl.cc
+++ b/fuchsia/engine/browser/frame_impl.cc
@@ -126,46 +126,46 @@
   return false;
 }
 
-fx_log_severity_t FuchsiaWebConsoleLogLevelToFxLogSeverity(
+FuchsiaLogSeverity FuchsiaWebConsoleLogLevelToFxLogSeverity(
     fuchsia::web::ConsoleLogLevel level) {
   switch (level) {
     case fuchsia::web::ConsoleLogLevel::DEBUG:
-      return FX_LOG_DEBUG;
+      return FUCHSIA_LOG_DEBUG;
     case fuchsia::web::ConsoleLogLevel::INFO:
-      return FX_LOG_INFO;
+      return FUCHSIA_LOG_INFO;
     case fuchsia::web::ConsoleLogLevel::WARN:
-      return FX_LOG_WARNING;
+      return FUCHSIA_LOG_WARNING;
     case fuchsia::web::ConsoleLogLevel::ERROR:
-      return FX_LOG_ERROR;
+      return FUCHSIA_LOG_ERROR;
     case fuchsia::web::ConsoleLogLevel::NONE:
-      return FX_LOG_NONE;
+      return FUCHSIA_LOG_NONE;
     default:
       // Cope gracefully with callers setting undefined levels.
       DLOG(ERROR) << "Unknown log level:"
                   << static_cast<std::underlying_type<decltype(level)>::type>(
                          level);
-      return FX_LOG_NONE;
+      return FUCHSIA_LOG_NONE;
   }
 }
 
-fx_log_severity_t BlinkConsoleMessageLevelToFxLogSeverity(
+FuchsiaLogSeverity BlinkConsoleMessageLevelToFxLogSeverity(
     blink::mojom::ConsoleMessageLevel level) {
   switch (level) {
     case blink::mojom::ConsoleMessageLevel::kVerbose:
-      return FX_LOG_DEBUG;
+      return FUCHSIA_LOG_DEBUG;
     case blink::mojom::ConsoleMessageLevel::kInfo:
-      return FX_LOG_INFO;
+      return FUCHSIA_LOG_INFO;
     case blink::mojom::ConsoleMessageLevel::kWarning:
-      return FX_LOG_WARNING;
+      return FUCHSIA_LOG_WARNING;
     case blink::mojom::ConsoleMessageLevel::kError:
-      return FX_LOG_ERROR;
+      return FUCHSIA_LOG_ERROR;
   }
 
   // Cope gracefully with callers setting undefined levels.
   DLOG(ERROR) << "Unknown log level:"
               << static_cast<std::underlying_type<decltype(level)>::type>(
                      level);
-  return FX_LOG_NONE;
+  return FUCHSIA_LOG_NONE;
 }
 
 bool IsHeadless() {
@@ -808,10 +808,10 @@
 
 void FrameImpl::SetConsoleLogSink(fuchsia::logger::LogSinkHandle sink) {
   if (sink) {
-    console_logger_ = base::CreateFxLoggerFromLogSinkWithTag(std::move(sink),
-                                                             console_log_tag_);
+    console_logger_ = base::ScopedFxLogger::CreateFromLogSinkWithTag(
+        std::move(sink), console_log_tag_);
   } else {
-    console_logger_ = nullptr;
+    console_logger_ = {};
   }
 }
 
@@ -1056,29 +1056,31 @@
     const std::u16string& message,
     int32_t line_no,
     const std::u16string& source_id) {
-  fx_log_severity_t severity =
+  FuchsiaLogSeverity severity =
       BlinkConsoleMessageLevelToFxLogSeverity(log_level);
   if (severity < log_level_) {
     // Prevent the default logging mechanism from logging the message.
     return true;
   }
 
-  if (!console_logger_) {
+  if (!console_logger_.is_valid()) {
     // Log via the process' LogSink service if none was set on the Frame.
     // Connect on-demand, so that embedders need not provide a LogSink in the
     // CreateContextParams services, unless they actually enable logging.
-    console_logger_ = base::CreateFxLoggerFromLogSinkWithTag(
+    console_logger_ = base::ScopedFxLogger::CreateFromLogSinkWithTag(
         base::ComponentContextForProcess()
             ->svc()
             ->Connect<fuchsia::logger::LogSink>(),
         console_log_tag_);
+
+    if (!console_logger_.is_valid())
+      return false;
   }
 
-  std::string formatted_message =
-      base::StringPrintf("%s:%d : %s", base::UTF16ToUTF8(source_id).data(),
-                         line_no, base::UTF16ToUTF8(message).data());
-  fx_logger_log(console_logger_.get(), severity, nullptr,
-                formatted_message.data());
+  std::string source_id_utf8 = base::UTF16ToUTF8(source_id);
+  std::string message_utf8 = base::UTF16ToUTF8(message);
+  console_logger_.LogMessage(source_id_utf8, line_no, message_utf8, severity);
+
   return true;
 }
 
diff --git a/fuchsia/engine/browser/frame_impl.h b/fuchsia/engine/browser/frame_impl.h
index 3e65c4e8..4b562268 100644
--- a/fuchsia/engine/browser/frame_impl.h
+++ b/fuchsia/engine/browser/frame_impl.h
@@ -9,7 +9,7 @@
 #include <fuchsia/web/cpp/fidl.h>
 #include <lib/fidl/cpp/binding_set.h>
 #include <lib/inspect/cpp/vmo/types.h>
-#include <lib/syslog/logger.h>
+#include <lib/syslog/structured_backend/cpp/fuchsia_syslog.h>
 #include <lib/ui/scenic/cpp/view_ref_pair.h>
 #include <lib/zx/channel.h>
 
@@ -292,7 +292,7 @@
 
   // Logger used for console messages from content, depending on |log_level_|.
   base::ScopedFxLogger console_logger_;
-  fx_log_severity_t log_level_ = FX_LOG_NONE;
+  FuchsiaLogSeverity log_level_ = FUCHSIA_LOG_NONE;
 
   // Parameters applied to popups created by content running in this Frame.
   const fuchsia::web::CreateFrameParams params_for_popups_;
diff --git a/fuchsia/engine/browser/web_engine_memory_inspector.cc b/fuchsia/engine/browser/web_engine_memory_inspector.cc
index fda65468..08d7b678 100644
--- a/fuchsia/engine/browser/web_engine_memory_inspector.cc
+++ b/fuchsia/engine/browser/web_engine_memory_inspector.cc
@@ -175,25 +175,32 @@
     // Include details of each process' role in the web instance.
     std::ostringstream type;
     type << process_dump->process_type;
-    node.CreateString("type", type.str(), dump_results_.get());
+    static const inspect::StringReference kTypeNodeName("type");
+    node.CreateString(kTypeNodeName, type.str(), dump_results_.get());
 
     const auto service_name = process_dump->service_name;
     if (service_name) {
-      node.CreateString("service", *service_name, dump_results_.get());
+      static const inspect::StringReference kServiceNodeName("service");
+      node.CreateString(kServiceNodeName, *service_name, dump_results_.get());
     }
 
     // Include the summary of the process' memory usage.
     const auto& os_dump = process_dump->os_dump;
-    node.CreateUint("resident_kb", os_dump->resident_set_kb,
+    static const inspect::StringReference kResidentKbNodeName("resident_kb");
+    node.CreateUint(kResidentKbNodeName, os_dump->resident_set_kb,
                     dump_results_.get());
-    node.CreateUint("private_kb", os_dump->private_footprint_kb,
+    static const inspect::StringReference kPrivateKbNodeName("private_kb");
+    node.CreateUint(kPrivateKbNodeName, os_dump->private_footprint_kb,
                     dump_results_.get());
-    node.CreateUint("shared_kb", os_dump->shared_footprint_kb,
+    static const inspect::StringReference kSharedKbNodeName("shared_kb");
+    node.CreateUint(kSharedKbNodeName, os_dump->shared_footprint_kb,
                     dump_results_.get());
 
     // If provided, include detail from individual allocators.
     if (!process_dump->chrome_allocator_dumps.empty()) {
-      auto detail_node = node.CreateChild("allocator_dump");
+      static const inspect::StringReference kAllocatorDumpNodeName(
+          "allocator_dump");
+      auto detail_node = node.CreateChild(kAllocatorDumpNodeName);
 
       for (auto& it : process_dump->chrome_allocator_dumps) {
         dump_results_->emplace(NodeFromAllocatorMemDump(
diff --git a/fuchsia/engine/web_engine_integration_logging_test.cc b/fuchsia/engine/web_engine_integration_logging_test.cc
index 2b30265..b93a496 100644
--- a/fuchsia/engine/web_engine_integration_logging_test.cc
+++ b/fuchsia/engine/web_engine_integration_logging_test.cc
@@ -11,6 +11,7 @@
 #include "base/fuchsia/process_context.h"
 #include "base/fuchsia/test_log_listener_safe.h"
 #include "base/strings/string_piece.h"
+#include "base/strings/stringprintf.h"
 #include "base/test/bind.h"
 #include "fuchsia/base/test/context_provider_test_connector.h"
 #include "fuchsia/base/test/frame_test_util.h"
@@ -146,6 +147,7 @@
 
   // Verify that the message is formatted as expected.
   EXPECT_EQ(NormalizeConsoleLogMessage(logged_message->msg),
-            std::string("http://127.0.0.1:") + kNormalizedPortNumber +
-                "/console_logging.html:8 : This is a debug() message.");
+            base::StringPrintf("[http://127.0.0.1:%s/console_logging.html(8)] "
+                               "This is a debug() message.",
+                               kNormalizedPortNumber));
 }
diff --git a/fuchsia/engine/web_instance_host_integration_test.cc b/fuchsia/engine/web_instance_host_integration_test.cc
index 12df9e4..5eacb5ef 100644
--- a/fuchsia/engine/web_instance_host_integration_test.cc
+++ b/fuchsia/engine/web_instance_host_integration_test.cc
@@ -15,9 +15,9 @@
 #include "base/fuchsia/process_context.h"
 #include "base/strings/string_piece_forward.h"
 #include "base/test/task_environment.h"
+#include "base/test/test_future.h"
 #include "fuchsia/base/test/fit_adapter.h"
 #include "fuchsia/base/test/frame_test_util.h"
-#include "fuchsia/base/test/result_receiver.h"
 #include "fuchsia/base/test/test_devtools_list_fetcher.h"
 #include "fuchsia/base/test/test_navigation_listener.h"
 #include "fuchsia/engine/test/frame_for_test.h"
@@ -119,15 +119,13 @@
                                                 std::move(create_frame_params));
 
   // Expect to receive a notification of the selected DevTools port.
-  base::RunLoop run_loop;
-  cr_fuchsia::ResultReceiver<
-      fuchsia::web::Context_GetRemoteDebuggingPort_Result>
-      port_receiver(run_loop.QuitClosure());
+  base::test::TestFuture<fuchsia::web::Context_GetRemoteDebuggingPort_Result>
+      port_receiver;
   context_->GetRemoteDebuggingPort(
-      cr_fuchsia::CallbackToFitFunction(port_receiver.GetReceiveCallback()));
-  run_loop.Run();
-  ASSERT_TRUE(port_receiver->is_response());
-  uint16_t remote_debugging_port = port_receiver->response().port;
+      cr_fuchsia::CallbackToFitFunction(port_receiver.GetCallback()));
+  ASSERT_TRUE(port_receiver.Wait());
+  ASSERT_TRUE(port_receiver.Get().is_response());
+  uint16_t remote_debugging_port = port_receiver.Get().response().port;
   ASSERT_TRUE(remote_debugging_port != 0);
 
   // Navigate to a URL, the devtools service should be active and report a
diff --git a/gpu/command_buffer/client/client_discardable_manager.h b/gpu/command_buffer/client/client_discardable_manager.h
index 656c473..95fbd3d 100644
--- a/gpu/command_buffer/client/client_discardable_manager.h
+++ b/gpu/command_buffer/client/client_discardable_manager.h
@@ -21,6 +21,10 @@
 class GPU_EXPORT ClientDiscardableManager {
  public:
   ClientDiscardableManager();
+
+  ClientDiscardableManager(const ClientDiscardableManager&) = delete;
+  ClientDiscardableManager& operator=(const ClientDiscardableManager&) = delete;
+
   ~ClientDiscardableManager();
 
   // Note that the handles bound to an id are not guaranteed to outlive the
@@ -73,8 +77,6 @@
   // Handles that are pending service deletion, and can be re-used once
   // ClientDiscardableHandle::CanBeReUsed returns true.
   base::queue<ClientDiscardableHandle> pending_handles_;
-
-  DISALLOW_COPY_AND_ASSIGN(ClientDiscardableManager);
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/client/client_discardable_texture_manager.h b/gpu/command_buffer/client/client_discardable_texture_manager.h
index 9460bd64..5234b2b 100644
--- a/gpu/command_buffer/client/client_discardable_texture_manager.h
+++ b/gpu/command_buffer/client/client_discardable_texture_manager.h
@@ -23,6 +23,12 @@
 class GPU_EXPORT ClientDiscardableTextureManager {
  public:
   ClientDiscardableTextureManager();
+
+  ClientDiscardableTextureManager(const ClientDiscardableTextureManager&) =
+      delete;
+  ClientDiscardableTextureManager& operator=(
+      const ClientDiscardableTextureManager&) = delete;
+
   ~ClientDiscardableTextureManager();
   ClientDiscardableHandle InitializeTexture(CommandBuffer* command_buffer,
                                             uint32_t texture_id);
@@ -58,8 +64,6 @@
   mutable base::Lock lock_;
   std::map<uint32_t, TextureEntry> texture_entries_;
   ClientDiscardableManager discardable_manager_;
-
-  DISALLOW_COPY_AND_ASSIGN(ClientDiscardableTextureManager);
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/client/client_test_helper.h b/gpu/command_buffer/client/client_test_helper.h
index bd0cc07..aeb525d 100644
--- a/gpu/command_buffer/client/client_test_helper.h
+++ b/gpu/command_buffer/client/client_test_helper.h
@@ -106,6 +106,10 @@
 class MockClientGpuControl : public GpuControl {
  public:
   MockClientGpuControl();
+
+  MockClientGpuControl(const MockClientGpuControl&) = delete;
+  MockClientGpuControl& operator=(const MockClientGpuControl&) = delete;
+
   ~MockClientGpuControl() override;
 
   MOCK_METHOD1(SetGpuControlClient, void(GpuControlClient*));
@@ -147,9 +151,6 @@
                    base::OnceCallback<void(std::unique_ptr<gfx::GpuFence>)>
                        callback) override {}
   MOCK_METHOD1(SetDisplayTransform, void(gfx::OverlayTransform));
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockClientGpuControl);
 };
 
 class FakeDecoderClient : public DecoderClient {
diff --git a/gpu/command_buffer/client/client_transfer_cache.h b/gpu/command_buffer/client/client_transfer_cache.h
index c01c59b..a3f2b29d 100644
--- a/gpu/command_buffer/client/client_transfer_cache.h
+++ b/gpu/command_buffer/client/client_transfer_cache.h
@@ -72,6 +72,10 @@
   };
 
   explicit ClientTransferCache(Client* client);
+
+  ClientTransferCache(const ClientTransferCache&) = delete;
+  ClientTransferCache& operator=(const ClientTransferCache&) = delete;
+
   ~ClientTransferCache();
 
   // Adds a transfer cache entry with previously written memory.
@@ -119,8 +123,6 @@
   base::Lock lock_;
   ClientDiscardableManager discardable_manager_;
   std::map<EntryKey, ClientDiscardableHandle::Id> discardable_handle_id_map_;
-
-  DISALLOW_COPY_AND_ASSIGN(ClientTransferCache);
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/client/cmd_buffer_helper.h b/gpu/command_buffer/client/cmd_buffer_helper.h
index 034a04a..7a3571f 100644
--- a/gpu/command_buffer/client/cmd_buffer_helper.h
+++ b/gpu/command_buffer/client/cmd_buffer_helper.h
@@ -53,6 +53,10 @@
 class GPU_EXPORT CommandBufferHelper {
  public:
   explicit CommandBufferHelper(CommandBuffer* command_buffer);
+
+  CommandBufferHelper(const CommandBufferHelper&) = delete;
+  CommandBufferHelper& operator=(const CommandBufferHelper&) = delete;
+
   virtual ~CommandBufferHelper();
 
   // Initializes the CommandBufferHelper.
@@ -345,7 +349,6 @@
   uint32_t flush_generation_ = 0;
 
   friend class CommandBufferHelperTest;
-  DISALLOW_COPY_AND_ASSIGN(CommandBufferHelper);
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/client/command_buffer_direct_locked.h b/gpu/command_buffer/client/command_buffer_direct_locked.h
index e8c6a14a..4a3f987c 100644
--- a/gpu/command_buffer/client/command_buffer_direct_locked.h
+++ b/gpu/command_buffer/client/command_buffer_direct_locked.h
@@ -14,6 +14,11 @@
 class CommandBufferDirectLocked : public CommandBufferDirect {
  public:
   CommandBufferDirectLocked() = default;
+
+  CommandBufferDirectLocked(const CommandBufferDirectLocked&) = delete;
+  CommandBufferDirectLocked& operator=(const CommandBufferDirectLocked&) =
+      delete;
+
   ~CommandBufferDirectLocked() override = default;
 
   // Overridden from CommandBufferDirect
@@ -51,7 +56,6 @@
   int client_put_offset_ = 0;
   int service_put_offset_ = 0;
   int flush_count_ = 0;
-  DISALLOW_COPY_AND_ASSIGN(CommandBufferDirectLocked);
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/client/gl_helper.cc b/gpu/command_buffer/client/gl_helper.cc
index e942e6c8..fac51cf 100644
--- a/gpu/command_buffer/client/gl_helper.cc
+++ b/gpu/command_buffer/client/gl_helper.cc
@@ -40,12 +40,13 @@
  public:
   explicit ScopedFlush(gles2::GLES2Interface* gl) : gl_(gl) {}
 
+  ScopedFlush(const ScopedFlush&) = delete;
+  ScopedFlush& operator=(const ScopedFlush&) = delete;
+
   ~ScopedFlush() { gl_->Flush(); }
 
  private:
   gles2::GLES2Interface* gl_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedFlush);
 };
 
 // Helper class for allocating and holding an RGBA texture of a given
@@ -78,6 +79,9 @@
                     bool swizzle,
                     bool use_mrt);
 
+  I420ConverterImpl(const I420ConverterImpl&) = delete;
+  I420ConverterImpl& operator=(const I420ConverterImpl&) = delete;
+
   ~I420ConverterImpl() override;
 
   void Convert(GLuint src_texture,
@@ -124,8 +128,6 @@
   // Intermediate texture, holding the UV interim output (if the MRT shader
   // is being used).
   absl::optional<ScopedTexture> uv_;
-
-  DISALLOW_COPY_AND_ASSIGN(I420ConverterImpl);
 };
 
 }  // namespace
@@ -215,6 +217,10 @@
   class FinishRequestHelper {
    public:
     FinishRequestHelper() {}
+
+    FinishRequestHelper(const FinishRequestHelper&) = delete;
+    FinishRequestHelper& operator=(const FinishRequestHelper&) = delete;
+
     ~FinishRequestHelper() {
       while (!requests_.empty()) {
         Request* request = requests_.front();
@@ -227,7 +233,6 @@
 
    private:
     base::queue<Request*> requests_;
-    DISALLOW_COPY_AND_ASSIGN(FinishRequestHelper);
   };
 
   // A readback pipeline that also converts the data to YUV before
@@ -242,6 +247,9 @@
                     ReadbackSwizzle swizzle,
                     bool use_mrt);
 
+    ReadbackYUVImpl(const ReadbackYUVImpl&) = delete;
+    ReadbackYUVImpl& operator=(const ReadbackYUVImpl&) = delete;
+
     ~ReadbackYUVImpl() override;
 
     void SetScaler(std::unique_ptr<GLHelper::ScalerInterface> scaler) override;
@@ -281,8 +289,6 @@
     ScopedFramebuffer y_readback_framebuffer_;
     ScopedFramebuffer u_readback_framebuffer_;
     ScopedFramebuffer v_readback_framebuffer_;
-
-    DISALLOW_COPY_AND_ASSIGN(ReadbackYUVImpl);
   };
 
   void ReadbackDone(Request* request, size_t bytes_per_pixel);
diff --git a/gpu/command_buffer/client/gl_helper.h b/gpu/command_buffer/client/gl_helper.h
index 379c456..0b91c3e 100644
--- a/gpu/command_buffer/client/gl_helper.h
+++ b/gpu/command_buffer/client/gl_helper.h
@@ -41,6 +41,9 @@
 
   GLuint id() const { return id_; }
 
+  ScopedGLuint(const ScopedGLuint&) = delete;
+  ScopedGLuint& operator=(const ScopedGLuint&) = delete;
+
   ~ScopedGLuint() {
     if (id_ != 0) {
       (gl_->*delete_func_)(1, &id_);
@@ -51,8 +54,6 @@
   gles2::GLES2Interface* gl_;
   GLuint id_;
   DeleteFunc delete_func_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedGLuint);
 };
 
 class ScopedBuffer : public ScopedGLuint {
@@ -88,13 +89,14 @@
     (gl_->*bind_func_)(Target, id);
   }
 
+  ScopedBinder(const ScopedBinder&) = delete;
+  ScopedBinder& operator=(const ScopedBinder&) = delete;
+
   virtual ~ScopedBinder() { (gl_->*bind_func_)(Target, 0); }
 
  private:
   gles2::GLES2Interface* gl_;
   BindFunc bind_func_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedBinder);
 };
 
 template <GLenum Target>
@@ -129,6 +131,10 @@
 class GPU_EXPORT GLHelper {
  public:
   GLHelper(gles2::GLES2Interface* gl, ContextSupport* context_support);
+
+  GLHelper(const GLHelper&) = delete;
+  GLHelper& operator=(const GLHelper&) = delete;
+
   ~GLHelper();
 
   enum ScalerQuality {
@@ -165,6 +171,9 @@
   // a source texture at a fixed scaling ratio.
   class ScalerInterface {
    public:
+    ScalerInterface(const ScalerInterface&) = delete;
+    ScalerInterface& operator=(const ScalerInterface&) = delete;
+
     virtual ~ScalerInterface() {}
 
     // Scales a portion of |src_texture| and draws the result into
@@ -244,9 +253,6 @@
 
    protected:
     ScalerInterface() {}
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(ScalerInterface);
   };
 
   // Create a scaler that upscales or downscales at the given ratio
@@ -353,9 +359,6 @@
   // Memoized result for MaxDrawBuffers(), if >= 0. Otherwise, MaxDrawBuffers()
   // will need to query the GL implementation.
   GLint max_draw_buffers_ = -1;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(GLHelper);
 };
 
 // Splits an RGBA source texture's image into separate Y, U, and V planes. The U
@@ -363,6 +366,10 @@
 class GPU_EXPORT I420Converter {
  public:
   I420Converter();
+
+  I420Converter(const I420Converter&) = delete;
+  I420Converter& operator=(const I420Converter&) = delete;
+
   virtual ~I420Converter();
 
   // Transforms a RGBA |src_texture| into three textures, each containing bytes
@@ -406,9 +413,6 @@
   // CEIL(output_rect_size.height() / 2); because the chroma planes are half-
   // length in both dimensions in the I420 format.
   static gfx::Size GetChromaPlaneTextureSize(const gfx::Size& output_rect_size);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(I420Converter);
 };
 
 // Similar to a ScalerInterface, a YUV readback pipeline will cache a scaler and
diff --git a/gpu/command_buffer/client/gl_helper_scaling.h b/gpu/command_buffer/client/gl_helper_scaling.h
index 821b37f..42b9450b 100644
--- a/gpu/command_buffer/client/gl_helper_scaling.h
+++ b/gpu/command_buffer/client/gl_helper_scaling.h
@@ -41,6 +41,10 @@
   using ShaderProgramKeyType = std::pair<ShaderType, bool>;
 
   GLHelperScaling(gles2::GLES2Interface* gl, GLHelper* helper);
+
+  GLHelperScaling(const GLHelperScaling&) = delete;
+  GLHelperScaling& operator=(const GLHelperScaling&) = delete;
+
   ~GLHelperScaling();
   void InitBuffer();
 
@@ -189,7 +193,6 @@
   friend class ScalerImpl;
   friend class GLHelperBenchmark;
   friend class GLHelperTest;
-  DISALLOW_COPY_AND_ASSIGN(GLHelperScaling);
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/client/gles2_cmd_helper.h b/gpu/command_buffer/client/gles2_cmd_helper.h
index cb738a16..081ed80 100644
--- a/gpu/command_buffer/client/gles2_cmd_helper.h
+++ b/gpu/command_buffer/client/gles2_cmd_helper.h
@@ -19,6 +19,10 @@
 class GPU_GLES2_EXPORT GLES2CmdHelper : public CommandBufferHelper {
  public:
   explicit GLES2CmdHelper(CommandBuffer* command_buffer);
+
+  GLES2CmdHelper(const GLES2CmdHelper&) = delete;
+  GLES2CmdHelper& operator=(const GLES2CmdHelper&) = delete;
+
   ~GLES2CmdHelper() override;
 
   // Include the auto-generated part of this class. We split this because it
@@ -27,9 +31,6 @@
   #include "gpu/command_buffer/client/gles2_cmd_helper_autogen.h"
 
   // Helpers that could not be auto-generated.
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(GLES2CmdHelper);
 };
 
 }  // namespace gles2
diff --git a/gpu/command_buffer/client/gles2_implementation.h b/gpu/command_buffer/client/gles2_implementation.h
index 207a2e9..0cc6299 100644
--- a/gpu/command_buffer/client/gles2_implementation.h
+++ b/gpu/command_buffer/client/gles2_implementation.h
@@ -89,6 +89,9 @@
                       bool support_client_side_arrays,
                       GpuControl* gpu_control);
 
+  GLES2Implementation(const GLES2Implementation&) = delete;
+  GLES2Implementation& operator=(const GLES2Implementation&) = delete;
+
   ~GLES2Implementation() override;
 
   gpu::ContextResult Initialize(const SharedMemoryLimits& limits);
@@ -872,8 +875,6 @@
   gl::GpuPreference active_gpu_heuristic_ = gl::GpuPreference::kDefault;
 
   base::WeakPtrFactory<GLES2Implementation> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(GLES2Implementation);
 };
 
 inline bool GLES2Implementation::GetBufferParameteri64vHelper(
diff --git a/gpu/command_buffer/client/gpu_control.h b/gpu/command_buffer/client/gpu_control.h
index 47ca927..38267ff 100644
--- a/gpu/command_buffer/client/gpu_control.h
+++ b/gpu/command_buffer/client/gpu_control.h
@@ -38,6 +38,10 @@
 class GPU_EXPORT GpuControl {
  public:
   GpuControl() = default;
+
+  GpuControl(const GpuControl&) = delete;
+  GpuControl& operator=(const GpuControl&) = delete;
+
   virtual ~GpuControl() = default;
 
   virtual void SetGpuControlClient(GpuControlClient* gpu_control_client) = 0;
@@ -122,9 +126,6 @@
   // Notifies the surface of the ideal frame rate that the content is updated
   // at. This can be used to tune the hardware refresh rate.
   virtual void SetFrameRate(float frame_rate) {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(GpuControl);
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/client/implementation_base.h b/gpu/command_buffer/client/implementation_base.h
index cc0be55..cb2ea89 100644
--- a/gpu/command_buffer/client/implementation_base.h
+++ b/gpu/command_buffer/client/implementation_base.h
@@ -62,6 +62,10 @@
   ImplementationBase(CommandBufferHelper* helper,
                      TransferBufferInterface* transfer_buffer,
                      GpuControl* gpu_control);
+
+  ImplementationBase(const ImplementationBase&) = delete;
+  ImplementationBase& operator=(const ImplementationBase&) = delete;
+
   ~ImplementationBase() override;
 
   void FreeUnusedSharedMemory();
@@ -160,8 +164,6 @@
   CommandBufferHelper* helper_;
 
   base::WeakPtrFactory<ImplementationBase> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(ImplementationBase);
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/client/logging.h b/gpu/command_buffer/client/logging.h
index e206a77..69d23f7 100644
--- a/gpu/command_buffer/client/logging.h
+++ b/gpu/command_buffer/client/logging.h
@@ -60,14 +60,16 @@
 class GLES2_IMPL_EXPORT LogSettings {
  public:
   LogSettings();
+
+  LogSettings(const LogSettings&) = delete;
+  LogSettings& operator=(const LogSettings&) = delete;
+
   ~LogSettings();
 
   bool enabled() { return enabled_; }
 
  private:
   bool enabled_;
-
-  DISALLOW_COPY_AND_ASSIGN(LogSettings);
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/client/mapped_memory.h b/gpu/command_buffer/client/mapped_memory.h
index 76eeded4..f35fbca 100644
--- a/gpu/command_buffer/client/mapped_memory.h
+++ b/gpu/command_buffer/client/mapped_memory.h
@@ -29,6 +29,10 @@
   MemoryChunk(int32_t shm_id,
               scoped_refptr<gpu::Buffer> shm,
               CommandBufferHelper* helper);
+
+  MemoryChunk(const MemoryChunk&) = delete;
+  MemoryChunk& operator=(const MemoryChunk&) = delete;
+
   ~MemoryChunk();
 
   // Gets the size of the largest free block that is available without waiting.
@@ -112,8 +116,6 @@
   int32_t shm_id_;
   scoped_refptr<gpu::Buffer> shm_;
   FencedAllocatorWrapper allocator_;
-
-  DISALLOW_COPY_AND_ASSIGN(MemoryChunk);
 };
 
 // Manages MemoryChunks.
@@ -128,6 +130,9 @@
   MappedMemoryManager(CommandBufferHelper* helper,
                       size_t unused_memory_reclaim_limit);
 
+  MappedMemoryManager(const MappedMemoryManager&) = delete;
+  MappedMemoryManager& operator=(const MappedMemoryManager&) = delete;
+
   ~MappedMemoryManager();
 
   uint32_t chunk_size_multiple() const { return chunk_size_multiple_; }
@@ -220,8 +225,6 @@
   // A process-unique ID used for disambiguating memory dumps from different
   // mapped memory manager.
   int tracing_id_;
-
-  DISALLOW_COPY_AND_ASSIGN(MappedMemoryManager);
 };
 
 // A class that will manage the lifetime of a mapped memory allocation
@@ -240,6 +243,9 @@
     Reset(size);
   }
 
+  ScopedMappedMemoryPtr(const ScopedMappedMemoryPtr&) = delete;
+  ScopedMappedMemoryPtr& operator=(const ScopedMappedMemoryPtr&) = delete;
+
   ~ScopedMappedMemoryPtr() {
     Release();
   }
@@ -278,7 +284,6 @@
   bool flush_after_release_;
   CommandBufferHelper* helper_;
   MappedMemoryManager* mapped_memory_manager_;
-  DISALLOW_COPY_AND_ASSIGN(ScopedMappedMemoryPtr);
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/client/mock_transfer_buffer.h b/gpu/command_buffer/client/mock_transfer_buffer.h
index 3106c69..f3fb85ac 100644
--- a/gpu/command_buffer/client/mock_transfer_buffer.h
+++ b/gpu/command_buffer/client/mock_transfer_buffer.h
@@ -27,6 +27,9 @@
                      unsigned int alignment,
                      bool initialize_fail);
 
+  MockTransferBuffer(const MockTransferBuffer&) = delete;
+  MockTransferBuffer& operator=(const MockTransferBuffer&) = delete;
+
   ~MockTransferBuffer() override;
 
   base::UnguessableToken shared_memory_guid() const override;
@@ -88,8 +91,6 @@
   uint32_t actual_offset_;
   bool initialize_fail_;
   bool outstanding_result_pointer_ = false;
-
-  DISALLOW_COPY_AND_ASSIGN(MockTransferBuffer);
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/client/query_tracker.h b/gpu/command_buffer/client/query_tracker.h
index 0907457..5755d41 100644
--- a/gpu/command_buffer/client/query_tracker.h
+++ b/gpu/command_buffer/client/query_tracker.h
@@ -67,6 +67,10 @@
   };
 
   explicit QuerySyncManager(MappedMemoryManager* manager);
+
+  QuerySyncManager(const QuerySyncManager&) = delete;
+  QuerySyncManager& operator=(const QuerySyncManager&) = delete;
+
   ~QuerySyncManager();
 
   bool Alloc(QueryInfo* info);
@@ -78,8 +82,6 @@
 
   MappedMemoryManager* mapped_memory_;
   base::circular_deque<std::unique_ptr<Bucket>> buckets_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuerySyncManager);
 };
 
 class GLES2_IMPL_EXPORT QueryTrackerClient {
diff --git a/gpu/command_buffer/client/raster_cmd_helper.h b/gpu/command_buffer/client/raster_cmd_helper.h
index cab4dddd..a0061eb 100644
--- a/gpu/command_buffer/client/raster_cmd_helper.h
+++ b/gpu/command_buffer/client/raster_cmd_helper.h
@@ -19,15 +19,16 @@
 class RASTER_EXPORT RasterCmdHelper : public CommandBufferHelper {
  public:
   explicit RasterCmdHelper(CommandBuffer* command_buffer);
+
+  RasterCmdHelper(const RasterCmdHelper&) = delete;
+  RasterCmdHelper& operator=(const RasterCmdHelper&) = delete;
+
   ~RasterCmdHelper() override;
 
 // Include the auto-generated part of this class. We split this because it
 // means we can easily edit the non-auto generated parts right here in this
 // file instead of having to edit some template or the code generator.
 #include "gpu/command_buffer/client/raster_cmd_helper_autogen.h"
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(RasterCmdHelper);
 };
 
 }  // namespace raster
diff --git a/gpu/command_buffer/client/raster_implementation.cc b/gpu/command_buffer/client/raster_implementation.cc
index 94f19eb..b802e7c2 100644
--- a/gpu/command_buffer/client/raster_implementation.cc
+++ b/gpu/command_buffer/client/raster_implementation.cc
@@ -139,6 +139,12 @@
  public:
   explicit TransferCacheSerializeHelperImpl(RasterImplementation* ri)
       : ri_(ri) {}
+
+  TransferCacheSerializeHelperImpl(const TransferCacheSerializeHelperImpl&) =
+      delete;
+  TransferCacheSerializeHelperImpl& operator=(
+      const TransferCacheSerializeHelperImpl&) = delete;
+
   ~TransferCacheSerializeHelperImpl() final = default;
 
   uint32_t take_end_offset_of_last_inlined_entry() {
@@ -218,8 +224,6 @@
 
   RasterImplementation* const ri_;
   uint32_t end_offset_of_last_inlined_entry_ = 0u;
-
-  DISALLOW_COPY_AND_ASSIGN(TransferCacheSerializeHelperImpl);
 };
 
 // Helper to copy PaintOps to the GPU service over the transfer buffer.
@@ -240,6 +244,9 @@
         static_cast<char*>(ri_->MapRasterCHROMIUM(initial_size, &free_bytes_));
   }
 
+  PaintOpSerializer(const PaintOpSerializer&) = delete;
+  PaintOpSerializer& operator=(const PaintOpSerializer&) = delete;
+
   ~PaintOpSerializer() {
     // Need to call SendSerializedData;
     DCHECK(!written_bytes_);
@@ -343,8 +350,6 @@
   uint32_t free_bytes_ = 0;
 
   size_t* max_op_size_hint_;
-
-  DISALLOW_COPY_AND_ASSIGN(PaintOpSerializer);
 };
 
 RasterImplementation::SingleThreadChecker::SingleThreadChecker(
diff --git a/gpu/command_buffer/client/raster_implementation.h b/gpu/command_buffer/client/raster_implementation.h
index 855afada..80ecd6d 100644
--- a/gpu/command_buffer/client/raster_implementation.h
+++ b/gpu/command_buffer/client/raster_implementation.h
@@ -63,6 +63,9 @@
       GpuControl* gpu_control,
       ImageDecodeAcceleratorInterface* image_decode_accelerator);
 
+  RasterImplementation(const RasterImplementation&) = delete;
+  RasterImplementation& operator=(const RasterImplementation&) = delete;
+
   ~RasterImplementation() override;
 
   gpu::ContextResult Initialize(const SharedMemoryLimits& limits);
@@ -453,8 +456,6 @@
 
   // Tracing helpers.
   int raster_chromium_id_ = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(RasterImplementation);
 };
 
 }  // namespace raster
diff --git a/gpu/command_buffer/client/raster_implementation_gles.h b/gpu/command_buffer/client/raster_implementation_gles.h
index 9915ec45..63338e4 100644
--- a/gpu/command_buffer/client/raster_implementation_gles.h
+++ b/gpu/command_buffer/client/raster_implementation_gles.h
@@ -25,6 +25,10 @@
  public:
   explicit RasterImplementationGLES(gles2::GLES2Interface* gl,
                                     ContextSupport* context_support);
+
+  RasterImplementationGLES(const RasterImplementationGLES&) = delete;
+  RasterImplementationGLES& operator=(const RasterImplementationGLES&) = delete;
+
   ~RasterImplementationGLES() override;
 
   // Command buffer Flush / Finish.
@@ -187,8 +191,6 @@
   ContextSupport* context_support_;
   std::unique_ptr<GLHelper> gl_helper_;
   base::WeakPtrFactory<RasterImplementationGLES> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(RasterImplementationGLES);
 };
 
 }  // namespace raster
diff --git a/gpu/command_buffer/client/readback_buffer_shadow_tracker.h b/gpu/command_buffer/client/readback_buffer_shadow_tracker.h
index 88f53dd..de65d6d3be 100644
--- a/gpu/command_buffer/client/readback_buffer_shadow_tracker.h
+++ b/gpu/command_buffer/client/readback_buffer_shadow_tracker.h
@@ -22,6 +22,10 @@
   class Buffer : public base::SupportsWeakPtr<Buffer> {
    public:
     explicit Buffer(GLuint buffer_id, ReadbackBufferShadowTracker* tracker);
+
+    Buffer(const Buffer&) = delete;
+    Buffer& operator=(const Buffer&) = delete;
+
     ~Buffer();
 
     uint32_t Alloc(int32_t* shm_id,
@@ -49,8 +53,6 @@
     uint64_t serial_of_readback_data_ = 0;
     uint32_t size_ = 0;
     bool is_mapped_ = false;
-
-    DISALLOW_COPY_AND_ASSIGN(Buffer);
   };
 
   ReadbackBufferShadowTracker(MappedMemoryManager* mapped_memory,
diff --git a/gpu/command_buffer/client/shared_image_interface.cc b/gpu/command_buffer/client/shared_image_interface.cc
index 2c8a447d..86b4752 100644
--- a/gpu/command_buffer/client/shared_image_interface.cc
+++ b/gpu/command_buffer/client/shared_image_interface.cc
@@ -41,4 +41,9 @@
                            surface_origin, alpha_type, usage);
 }
 
+void SharedImageInterface::CopyToGpuMemoryBuffer(const SyncToken& sync_token,
+                                                 const Mailbox& mailbox) {
+  NOTREACHED();
+}
+
 }  // namespace gpu
diff --git a/gpu/command_buffer/client/shared_image_interface.h b/gpu/command_buffer/client/shared_image_interface.h
index 29816ef..0b2c5fdf 100644
--- a/gpu/command_buffer/client/shared_image_interface.h
+++ b/gpu/command_buffer/client/shared_image_interface.h
@@ -145,6 +145,13 @@
                                  std::unique_ptr<gfx::GpuFence> acquire_fence,
                                  const Mailbox& mailbox) = 0;
 
+  // Update the GpuMemoryBuffer associated with the shared image |mailbox| after
+  // |sync_token| is released. This needed when the GpuMemoryBuffer is backed by
+  // shared memory on platforms like Windows where the renderer cannot create
+  // native GMBs.
+  virtual void CopyToGpuMemoryBuffer(const SyncToken& sync_token,
+                                     const Mailbox& mailbox);
+
   // Destroys the shared image, unregistering its mailbox, after |sync_token|
   // has been released. After this call, the mailbox can't be used to reference
   // the image any more, however if the image was imported into other APIs,
diff --git a/gpu/command_buffer/client/transfer_buffer.h b/gpu/command_buffer/client/transfer_buffer.h
index 505772b..1038504 100644
--- a/gpu/command_buffer/client/transfer_buffer.h
+++ b/gpu/command_buffer/client/transfer_buffer.h
@@ -199,6 +199,9 @@
         helper_(helper),
         transfer_buffer_(transfer_buffer) {}
 
+  ScopedTransferBufferPtr(const ScopedTransferBufferPtr&) = delete;
+  ScopedTransferBufferPtr& operator=(const ScopedTransferBufferPtr&) = delete;
+
   ~ScopedTransferBufferPtr() {
     Release();
   }
@@ -240,7 +243,6 @@
   unsigned int size_;
   CommandBufferHelper* helper_;
   TransferBufferInterface* transfer_buffer_;
-  DISALLOW_COPY_AND_ASSIGN(ScopedTransferBufferPtr);
 };
 
 template <typename T>
@@ -270,6 +272,10 @@
   explicit ScopedResultPtr(TransferBufferInterface* tb)
       : result_(static_cast<T*>(tb->AcquireResultBuffer())),
         transfer_buffer_(tb) {}
+
+  ScopedResultPtr(const ScopedResultPtr&) = delete;
+  ScopedResultPtr& operator=(const ScopedResultPtr&) = delete;
+
   ~ScopedResultPtr() {
     if (transfer_buffer_)
       transfer_buffer_->ReleaseResultBuffer();
@@ -278,7 +284,6 @@
   int offset() const { return transfer_buffer_->GetResultOffset(); }
 
   // Make this a move-only class like unique_ptr.
-  DISALLOW_COPY_AND_ASSIGN(ScopedResultPtr);
   ScopedResultPtr(ScopedResultPtr<T>&& other) { *this = std::move(other); }
   ScopedResultPtr& operator=(ScopedResultPtr<T>&& other) {
     this->result_ = other.result_;
diff --git a/gpu/command_buffer/client/vertex_array_object_manager.h b/gpu/command_buffer/client/vertex_array_object_manager.h
index 9ddf3e4e..70fdb21 100644
--- a/gpu/command_buffer/client/vertex_array_object_manager.h
+++ b/gpu/command_buffer/client/vertex_array_object_manager.h
@@ -30,6 +30,10 @@
       GLuint array_buffer_id,
       GLuint element_array_buffer_id,
       bool support_client_side_arrays);
+
+  VertexArrayObjectManager(const VertexArrayObjectManager&) = delete;
+  VertexArrayObjectManager& operator=(const VertexArrayObjectManager&) = delete;
+
   ~VertexArrayObjectManager();
 
   bool IsReservedId(GLuint id) const;
@@ -124,12 +128,9 @@
   VertexArrayObjectMap vertex_array_objects_;
 
   const bool support_client_side_arrays_;
-
-  DISALLOW_COPY_AND_ASSIGN(VertexArrayObjectManager);
 };
 
 }  // namespace gles2
 }  // namespace gpu
 
 #endif  // GPU_COMMAND_BUFFER_CLIENT_VERTEX_ARRAY_OBJECT_MANAGER_H_
-
diff --git a/gpu/command_buffer/client/webgpu_cmd_helper.h b/gpu/command_buffer/client/webgpu_cmd_helper.h
index ea85536..e59ed7a 100644
--- a/gpu/command_buffer/client/webgpu_cmd_helper.h
+++ b/gpu/command_buffer/client/webgpu_cmd_helper.h
@@ -19,15 +19,16 @@
 class WEBGPU_EXPORT WebGPUCmdHelper : public CommandBufferHelper {
  public:
   explicit WebGPUCmdHelper(CommandBuffer* command_buffer);
+
+  WebGPUCmdHelper(const WebGPUCmdHelper&) = delete;
+  WebGPUCmdHelper& operator=(const WebGPUCmdHelper&) = delete;
+
   ~WebGPUCmdHelper() override;
 
 // Include the auto-generated part of this class. We split this because it
 // means we can easily edit the non-auto generated parts right here in this
 // file instead of having to edit some template or the code generator.
 #include "gpu/command_buffer/client/webgpu_cmd_helper_autogen.h"
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(WebGPUCmdHelper);
 };
 
 }  // namespace webgpu
diff --git a/gpu/command_buffer/client/webgpu_implementation.h b/gpu/command_buffer/client/webgpu_implementation.h
index 0ed927da..4fade692 100644
--- a/gpu/command_buffer/client/webgpu_implementation.h
+++ b/gpu/command_buffer/client/webgpu_implementation.h
@@ -36,6 +36,10 @@
   explicit WebGPUImplementation(WebGPUCmdHelper* helper,
                                 TransferBufferInterface* transfer_buffer,
                                 GpuControl* gpu_control);
+
+  WebGPUImplementation(const WebGPUImplementation&) = delete;
+  WebGPUImplementation& operator=(const WebGPUImplementation&) = delete;
+
   ~WebGPUImplementation() override;
 
   gpu::ContextResult Initialize(const SharedMemoryLimits& limits);
@@ -161,8 +165,6 @@
   DawnRequestDeviceSerial request_device_serial_ = 0;
 
   std::atomic_bool lost_{false};
-
-  DISALLOW_COPY_AND_ASSIGN(WebGPUImplementation);
 };
 
 }  // namespace webgpu
diff --git a/gpu/command_buffer/common/buffer.h b/gpu/command_buffer/common/buffer.h
index b02f6d76..abb26f8 100644
--- a/gpu/command_buffer/common/buffer.h
+++ b/gpu/command_buffer/common/buffer.h
@@ -30,6 +30,10 @@
 class GPU_EXPORT MemoryBufferBacking : public BufferBacking {
  public:
   explicit MemoryBufferBacking(uint32_t size);
+
+  MemoryBufferBacking(const MemoryBufferBacking&) = delete;
+  MemoryBufferBacking& operator=(const MemoryBufferBacking&) = delete;
+
   ~MemoryBufferBacking() override;
   void* GetMemory() const override;
   uint32_t GetSize() const override;
@@ -37,7 +41,6 @@
  private:
   std::unique_ptr<char[]> memory_;
   uint32_t size_;
-  DISALLOW_COPY_AND_ASSIGN(MemoryBufferBacking);
 };
 
 
@@ -46,6 +49,11 @@
   SharedMemoryBufferBacking(
       base::UnsafeSharedMemoryRegion shared_memory_region,
       base::WritableSharedMemoryMapping shared_memory_mapping);
+
+  SharedMemoryBufferBacking(const SharedMemoryBufferBacking&) = delete;
+  SharedMemoryBufferBacking& operator=(const SharedMemoryBufferBacking&) =
+      delete;
+
   ~SharedMemoryBufferBacking() override;
   const base::UnsafeSharedMemoryRegion& shared_memory_region() const override;
   base::UnguessableToken GetGUID() const override;
@@ -55,7 +63,6 @@
  private:
   base::UnsafeSharedMemoryRegion shared_memory_region_;
   base::WritableSharedMemoryMapping shared_memory_mapping_;
-  DISALLOW_COPY_AND_ASSIGN(SharedMemoryBufferBacking);
 };
 
 // Buffer owns a piece of shared-memory of a certain size.
diff --git a/gpu/command_buffer/common/command_buffer.h b/gpu/command_buffer/common/command_buffer.h
index 6335c47..b2006bc 100644
--- a/gpu/command_buffer/common/command_buffer.h
+++ b/gpu/command_buffer/common/command_buffer.h
@@ -67,6 +67,9 @@
 
   CommandBuffer() = default;
 
+  CommandBuffer(const CommandBuffer&) = delete;
+  CommandBuffer& operator=(const CommandBuffer&) = delete;
+
   virtual ~CommandBuffer() = default;
 
   // Check if a value is between a start and end value, inclusive, allowing
@@ -124,9 +127,6 @@
   // An ordering barrier must be placed after any commands that use the buffer
   // before it is safe to call this function to destroy it.
   virtual void DestroyTransferBuffer(int32_t id) = 0;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CommandBuffer);
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/common/id_allocator.h b/gpu/command_buffer/common/id_allocator.h
index 41c6e26..2fe1ff4 100644
--- a/gpu/command_buffer/common/id_allocator.h
+++ b/gpu/command_buffer/common/id_allocator.h
@@ -27,6 +27,10 @@
 class GPU_EXPORT IdAllocator {
  public:
   IdAllocator();
+
+  IdAllocator(const IdAllocator&) = delete;
+  IdAllocator& operator=(const IdAllocator&) = delete;
+
   ~IdAllocator();
 
   // Allocates a new resource ID.
@@ -58,8 +62,6 @@
   typedef std::map<ResourceId, ResourceId> ResourceIdRangeMap;
 
   ResourceIdRangeMap used_ids_;
-
-  DISALLOW_COPY_AND_ASSIGN(IdAllocator);
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/common/skia_utils.cc b/gpu/command_buffer/common/skia_utils.cc
index d19dd78..83030fa 100644
--- a/gpu/command_buffer/common/skia_utils.cc
+++ b/gpu/command_buffer/common/skia_utils.cc
@@ -31,6 +31,9 @@
         tracing_process_id_(base::trace_event::MemoryDumpManager::GetInstance()
                                 ->GetTracingProcessId()) {}
 
+  SkiaGpuTraceMemoryDump(const SkiaGpuTraceMemoryDump&) = delete;
+  SkiaGpuTraceMemoryDump& operator=(const SkiaGpuTraceMemoryDump&) = delete;
+
   ~SkiaGpuTraceMemoryDump() override = default;
 
   // Overridden from SkTraceMemoryDump:
@@ -129,8 +132,6 @@
   base::trace_event::ProcessMemoryDump* pmd_;
   absl::optional<uint64_t> share_group_tracing_guid_;
   uint64_t tracing_process_id_;
-
-  DISALLOW_COPY_AND_ASSIGN(SkiaGpuTraceMemoryDump);
 };
 
 }  // namespace
diff --git a/gpu/command_buffer/common/unittest_main.cc b/gpu/command_buffer/common/unittest_main.cc
index e479638..518a3659 100644
--- a/gpu/command_buffer/common/unittest_main.cc
+++ b/gpu/command_buffer/common/unittest_main.cc
@@ -15,10 +15,11 @@
 class GpuTestSuite : public base::TestSuite {
  public:
   GpuTestSuite(int argc, char** argv);
-  ~GpuTestSuite() override;
 
- private:
-  DISALLOW_COPY_AND_ASSIGN(GpuTestSuite);
+  GpuTestSuite(const GpuTestSuite&) = delete;
+  GpuTestSuite& operator=(const GpuTestSuite&) = delete;
+
+  ~GpuTestSuite() override;
 };
 
 GpuTestSuite::GpuTestSuite(int argc, char** argv)
diff --git a/gpu/command_buffer/service/buffer_manager.h b/gpu/command_buffer/service/buffer_manager.h
index b8588c4..15fc7bf 100644
--- a/gpu/command_buffer/service/buffer_manager.h
+++ b/gpu/command_buffer/service/buffer_manager.h
@@ -247,6 +247,10 @@
     : public base::trace_event::MemoryDumpProvider {
  public:
   BufferManager(MemoryTracker* memory_tracker, FeatureInfo* feature_info);
+
+  BufferManager(const BufferManager&) = delete;
+  BufferManager& operator=(const BufferManager&) = delete;
+
   ~BufferManager() override;
 
   void MarkContextLost();
@@ -467,8 +471,6 @@
 
   bool lost_context_;
   bool use_client_side_arrays_for_stream_buffers_;
-
-  DISALLOW_COPY_AND_ASSIGN(BufferManager);
 };
 
 }  // namespace gles2
diff --git a/gpu/command_buffer/service/command_buffer_service.h b/gpu/command_buffer/service/command_buffer_service.h
index 3e52c3d0..6d68e7e 100644
--- a/gpu/command_buffer/service/command_buffer_service.h
+++ b/gpu/command_buffer/service/command_buffer_service.h
@@ -75,6 +75,10 @@
 
   CommandBufferService(CommandBufferServiceClient* client,
                        MemoryTracker* memory_tracker);
+
+  CommandBufferService(const CommandBufferService&) = delete;
+  CommandBufferService& operator=(const CommandBufferService&) = delete;
+
   ~CommandBufferService() override;
 
   // CommandBufferServiceBase implementation:
@@ -143,8 +147,6 @@
   // Whether the scheduler is currently able to process more commands.
   bool scheduled_ = true;
   bool paused_ = false;
-
-  DISALLOW_COPY_AND_ASSIGN(CommandBufferService);
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/common_decoder.h b/gpu/command_buffer/service/common_decoder.h
index 3132b8f3..5e81686 100644
--- a/gpu/command_buffer/service/common_decoder.h
+++ b/gpu/command_buffer/service/common_decoder.h
@@ -64,6 +64,10 @@
   class GPU_EXPORT Bucket {
    public:
     Bucket();
+
+    Bucket(const Bucket&) = delete;
+    Bucket& operator=(const Bucket&) = delete;
+
     ~Bucket();
 
     size_t size() const {
@@ -112,8 +116,6 @@
 
     size_t size_;
     ::std::unique_ptr<int8_t[]> data_;
-
-    DISALLOW_COPY_AND_ASSIGN(Bucket);
   };
 
   explicit CommonDecoder(DecoderClient* client,
diff --git a/gpu/command_buffer/service/copy_texture_chromium_mock.h b/gpu/command_buffer/service/copy_texture_chromium_mock.h
index 5aa5f6c6a..637e7e4 100644
--- a/gpu/command_buffer/service/copy_texture_chromium_mock.h
+++ b/gpu/command_buffer/service/copy_texture_chromium_mock.h
@@ -17,6 +17,12 @@
     : public CopyTexImageResourceManager {
  public:
   MockCopyTexImageResourceManager(const gles2::FeatureInfo* feature_info);
+
+  MockCopyTexImageResourceManager(const MockCopyTexImageResourceManager&) =
+      delete;
+  MockCopyTexImageResourceManager& operator=(
+      const MockCopyTexImageResourceManager&) = delete;
+
   ~MockCopyTexImageResourceManager() final;
 
   MOCK_METHOD1(Initialize, void(const DecoderContext* decoder));
@@ -56,15 +62,18 @@
       GLsizei height,
       GLuint source_framebuffer,
       GLenum source_framebuffer_internal_format) override {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockCopyTexImageResourceManager);
 };
 
 class MockCopyTextureResourceManager final
     : public CopyTextureCHROMIUMResourceManager {
  public:
   MockCopyTextureResourceManager();
+
+  MockCopyTextureResourceManager(const MockCopyTextureResourceManager&) =
+      delete;
+  MockCopyTextureResourceManager& operator=(
+      const MockCopyTextureResourceManager&) = delete;
+
   ~MockCopyTextureResourceManager() final;
 
   MOCK_METHOD2(Initialize,
@@ -117,9 +126,6 @@
       bool dither,
       CopyTextureMethod method,
       CopyTexImageResourceManager* luma_emulation_blitter) override {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockCopyTextureResourceManager);
 };
 
 }  // namespace gles2
diff --git a/gpu/command_buffer/service/error_state.cc b/gpu/command_buffer/service/error_state.cc
index 4312185..8ddcda0 100644
--- a/gpu/command_buffer/service/error_state.cc
+++ b/gpu/command_buffer/service/error_state.cc
@@ -21,6 +21,10 @@
 class ErrorStateImpl : public ErrorState {
  public:
   explicit ErrorStateImpl(ErrorStateClient* client, Logger* logger);
+
+  ErrorStateImpl(const ErrorStateImpl&) = delete;
+  ErrorStateImpl& operator=(const ErrorStateImpl&) = delete;
+
   ~ErrorStateImpl() override;
 
   uint32_t GetGLError() override;
@@ -70,8 +74,6 @@
 
   ErrorStateClient* client_;
   Logger* logger_;
-
-  DISALLOW_COPY_AND_ASSIGN(ErrorStateImpl);
 };
 
 ErrorState::ErrorState() = default;
@@ -219,4 +221,3 @@
 
 }  // namespace gles2
 }  // namespace gpu
-
diff --git a/gpu/command_buffer/service/error_state.h b/gpu/command_buffer/service/error_state.h
index 3f91eaf..711762da 100644
--- a/gpu/command_buffer/service/error_state.h
+++ b/gpu/command_buffer/service/error_state.h
@@ -66,6 +66,9 @@
 
 class GPU_GLES2_EXPORT ErrorState {
  public:
+  ErrorState(const ErrorState&) = delete;
+  ErrorState& operator=(const ErrorState&) = delete;
+
   virtual ~ErrorState();
 
   static ErrorState* Create(ErrorStateClient* client, Logger* logger);
@@ -118,12 +121,9 @@
 
  protected:
   ErrorState();
-
-  DISALLOW_COPY_AND_ASSIGN(ErrorState);
 };
 
 }  // namespace gles2
 }  // namespace gpu
 
 #endif  // GPU_COMMAND_BUFFER_SERVICE_ERROR_STATE_H_
-
diff --git a/gpu/command_buffer/service/error_state_mock.h b/gpu/command_buffer/service/error_state_mock.h
index 7bd5c28..1d11812 100644
--- a/gpu/command_buffer/service/error_state_mock.h
+++ b/gpu/command_buffer/service/error_state_mock.h
@@ -19,6 +19,10 @@
 class MockErrorState : public ErrorState {
  public:
   MockErrorState();
+
+  MockErrorState(const MockErrorState&) = delete;
+  MockErrorState& operator=(const MockErrorState&) = delete;
+
   ~MockErrorState() override;
 
   MOCK_METHOD0(GetGLError, uint32_t());
@@ -48,11 +52,8 @@
       const char* file, int line, const char* filename));
   MOCK_METHOD3(ClearRealGLErrors, void(
       const char* file, int line, const char* filename));
-
-  DISALLOW_COPY_AND_ASSIGN(MockErrorState);
 };
 }  // namespace gles2
 }  // namespace gpu
 
 #endif  // GPU_COMMAND_BUFFER_SERVICE_ERROR_STATE_MOCK_H_
-
diff --git a/gpu/command_buffer/service/external_vk_image_backing.h b/gpu/command_buffer/service/external_vk_image_backing.h
index d61957a6..2bf97ee 100644
--- a/gpu/command_buffer/service/external_vk_image_backing.h
+++ b/gpu/command_buffer/service/external_vk_image_backing.h
@@ -73,6 +73,9 @@
                          VulkanCommandPool* command_pool,
                          bool use_separate_gl_texture);
 
+  ExternalVkImageBacking(const ExternalVkImageBacking&) = delete;
+  ExternalVkImageBacking& operator=(const ExternalVkImageBacking&) = delete;
+
   ~ExternalVkImageBacking() override;
 
   SharedContextState* context_state() const { return context_state_.get(); }
@@ -218,8 +221,6 @@
   // When the backing is accessed by the vulkan device for GrContext, they can
   // be returned to ExternalSemaphorePool through VulkanFenceHelper.
   std::vector<ExternalSemaphore> pending_semaphores_;
-
-  DISALLOW_COPY_AND_ASSIGN(ExternalVkImageBacking);
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/external_vk_image_dawn_representation.h b/gpu/command_buffer/service/external_vk_image_dawn_representation.h
index b215d4db..04f19c0 100644
--- a/gpu/command_buffer/service/external_vk_image_dawn_representation.h
+++ b/gpu/command_buffer/service/external_vk_image_dawn_representation.h
@@ -18,6 +18,12 @@
                                     WGPUDevice device,
                                     WGPUTextureFormat dawn_format,
                                     base::ScopedFD memory_fd);
+
+  ExternalVkImageDawnRepresentation(const ExternalVkImageDawnRepresentation&) =
+      delete;
+  ExternalVkImageDawnRepresentation& operator=(
+      const ExternalVkImageDawnRepresentation&) = delete;
+
   ~ExternalVkImageDawnRepresentation() override;
 
   WGPUTexture BeginAccess(WGPUTextureUsage usage) override;
@@ -39,8 +45,6 @@
   const DawnProcTable dawn_procs_;
 
   std::vector<ExternalSemaphore> begin_access_semaphores_;
-
-  DISALLOW_COPY_AND_ASSIGN(ExternalVkImageDawnRepresentation);
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/external_vk_image_factory.h b/gpu/command_buffer/service/external_vk_image_factory.h
index 055aedc..8b015f3 100644
--- a/gpu/command_buffer/service/external_vk_image_factory.h
+++ b/gpu/command_buffer/service/external_vk_image_factory.h
@@ -26,6 +26,10 @@
  public:
   explicit ExternalVkImageFactory(
       scoped_refptr<SharedContextState> context_state);
+
+  ExternalVkImageFactory(const ExternalVkImageFactory&) = delete;
+  ExternalVkImageFactory& operator=(const ExternalVkImageFactory&) = delete;
+
   ~ExternalVkImageFactory() override;
 
   // SharedImageBackingFactory implementation.
@@ -81,8 +85,6 @@
   std::unique_ptr<VulkanCommandPool> command_pool_;
 
   const VulkanImageUsageCache image_usage_cache_;
-
-  DISALLOW_COPY_AND_ASSIGN(ExternalVkImageFactory);
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/external_vk_image_gl_representation.h b/gpu/command_buffer/service/external_vk_image_gl_representation.h
index fec8ce5..3c15d1e 100644
--- a/gpu/command_buffer/service/external_vk_image_gl_representation.h
+++ b/gpu/command_buffer/service/external_vk_image_gl_representation.h
@@ -25,6 +25,12 @@
 
   ExternalVkImageGLRepresentationShared(SharedImageBacking* backing,
                                         GLuint texture_service_id);
+
+  ExternalVkImageGLRepresentationShared(
+      const ExternalVkImageGLRepresentationShared&) = delete;
+  ExternalVkImageGLRepresentationShared& operator=(
+      const ExternalVkImageGLRepresentationShared&) = delete;
+
   ~ExternalVkImageGLRepresentationShared();
 
   bool BeginAccess(GLenum mode);
@@ -41,8 +47,6 @@
   const GLuint texture_service_id_;
   GLenum current_access_mode_ = 0;
   std::vector<ExternalSemaphore> begin_access_semaphores_;
-
-  DISALLOW_COPY_AND_ASSIGN(ExternalVkImageGLRepresentationShared);
 };
 
 class ExternalVkImageGLRepresentation
@@ -53,6 +57,12 @@
                                   MemoryTypeTracker* tracker,
                                   gles2::Texture* texture,
                                   GLuint texture_service_id);
+
+  ExternalVkImageGLRepresentation(const ExternalVkImageGLRepresentation&) =
+      delete;
+  ExternalVkImageGLRepresentation& operator=(
+      const ExternalVkImageGLRepresentation&) = delete;
+
   ~ExternalVkImageGLRepresentation() override;
 
   // SharedImageRepresentationGLTexture implementation.
@@ -63,8 +73,6 @@
  private:
   gles2::Texture* const texture_;
   ExternalVkImageGLRepresentationShared representation_shared_;
-
-  DISALLOW_COPY_AND_ASSIGN(ExternalVkImageGLRepresentation);
 };
 
 class ExternalVkImageGLPassthroughRepresentation
@@ -74,6 +82,12 @@
                                              SharedImageBacking* backing,
                                              MemoryTypeTracker* tracker,
                                              GLuint texture_service_id);
+
+  ExternalVkImageGLPassthroughRepresentation(
+      const ExternalVkImageGLPassthroughRepresentation&) = delete;
+  ExternalVkImageGLPassthroughRepresentation& operator=(
+      const ExternalVkImageGLPassthroughRepresentation&) = delete;
+
   ~ExternalVkImageGLPassthroughRepresentation() override;
 
   // SharedImageRepresentationGLTexturePassthrough implementation.
@@ -84,8 +98,6 @@
 
  private:
   ExternalVkImageGLRepresentationShared representation_shared_;
-
-  DISALLOW_COPY_AND_ASSIGN(ExternalVkImageGLPassthroughRepresentation);
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/framebuffer_completeness_cache.h b/gpu/command_buffer/service/framebuffer_completeness_cache.h
index 53f13f1..2a642a6 100644
--- a/gpu/command_buffer/service/framebuffer_completeness_cache.h
+++ b/gpu/command_buffer/service/framebuffer_completeness_cache.h
@@ -20,6 +20,11 @@
 class GPU_GLES2_EXPORT FramebufferCompletenessCache {
  public:
   FramebufferCompletenessCache();
+
+  FramebufferCompletenessCache(const FramebufferCompletenessCache&) = delete;
+  FramebufferCompletenessCache& operator=(const FramebufferCompletenessCache&) =
+      delete;
+
   ~FramebufferCompletenessCache();
 
   bool IsComplete(const std::string& signature) const;
@@ -29,8 +34,6 @@
   typedef std::unordered_set<std::string> Map;
 
   Map cache_;
-
-  DISALLOW_COPY_AND_ASSIGN(FramebufferCompletenessCache);
 };
 
 }  // namespace gles2
diff --git a/gpu/command_buffer/service/framebuffer_manager.h b/gpu/command_buffer/service/framebuffer_manager.h
index 3b14720..42e2b83 100644
--- a/gpu/command_buffer/service/framebuffer_manager.h
+++ b/gpu/command_buffer/service/framebuffer_manager.h
@@ -341,6 +341,10 @@
       uint32_t max_draw_buffers,
       uint32_t max_color_attachments,
       FramebufferCompletenessCache* framebuffer_combo_complete_cache);
+
+  FramebufferManager(const FramebufferManager&) = delete;
+  FramebufferManager& operator=(const FramebufferManager&) = delete;
+
   ~FramebufferManager();
 
   // Must call before destruction.
@@ -401,8 +405,6 @@
   uint32_t max_color_attachments_;
 
   FramebufferCompletenessCache* framebuffer_combo_complete_cache_;
-
-  DISALLOW_COPY_AND_ASSIGN(FramebufferManager);
 };
 
 }  // namespace gles2
diff --git a/gpu/command_buffer/service/gl_state_restorer_impl.h b/gpu/command_buffer/service/gl_state_restorer_impl.h
index 4385129e..f9fbe111 100644
--- a/gpu/command_buffer/service/gl_state_restorer_impl.h
+++ b/gpu/command_buffer/service/gl_state_restorer_impl.h
@@ -26,6 +26,10 @@
  public:
   explicit GLStateRestorerImpl(
       base::WeakPtr<GLContextVirtualDelegate> delegate);
+
+  GLStateRestorerImpl(const GLStateRestorerImpl&) = delete;
+  GLStateRestorerImpl& operator=(const GLStateRestorerImpl&) = delete;
+
   ~GLStateRestorerImpl() override;
 
   bool IsInitialized() override;
@@ -44,8 +48,6 @@
  private:
   const gles2::ContextState* GetContextState() const;
   base::WeakPtr<GLContextVirtualDelegate> delegate_;
-
-  DISALLOW_COPY_AND_ASSIGN(GLStateRestorerImpl);
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/gles2_cmd_clear_framebuffer.h b/gpu/command_buffer/service/gles2_cmd_clear_framebuffer.h
index 81533a0..23a2fb8 100644
--- a/gpu/command_buffer/service/gles2_cmd_clear_framebuffer.h
+++ b/gpu/command_buffer/service/gles2_cmd_clear_framebuffer.h
@@ -20,6 +20,12 @@
 class GPU_GLES2_EXPORT ClearFramebufferResourceManager {
  public:
   ClearFramebufferResourceManager(const gles2::GLES2Decoder* decoder);
+
+  ClearFramebufferResourceManager(const ClearFramebufferResourceManager&) =
+      delete;
+  ClearFramebufferResourceManager& operator=(
+      const ClearFramebufferResourceManager&) = delete;
+
   ~ClearFramebufferResourceManager();
 
   void Destroy();
@@ -44,8 +50,6 @@
   GLuint depth_handle_;
   GLuint color_handle_;
   GLuint buffer_id_;
-
-  DISALLOW_COPY_AND_ASSIGN(ClearFramebufferResourceManager);
 };
 
 }  // namespace gles2
diff --git a/gpu/command_buffer/service/gles2_cmd_copy_tex_image.h b/gpu/command_buffer/service/gles2_cmd_copy_tex_image.h
index 409da846..6683c66 100644
--- a/gpu/command_buffer/service/gles2_cmd_copy_tex_image.h
+++ b/gpu/command_buffer/service/gles2_cmd_copy_tex_image.h
@@ -22,6 +22,11 @@
 class GPU_GLES2_EXPORT CopyTexImageResourceManager {
  public:
   explicit CopyTexImageResourceManager(const gles2::FeatureInfo* feature_info);
+
+  CopyTexImageResourceManager(const CopyTexImageResourceManager&) = delete;
+  CopyTexImageResourceManager& operator=(const CopyTexImageResourceManager&) =
+      delete;
+
   virtual ~CopyTexImageResourceManager();
 
   virtual void Initialize(const DecoderContext* decoder);
@@ -75,8 +80,6 @@
   GLuint scratch_fbo_ = 0;
 
   GLuint vao_ = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(CopyTexImageResourceManager);
 };
 
 }  // namespace gles2
diff --git a/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h b/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h
index b279a6a..8b587da 100644
--- a/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h
+++ b/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h
@@ -45,6 +45,11 @@
 // The target of |dest_id| texture must be GL_TEXTURE_2D.
 class GPU_GLES2_EXPORT CopyTextureCHROMIUMResourceManager {
  public:
+  CopyTextureCHROMIUMResourceManager(
+      const CopyTextureCHROMIUMResourceManager&) = delete;
+  CopyTextureCHROMIUMResourceManager& operator=(
+      const CopyTextureCHROMIUMResourceManager&) = delete;
+
   virtual ~CopyTextureCHROMIUMResourceManager();
 
   // Factory generating a real implementation.
@@ -106,9 +111,6 @@
 
  protected:
   CopyTextureCHROMIUMResourceManager();
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CopyTextureCHROMIUMResourceManager);
 };
 
 }  // namespace gles2
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 608c3d4..429880e 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -291,11 +291,14 @@
  public:
   explicit ScopedGLErrorSuppressor(
       const char* function_name, ErrorState* error_state);
+
+  ScopedGLErrorSuppressor(const ScopedGLErrorSuppressor&) = delete;
+  ScopedGLErrorSuppressor& operator=(const ScopedGLErrorSuppressor&) = delete;
+
   ~ScopedGLErrorSuppressor();
  private:
   const char* function_name_;
   ErrorState* error_state_;
-  DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
 };
 
 // Temporarily changes a decoder's bound texture and restore it when this
@@ -307,13 +310,16 @@
                                ErrorState* error_state,
                                GLuint id,
                                GLenum target);
+
+  ScopedTextureBinder(const ScopedTextureBinder&) = delete;
+  ScopedTextureBinder& operator=(const ScopedTextureBinder&) = delete;
+
   ~ScopedTextureBinder();
 
  private:
   ContextState* state_;
   ErrorState* error_state_;
   GLenum target_;
-  DISALLOW_COPY_AND_ASSIGN(ScopedTextureBinder);
 };
 
 // Temporarily changes a decoder's bound render buffer and restore it when this
@@ -323,12 +329,15 @@
   explicit ScopedRenderBufferBinder(ContextState* state,
                                     ErrorState* error_state,
                                     GLuint id);
+
+  ScopedRenderBufferBinder(const ScopedRenderBufferBinder&) = delete;
+  ScopedRenderBufferBinder& operator=(const ScopedRenderBufferBinder&) = delete;
+
   ~ScopedRenderBufferBinder();
 
  private:
   ContextState* state_;
   ErrorState* error_state_;
-  DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
 };
 
 // Temporarily changes a decoder's bound frame buffer and restore it when this
@@ -336,11 +345,14 @@
 class ScopedFramebufferBinder {
  public:
   explicit ScopedFramebufferBinder(GLES2DecoderImpl* decoder, GLuint id);
+
+  ScopedFramebufferBinder(const ScopedFramebufferBinder&) = delete;
+  ScopedFramebufferBinder& operator=(const ScopedFramebufferBinder&) = delete;
+
   ~ScopedFramebufferBinder();
 
  private:
   GLES2DecoderImpl* decoder_;
-  DISALLOW_COPY_AND_ASSIGN(ScopedFramebufferBinder);
 };
 
 // Temporarily changes a decoder's bound frame buffer to a resolved version of
@@ -352,12 +364,17 @@
   explicit ScopedResolvedFramebufferBinder(GLES2DecoderImpl* decoder,
                                            bool enforce_internal_framebuffer,
                                            bool internal);
+
+  ScopedResolvedFramebufferBinder(const ScopedResolvedFramebufferBinder&) =
+      delete;
+  ScopedResolvedFramebufferBinder& operator=(
+      const ScopedResolvedFramebufferBinder&) = delete;
+
   ~ScopedResolvedFramebufferBinder();
 
  private:
   GLES2DecoderImpl* decoder_;
   bool resolve_and_bind_;
-  DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFramebufferBinder);
 };
 
 // Temporarily create and bind a single sample copy of the currently bound
@@ -372,6 +389,10 @@
                                        GLint width = 0,
                                        GLint height = 0);
 
+  ScopedFramebufferCopyBinder(const ScopedFramebufferCopyBinder&) = delete;
+  ScopedFramebufferCopyBinder& operator=(const ScopedFramebufferCopyBinder&) =
+      delete;
+
   ~ScopedFramebufferCopyBinder();
 
  private:
@@ -379,7 +400,6 @@
   std::unique_ptr<ScopedFramebufferBinder> framebuffer_binder_;
   GLuint temp_texture_;
   GLuint temp_framebuffer_;
-  DISALLOW_COPY_AND_ASSIGN(ScopedFramebufferCopyBinder);
 };
 
 // Temporarily changes a decoder's PIXEL_UNPACK_BUFFER to 0 and set pixel unpack
@@ -387,17 +407,24 @@
 class ScopedPixelUnpackState {
  public:
   explicit ScopedPixelUnpackState(ContextState* state);
+
+  ScopedPixelUnpackState(const ScopedPixelUnpackState&) = delete;
+  ScopedPixelUnpackState& operator=(const ScopedPixelUnpackState&) = delete;
+
   ~ScopedPixelUnpackState();
 
  private:
   ContextState* state_;
-  DISALLOW_COPY_AND_ASSIGN(ScopedPixelUnpackState);
 };
 
 // Encapsulates an OpenGL texture.
 class BackTexture {
  public:
   explicit BackTexture(GLES2DecoderImpl* decoder);
+
+  BackTexture(const BackTexture&) = delete;
+  BackTexture& operator=(const BackTexture&) = delete;
+
   ~BackTexture();
 
   // Create a new render texture.
@@ -452,14 +479,16 @@
   // The image that backs the texture, if its backed by a native
   // GpuMemoryBuffer.
   scoped_refptr<gl::GLImage> image_;
-
-  DISALLOW_COPY_AND_ASSIGN(BackTexture);
 };
 
 // Encapsulates an OpenGL render buffer of any format.
 class BackRenderbuffer {
  public:
   explicit BackRenderbuffer(GLES2DecoderImpl* decoder);
+
+  BackRenderbuffer(const BackRenderbuffer&) = delete;
+  BackRenderbuffer& operator=(const BackRenderbuffer&) = delete;
+
   ~BackRenderbuffer();
 
   // Create a new render buffer.
@@ -487,13 +516,16 @@
   MemoryTypeTracker memory_tracker_;
   size_t bytes_allocated_;
   GLuint id_;
-  DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer);
 };
 
 // Encapsulates an OpenGL frame buffer.
 class BackFramebuffer {
  public:
   explicit BackFramebuffer(GLES2DecoderImpl* decoder);
+
+  BackFramebuffer(const BackFramebuffer&) = delete;
+  BackFramebuffer& operator=(const BackFramebuffer&) = delete;
+
   ~BackFramebuffer();
 
   // Create a new frame buffer.
@@ -526,7 +558,6 @@
  private:
   GLES2DecoderImpl* decoder_;
   GLuint id_;
-  DISALLOW_COPY_AND_ASSIGN(BackFramebuffer);
 };
 
 struct FenceCallback {
@@ -617,6 +648,10 @@
                    CommandBufferServiceBase* command_buffer_service,
                    Outputter* outputter,
                    ContextGroup* group);
+
+  GLES2DecoderImpl(const GLES2DecoderImpl&) = delete;
+  GLES2DecoderImpl& operator=(const GLES2DecoderImpl&) = delete;
+
   ~GLES2DecoderImpl() override;
 
   error::Error DoCommands(unsigned int num_commands,
@@ -2830,8 +2865,6 @@
   std::set<scoped_refptr<TextureRef>> texture_refs_pending_destruction_;
 
   base::WeakPtrFactory<GLES2DecoderImpl> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
 };
 
 constexpr GLES2DecoderImpl::CommandInfo GLES2DecoderImpl::command_info[] = {
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.h b/gpu/command_buffer/service/gles2_cmd_decoder.h
index 5019ce3d..63bbe7c 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.h
@@ -106,6 +106,9 @@
                               Outputter* outputter,
                               ContextGroup* group);
 
+  GLES2Decoder(const GLES2Decoder&) = delete;
+  GLES2Decoder& operator=(const GLES2Decoder&) = delete;
+
   ~GLES2Decoder() override;
 
   // DecoderContext implementation.
@@ -212,8 +215,6 @@
   bool debug_ = false;
   bool log_commands_ = false;
   Outputter* outputter_ = nullptr;
-
-  DISALLOW_COPY_AND_ASSIGN(GLES2Decoder);
 };
 
 }  // namespace gles2
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
index d740594..0e2bc3e 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
@@ -40,6 +40,10 @@
   MockGLES2Decoder(DecoderClient* client,
                    CommandBufferServiceBase* command_buffer_service,
                    Outputter* outputter);
+
+  MockGLES2Decoder(const MockGLES2Decoder&) = delete;
+  MockGLES2Decoder& operator=(const MockGLES2Decoder&) = delete;
+
   ~MockGLES2Decoder() override;
 
   base::WeakPtr<DecoderContext> AsWeakPtr() override;
@@ -186,8 +190,6 @@
 
  private:
   base::WeakPtrFactory<MockGLES2Decoder> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(MockGLES2Decoder);
 };
 
 }  // namespace gles2
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h
index 227995e..bb6a9447 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h
@@ -101,6 +101,10 @@
         std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
             representation);
     SharedImageData(SharedImageData&& other);
+
+    SharedImageData(const SharedImageData&) = delete;
+    SharedImageData& operator=(const SharedImageData&) = delete;
+
     ~SharedImageData();
     SharedImageData& operator=(SharedImageData&& other);
 
@@ -122,7 +126,6 @@
         representation_;
     std::unique_ptr<SharedImageRepresentationGLTexturePassthrough::ScopedAccess>
         scoped_access_;
-    DISALLOW_COPY_AND_ASSIGN(SharedImageData);
   };
   // Mapping of client texture IDs to
   // SharedImageRepresentationGLTexturePassthroughs.
diff --git a/gpu/command_buffer/service/gles2_cmd_srgb_converter.h b/gpu/command_buffer/service/gles2_cmd_srgb_converter.h
index 8518a14..8cec58b 100644
--- a/gpu/command_buffer/service/gles2_cmd_srgb_converter.h
+++ b/gpu/command_buffer/service/gles2_cmd_srgb_converter.h
@@ -23,6 +23,10 @@
 class GPU_GLES2_EXPORT SRGBConverter {
  public:
   explicit SRGBConverter(const gles2::FeatureInfo* feature_info);
+
+  SRGBConverter(const SRGBConverter&) = delete;
+  SRGBConverter& operator=(const SRGBConverter&) = delete;
+
   ~SRGBConverter();
 
   void InitializeSRGBConverter(const gles2::GLES2Decoder* decoder);
@@ -67,8 +71,6 @@
   GLuint srgb_encoder_fbo_ = 0;
 
   GLuint srgb_converter_vao_ = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(SRGBConverter);
 };
 
 }  // namespace gles2.
diff --git a/gpu/command_buffer/service/gpu_command_buffer_memory_tracker.h b/gpu/command_buffer/service/gpu_command_buffer_memory_tracker.h
index 4161af934..f0a5c79 100644
--- a/gpu/command_buffer/service/gpu_command_buffer_memory_tracker.h
+++ b/gpu/command_buffer/service/gpu_command_buffer_memory_tracker.h
@@ -26,6 +26,11 @@
       uint64_t client_tracing_id,
       scoped_refptr<base::SingleThreadTaskRunner> task_runner,
       Observer* observer);
+
+  GpuCommandBufferMemoryTracker(const GpuCommandBufferMemoryTracker&) = delete;
+  GpuCommandBufferMemoryTracker& operator=(
+      const GpuCommandBufferMemoryTracker&) = delete;
+
   ~GpuCommandBufferMemoryTracker() override;
 
   // MemoryTracker implementation.
@@ -41,8 +46,6 @@
   const uint64_t client_tracing_id_;
 
   MemoryTracker::Observer* const observer_;
-
-  DISALLOW_COPY_AND_ASSIGN(GpuCommandBufferMemoryTracker);
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/gpu_fence_manager.h b/gpu/command_buffer/service/gpu_fence_manager.h
index c2a116a..f093e29 100644
--- a/gpu/command_buffer/service/gpu_fence_manager.h
+++ b/gpu/command_buffer/service/gpu_fence_manager.h
@@ -31,6 +31,10 @@
   class GPU_GLES2_EXPORT GpuFenceEntry {
    public:
     GpuFenceEntry();
+
+    GpuFenceEntry(const GpuFenceEntry&) = delete;
+    GpuFenceEntry& operator=(const GpuFenceEntry&) = delete;
+
     ~GpuFenceEntry();
 
     GpuFenceEntry(GpuFenceEntry&& other);
@@ -44,12 +48,14 @@
     // at the time the wait is issued.
     gfx::GpuFenceHandle fence_handle_;
     std::unique_ptr<gl::GLFence> gl_fence_;
-
-    DISALLOW_COPY_AND_ASSIGN(GpuFenceEntry);
   };
 
  public:
   GpuFenceManager();
+
+  GpuFenceManager(const GpuFenceManager&) = delete;
+  GpuFenceManager& operator=(const GpuFenceManager&) = delete;
+
   ~GpuFenceManager();
 
   bool CreateGpuFence(uint32_t client_id);
@@ -71,8 +77,6 @@
   using GpuFenceEntryMap =
       base::flat_map<uint32_t, std::unique_ptr<GpuFenceEntry>>;
   GpuFenceEntryMap gpu_fence_entries_;
-
-  DISALLOW_COPY_AND_ASSIGN(GpuFenceManager);
 };
 
 }  // namespace gles2
diff --git a/gpu/command_buffer/service/gpu_state_tracer.cc b/gpu/command_buffer/service/gpu_state_tracer.cc
index 023a315..8cc92c6aa 100644
--- a/gpu/command_buffer/service/gpu_state_tracer.cc
+++ b/gpu/command_buffer/service/gpu_state_tracer.cc
@@ -22,6 +22,9 @@
  public:
   static std::unique_ptr<Snapshot> Create(const ContextState* state);
 
+  Snapshot(const Snapshot&) = delete;
+  Snapshot& operator=(const Snapshot&) = delete;
+
   ~Snapshot() override = default;
 
   // Save a screenshot of the currently bound framebuffer.
@@ -37,8 +40,6 @@
 
   std::vector<unsigned char> screenshot_pixels_;
   gfx::Size screenshot_size_;
-
-  DISALLOW_COPY_AND_ASSIGN(Snapshot);
 };
 
 }  // namespace
diff --git a/gpu/command_buffer/service/gpu_state_tracer.h b/gpu/command_buffer/service/gpu_state_tracer.h
index 09a873bd..ba6ed6d 100644
--- a/gpu/command_buffer/service/gpu_state_tracer.h
+++ b/gpu/command_buffer/service/gpu_state_tracer.h
@@ -22,6 +22,10 @@
 class GPUStateTracer {
  public:
   static std::unique_ptr<GPUStateTracer> Create(const ContextState* state);
+
+  GPUStateTracer(const GPUStateTracer&) = delete;
+  GPUStateTracer& operator=(const GPUStateTracer&) = delete;
+
   ~GPUStateTracer();
 
   // Take a state snapshot with a screenshot of the currently bound framebuffer.
@@ -31,7 +35,6 @@
   explicit GPUStateTracer(const ContextState* state);
 
   const ContextState* state_;
-  DISALLOW_COPY_AND_ASSIGN(GPUStateTracer);
 };
 
 }  // namespace gles2
diff --git a/gpu/command_buffer/service/gpu_tracer.h b/gpu/command_buffer/service/gpu_tracer.h
index bc512e4..4f3b7c2 100644
--- a/gpu/command_buffer/service/gpu_tracer.h
+++ b/gpu/command_buffer/service/gpu_tracer.h
@@ -58,6 +58,10 @@
 class GPU_GLES2_EXPORT GPUTracer {
  public:
   explicit GPUTracer(DecoderContext* decoder, bool context_is_gl = true);
+
+  GPUTracer(const GPUTracer&) = delete;
+  GPUTracer& operator=(const GPUTracer&) = delete;
+
   virtual ~GPUTracer();
 
   void Destroy(bool have_context);
@@ -110,8 +114,6 @@
   int64_t disjoint_time_ = 0;
   bool gpu_executing_ = false;
   bool began_device_traces_ = false;
-
-  DISALLOW_COPY_AND_ASSIGN(GPUTracer);
 };
 
 class GPU_GLES2_EXPORT Outputter {
@@ -137,6 +139,10 @@
  public:
   TraceOutputter();
   explicit TraceOutputter(const std::string& name);
+
+  TraceOutputter(const TraceOutputter&) = delete;
+  TraceOutputter& operator=(const TraceOutputter&) = delete;
+
   ~TraceOutputter() override;
 
   void TraceDevice(GpuTracerSource source,
@@ -160,8 +166,6 @@
   uint64_t local_trace_service_id_ = 0;
 
   base::stack<uint64_t> trace_service_id_stack_[NUM_TRACER_SOURCES];
-
-  DISALLOW_COPY_AND_ASSIGN(TraceOutputter);
 };
 
 class GPU_GLES2_EXPORT GPUTrace : public base::RefCounted<GPUTrace> {
diff --git a/gpu/command_buffer/service/gr_cache_controller.h b/gpu/command_buffer/service/gr_cache_controller.h
index f218867..b48696d00 100644
--- a/gpu/command_buffer/service/gr_cache_controller.h
+++ b/gpu/command_buffer/service/gr_cache_controller.h
@@ -23,6 +23,10 @@
 class GPU_GLES2_EXPORT GrCacheController {
  public:
   explicit GrCacheController(SharedContextState* context_state);
+
+  GrCacheController(const GrCacheController&) = delete;
+  GrCacheController& operator=(const GrCacheController&) = delete;
+
   ~GrCacheController();
 
   // Called to schedule purging the GrCache after a period of inactivity.
@@ -45,8 +49,6 @@
   base::CancelableOnceClosure purge_gr_cache_cb_;
   SharedContextState* context_state_;
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-
-  DISALLOW_COPY_AND_ASSIGN(GrCacheController);
 };
 
 }  // namespace raster
diff --git a/gpu/command_buffer/service/id_manager.h b/gpu/command_buffer/service/id_manager.h
index 5f3c273..526520f2 100644
--- a/gpu/command_buffer/service/id_manager.h
+++ b/gpu/command_buffer/service/id_manager.h
@@ -21,6 +21,10 @@
 class GPU_GLES2_EXPORT IdManager {
  public:
   IdManager();
+
+  IdManager(const IdManager&) = delete;
+  IdManager& operator=(const IdManager&) = delete;
+
   ~IdManager();
 
   // Maps a client_id to a service_id. Return false if the client_id or
@@ -41,8 +45,6 @@
  private:
   typedef std::unordered_map<GLuint, GLuint> MapType;
   MapType id_map_;
-
-  DISALLOW_COPY_AND_ASSIGN(IdManager);
 };
 
 }  // namespace gles2
diff --git a/gpu/command_buffer/service/image_manager.h b/gpu/command_buffer/service/image_manager.h
index 29fa832..ac8f081 100644
--- a/gpu/command_buffer/service/image_manager.h
+++ b/gpu/command_buffer/service/image_manager.h
@@ -24,6 +24,10 @@
 class GPU_EXPORT ImageManager {
  public:
   ImageManager();
+
+  ImageManager(const ImageManager&) = delete;
+  ImageManager& operator=(const ImageManager&) = delete;
+
   ~ImageManager();
 
   void AddImage(gl::GLImage* image, int32_t service_id);
@@ -33,8 +37,6 @@
  private:
   typedef std::unordered_map<int32_t, scoped_refptr<gl::GLImage>> GLImageMap;
   GLImageMap images_;
-
-  DISALLOW_COPY_AND_ASSIGN(ImageManager);
 };
 
 }  // namespage gles2
diff --git a/gpu/command_buffer/service/image_reader_gl_owner.h b/gpu/command_buffer/service/image_reader_gl_owner.h
index fe32417..514a038 100644
--- a/gpu/command_buffer/service/image_reader_gl_owner.h
+++ b/gpu/command_buffer/service/image_reader_gl_owner.h
@@ -68,6 +68,10 @@
     ScopedCurrentImageRef(ImageReaderGLOwner* texture_owner,
                           AImage* image,
                           base::ScopedFD ready_fence);
+
+    ScopedCurrentImageRef(const ScopedCurrentImageRef&) = delete;
+    ScopedCurrentImageRef& operator=(const ScopedCurrentImageRef&) = delete;
+
     ~ScopedCurrentImageRef();
     AImage* image() const { return image_; }
     base::ScopedFD GetReadyFence() const;
@@ -80,8 +84,6 @@
 
     // Set to true if the current image is bound to |texture_id_|.
     bool image_bound_ = false;
-
-    DISALLOW_COPY_AND_ASSIGN(ScopedCurrentImageRef);
   };
 
   ImageReaderGLOwner(std::unique_ptr<gles2::AbstractTexture> texture,
diff --git a/gpu/command_buffer/service/logger.h b/gpu/command_buffer/service/logger.h
index d5f6a5a..84c9d6cc 100644
--- a/gpu/command_buffer/service/logger.h
+++ b/gpu/command_buffer/service/logger.h
@@ -30,6 +30,10 @@
   Logger(const DebugMarkerManager* debug_marker_manager,
          const LogMessageCallback& callback,
          bool disable_gl_error_limit);
+
+  Logger(const Logger&) = delete;
+  Logger& operator=(const Logger&) = delete;
+
   ~Logger();
 
   void LogMessage(const char* filename, int line, const std::string& msg);
@@ -52,8 +56,6 @@
   int log_message_count_;
   bool log_synthesized_gl_errors_;
   bool disable_gl_error_limit_;
-
-  DISALLOW_COPY_AND_ASSIGN(Logger);
 };
 
 }  // namespace gles2
diff --git a/gpu/command_buffer/service/mailbox_manager_dummy.h b/gpu/command_buffer/service/mailbox_manager_dummy.h
index 7bce5010..6e864bf3 100644
--- a/gpu/command_buffer/service/mailbox_manager_dummy.h
+++ b/gpu/command_buffer/service/mailbox_manager_dummy.h
@@ -18,15 +18,16 @@
 class GPU_GLES2_EXPORT MailboxManagerDummy : public MailboxManager {
  public:
   MailboxManagerDummy();
+
+  MailboxManagerDummy(const MailboxManagerDummy&) = delete;
+  MailboxManagerDummy& operator=(const MailboxManagerDummy&) = delete;
+
   ~MailboxManagerDummy() override;
 
   // MailboxManager implementation:
   TextureBase* ConsumeTexture(const Mailbox& mailbox) override;
   void ProduceTexture(const Mailbox& mailbox, TextureBase* texture) override {}
   void TextureDeleted(TextureBase* texture) override {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MailboxManagerDummy);
 };
 
 }  // namespace gles2
diff --git a/gpu/command_buffer/service/mailbox_manager_impl.h b/gpu/command_buffer/service/mailbox_manager_impl.h
index a4fea4b..23d5305 100644
--- a/gpu/command_buffer/service/mailbox_manager_impl.h
+++ b/gpu/command_buffer/service/mailbox_manager_impl.h
@@ -22,6 +22,10 @@
 class GPU_GLES2_EXPORT MailboxManagerImpl : public MailboxManager {
  public:
   MailboxManagerImpl();
+
+  MailboxManagerImpl(const MailboxManagerImpl&) = delete;
+  MailboxManagerImpl& operator=(const MailboxManagerImpl&) = delete;
+
   ~MailboxManagerImpl() override;
 
   // MailboxManager implementation:
@@ -40,12 +44,9 @@
 
   MailboxToTextureMap mailbox_to_textures_;
   TextureToMailboxMap textures_to_mailboxes_;
-
-  DISALLOW_COPY_AND_ASSIGN(MailboxManagerImpl);
 };
 
 }  // namespage gles2
 }  // namespace gpu
 
 #endif  // GPU_COMMAND_BUFFER_SERVICE_MAILBOX_MANAGER_IMPL_H_
-
diff --git a/gpu/command_buffer/service/mailbox_manager_unittest.cc b/gpu/command_buffer/service/mailbox_manager_unittest.cc
index 0a89fe9..8a3b7950 100644
--- a/gpu/command_buffer/service/mailbox_manager_unittest.cc
+++ b/gpu/command_buffer/service/mailbox_manager_unittest.cc
@@ -23,6 +23,10 @@
 class MailboxManagerTest : public GpuServiceTest {
  public:
   MailboxManagerTest() = default;
+
+  MailboxManagerTest(const MailboxManagerTest&) = delete;
+  MailboxManagerTest& operator=(const MailboxManagerTest&) = delete;
+
   ~MailboxManagerTest() override = default;
 
  protected:
@@ -72,8 +76,6 @@
 
  private:
   scoped_refptr<FeatureInfo> feature_info_;
-
-  DISALLOW_COPY_AND_ASSIGN(MailboxManagerTest);
 };
 
 // Tests basic produce/consume behavior.
diff --git a/gpu/command_buffer/service/memory_program_cache.h b/gpu/command_buffer/service/memory_program_cache.h
index 06b2e64f..bc10eec7 100644
--- a/gpu/command_buffer/service/memory_program_cache.h
+++ b/gpu/command_buffer/service/memory_program_cache.h
@@ -31,6 +31,10 @@
                      bool disable_gpu_shader_disk_cache,
                      bool disable_program_caching_for_transform_feedback,
                      GpuProcessActivityFlags* activity_flags);
+
+  MemoryProgramCache(const MemoryProgramCache&) = delete;
+  MemoryProgramCache& operator=(const MemoryProgramCache&) = delete;
+
   ~MemoryProgramCache() override;
 
   ProgramLoadResult LoadLinkedProgram(
@@ -174,8 +178,6 @@
   size_t curr_size_bytes_;
   ProgramMRUCache store_;
   GpuProcessActivityFlags* activity_flags_;
-
-  DISALLOW_COPY_AND_ASSIGN(MemoryProgramCache);
 };
 
 }  // namespace gles2
diff --git a/gpu/command_buffer/service/memory_tracking.h b/gpu/command_buffer/service/memory_tracking.h
index eac32da..4b93502 100644
--- a/gpu/command_buffer/service/memory_tracking.h
+++ b/gpu/command_buffer/service/memory_tracking.h
@@ -29,6 +29,10 @@
   class Observer {
    public:
     Observer() = default;
+
+    Observer(const Observer&) = delete;
+    Observer& operator=(const Observer&) = delete;
+
     virtual ~Observer() = default;
 
     virtual void OnMemoryAllocatedChange(
@@ -36,9 +40,6 @@
         uint64_t old_size,
         uint64_t new_size,
         GpuPeakMemoryAllocationSource source) = 0;
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(Observer);
   };
 
   virtual ~MemoryTracker() = default;
@@ -68,6 +69,10 @@
   // For testing.
   MemoryTypeTracker(MemoryTracker* memory_tracker,
                     scoped_refptr<base::SequencedTaskRunner> task_runner);
+
+  MemoryTypeTracker(const MemoryTypeTracker&) = delete;
+  MemoryTypeTracker& operator=(const MemoryTypeTracker&) = delete;
+
   ~MemoryTypeTracker();
 
   void TrackMemAlloc(size_t bytes);
@@ -84,8 +89,6 @@
 
   scoped_refptr<base::SequencedTaskRunner> task_runner_;
   base::WeakPtrFactory<MemoryTypeTracker> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(MemoryTypeTracker);
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/passthrough_discardable_manager.h b/gpu/command_buffer/service/passthrough_discardable_manager.h
index c69055af..59b251f 100644
--- a/gpu/command_buffer/service/passthrough_discardable_manager.h
+++ b/gpu/command_buffer/service/passthrough_discardable_manager.h
@@ -20,6 +20,11 @@
 class GPU_GLES2_EXPORT PassthroughDiscardableManager {
  public:
   explicit PassthroughDiscardableManager(const GpuPreferences& preferences);
+
+  PassthroughDiscardableManager(const PassthroughDiscardableManager&) = delete;
+  PassthroughDiscardableManager& operator=(
+      const PassthroughDiscardableManager&) = delete;
+
   ~PassthroughDiscardableManager();
 
   void InitializeTexture(uint32_t client_id,
@@ -99,8 +104,6 @@
 
   // The limit above which the cache will start evicting resources.
   size_t cache_size_limit_ = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(PassthroughDiscardableManager);
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/passthrough_program_cache.h b/gpu/command_buffer/service/passthrough_program_cache.h
index cb2d05d5..459f23a7c 100644
--- a/gpu/command_buffer/service/passthrough_program_cache.h
+++ b/gpu/command_buffer/service/passthrough_program_cache.h
@@ -23,6 +23,10 @@
  public:
   PassthroughProgramCache(size_t max_cache_size_bytes,
                           bool disable_gpu_shader_disk_cache);
+
+  PassthroughProgramCache(const PassthroughProgramCache&) = delete;
+  PassthroughProgramCache& operator=(const PassthroughProgramCache&) = delete;
+
   ~PassthroughProgramCache() override;
 
   ProgramLoadResult LoadLinkedProgram(
@@ -64,6 +68,10 @@
    public:
     ProgramCacheValue(Value&& program_blob,
                       PassthroughProgramCache* program_cache);
+
+    ProgramCacheValue(const ProgramCacheValue&) = delete;
+    ProgramCacheValue& operator=(const ProgramCacheValue&) = delete;
+
     ~ProgramCacheValue();
 
     ProgramCacheValue(ProgramCacheValue&& other);
@@ -74,8 +82,6 @@
    private:
     Value program_blob_;
     PassthroughProgramCache* program_cache_;
-
-    DISALLOW_COPY_AND_ASSIGN(ProgramCacheValue);
   };
 
   void ClearBackend() override;
@@ -94,8 +100,6 @@
 
   // TODO(syoussefi): take compression from memory_program_cache, see
   // compress_program_binaries_
-
-  DISALLOW_COPY_AND_ASSIGN(PassthroughProgramCache);
 };
 
 }  // namespace gles2
diff --git a/gpu/command_buffer/service/program_manager.h b/gpu/command_buffer/service/program_manager.h
index f99a099b..16bc087 100644
--- a/gpu/command_buffer/service/program_manager.h
+++ b/gpu/command_buffer/service/program_manager.h
@@ -653,6 +653,10 @@
                  const GpuPreferences& gpu_preferences,
                  FeatureInfo* feature_info,
                  gl::ProgressReporter* progress_reporter);
+
+  ProgramManager(const ProgramManager&) = delete;
+  ProgramManager& operator=(const ProgramManager&) = delete;
+
   ~ProgramManager();
 
   // Must call before destruction.
@@ -752,8 +756,6 @@
   // preventing time-outs when destruction takes a long time. May be null when
   // using in-process command buffer.
   gl::ProgressReporter* progress_reporter_;
-
-  DISALLOW_COPY_AND_ASSIGN(ProgramManager);
 };
 
 inline const FeatureInfo& Program::feature_info() const {
diff --git a/gpu/command_buffer/service/raster_decoder.cc b/gpu/command_buffer/service/raster_decoder.cc
index 05e017e..eccd1a3c 100644
--- a/gpu/command_buffer/service/raster_decoder.cc
+++ b/gpu/command_buffer/service/raster_decoder.cc
@@ -124,6 +124,10 @@
       : function_name_(function_name), error_state_(error_state) {
     ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_, function_name_);
   }
+
+  ScopedGLErrorSuppressor(const ScopedGLErrorSuppressor&) = delete;
+  ScopedGLErrorSuppressor& operator=(const ScopedGLErrorSuppressor&) = delete;
+
   ~ScopedGLErrorSuppressor() {
     ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_, function_name_);
   }
@@ -131,7 +135,6 @@
  private:
   const char* function_name_;
   gles2::ErrorState* error_state_;
-  DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
 };
 
 // Temporarily changes a decoder's bound texture and restore it when this
@@ -151,13 +154,14 @@
       gr_context->resetContext(kTextureBinding_GrGLBackendState);
   }
 
+  ScopedTextureBinder(const ScopedTextureBinder&) = delete;
+  ScopedTextureBinder& operator=(const ScopedTextureBinder&) = delete;
+
   ~ScopedTextureBinder() { state_->api()->glBindTextureFn(target_, 0); }
 
  private:
   gles2::ContextState* state_;
   GLenum target_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedTextureBinder);
 };
 
 // Temporarily changes a decoder's PIXEL_UNPACK_BUFFER to 0 and set pixel
@@ -185,10 +189,11 @@
                                kPixelStore_GrGLBackendState);
     }
   }
-  ~ScopedPixelUnpackState() = default;
 
- private:
-  DISALLOW_COPY_AND_ASSIGN(ScopedPixelUnpackState);
+  ScopedPixelUnpackState(const ScopedPixelUnpackState&) = delete;
+  ScopedPixelUnpackState& operator=(const ScopedPixelUnpackState&) = delete;
+
+  ~ScopedPixelUnpackState() = default;
 };
 
 // Commands that are explicitly listed as OK to occur between
@@ -427,6 +432,10 @@
                     SharedImageManager* shared_image_manager,
                     scoped_refptr<SharedContextState> shared_context_state,
                     bool is_privileged);
+
+  RasterDecoderImpl(const RasterDecoderImpl&) = delete;
+  RasterDecoderImpl& operator=(const RasterDecoderImpl&) = delete;
+
   ~RasterDecoderImpl() override;
 
   gles2::GLES2Util* GetGLES2Util() override { return &util_; }
@@ -970,8 +979,6 @@
   gl::GLApi* api_ = nullptr;
 
   base::WeakPtrFactory<DecoderContext> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(RasterDecoderImpl);
 };
 
 constexpr RasterDecoderImpl::CommandInfo RasterDecoderImpl::command_info[] = {
@@ -3400,6 +3407,12 @@
       : raster_decoder_id_(raster_decoder_id), transfer_cache_(transfer_cache) {
     DCHECK(transfer_cache_);
   }
+
+  TransferCacheDeserializeHelperImpl(
+      const TransferCacheDeserializeHelperImpl&) = delete;
+  TransferCacheDeserializeHelperImpl& operator=(
+      const TransferCacheDeserializeHelperImpl&) = delete;
+
   ~TransferCacheDeserializeHelperImpl() override = default;
 
   void CreateLocalEntry(
@@ -3421,8 +3434,6 @@
 
   const int raster_decoder_id_;
   ServiceTransferCache* const transfer_cache_;
-
-  DISALLOW_COPY_AND_ASSIGN(TransferCacheDeserializeHelperImpl);
 };
 
 }  // namespace
diff --git a/gpu/command_buffer/service/raster_decoder.h b/gpu/command_buffer/service/raster_decoder.h
index dbfdd18a..3a958ba9 100644
--- a/gpu/command_buffer/service/raster_decoder.h
+++ b/gpu/command_buffer/service/raster_decoder.h
@@ -46,6 +46,9 @@
       scoped_refptr<SharedContextState> shared_context_state,
       bool is_priviliged);
 
+  RasterDecoder(const RasterDecoder&) = delete;
+  RasterDecoder& operator=(const RasterDecoder&) = delete;
+
   ~RasterDecoder() override;
 
   // DecoderContext implementation.
@@ -103,8 +106,6 @@
   bool debug_ = false;
   bool log_commands_ = false;
   gles2::Outputter* outputter_ = nullptr;
-
-  DISALLOW_COPY_AND_ASSIGN(RasterDecoder);
 };
 
 }  // namespace raster
diff --git a/gpu/command_buffer/service/renderbuffer_manager.h b/gpu/command_buffer/service/renderbuffer_manager.h
index e839ae4..c0140e9 100644
--- a/gpu/command_buffer/service/renderbuffer_manager.h
+++ b/gpu/command_buffer/service/renderbuffer_manager.h
@@ -153,6 +153,10 @@
                       GLint max_renderbuffer_size,
                       GLint max_samples,
                       FeatureInfo* feature_info);
+
+  RenderbufferManager(const RenderbufferManager&) = delete;
+  RenderbufferManager& operator=(const RenderbufferManager&) = delete;
+
   ~RenderbufferManager() override;
 
   GLint max_renderbuffer_size() const {
@@ -228,8 +232,6 @@
   typedef std::unordered_map<GLuint, scoped_refptr<Renderbuffer>>
       RenderbufferMap;
   RenderbufferMap renderbuffers_;
-
-  DISALLOW_COPY_AND_ASSIGN(RenderbufferManager);
 };
 
 }  // namespace gles2
diff --git a/gpu/command_buffer/service/sampler_manager.h b/gpu/command_buffer/service/sampler_manager.h
index 9828eb0..cd39894 100644
--- a/gpu/command_buffer/service/sampler_manager.h
+++ b/gpu/command_buffer/service/sampler_manager.h
@@ -131,6 +131,10 @@
 class GPU_GLES2_EXPORT SamplerManager {
  public:
   SamplerManager(FeatureInfo* feature_info);
+
+  SamplerManager(const SamplerManager&) = delete;
+  SamplerManager& operator=(const SamplerManager&) = delete;
+
   ~SamplerManager();
 
   // Must call before destruction.
@@ -164,8 +168,6 @@
   SamplerMap samplers_;
 
   bool have_context_;
-
-  DISALLOW_COPY_AND_ASSIGN(SamplerManager);
 };
 
 }  // namespace gles2
diff --git a/gpu/command_buffer/service/scheduler.h b/gpu/command_buffer/service/scheduler.h
index de327231..003b49c9 100644
--- a/gpu/command_buffer/service/scheduler.h
+++ b/gpu/command_buffer/service/scheduler.h
@@ -59,6 +59,9 @@
   Scheduler(SyncPointManager* sync_point_manager,
             const GpuPreferences& gpu_preferences);
 
+  Scheduler(const Scheduler&) = delete;
+  Scheduler& operator=(const Scheduler&) = delete;
+
   ~Scheduler();
 
   // Create a sequence with given priority. Returns an identifier for the
@@ -144,6 +147,9 @@
              SchedulingPriority priority,
              scoped_refptr<SyncPointOrderData> order_data);
 
+    Sequence(const Sequence&) = delete;
+    Sequence& operator=(const Sequence&) = delete;
+
     ~Sequence();
 
     SequenceId sequence_id() const { return sequence_id_; }
@@ -342,8 +348,6 @@
                                  1] = {};
 
     base::flat_set<CommandBufferId> client_waits_;
-
-    DISALLOW_COPY_AND_ASSIGN(Sequence);
   };
 
   void SyncTokenFenceReleased(const SyncToken& sync_token,
@@ -397,7 +401,6 @@
   FRIEND_TEST_ALL_PREFIXES(SchedulerTest, StreamDestroyRemovesPriorities);
   FRIEND_TEST_ALL_PREFIXES(SchedulerTest, StreamPriorityChangeWhileReleasing);
   FRIEND_TEST_ALL_PREFIXES(SchedulerTest, CircularPriorities);
-  DISALLOW_COPY_AND_ASSIGN(Scheduler);
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/service_discardable_manager.h b/gpu/command_buffer/service/service_discardable_manager.h
index 876fa527..6eb4220 100644
--- a/gpu/command_buffer/service/service_discardable_manager.h
+++ b/gpu/command_buffer/service/service_discardable_manager.h
@@ -30,6 +30,11 @@
     : public base::trace_event::MemoryDumpProvider {
  public:
   explicit ServiceDiscardableManager(const GpuPreferences& preferences);
+
+  ServiceDiscardableManager(const ServiceDiscardableManager&) = delete;
+  ServiceDiscardableManager& operator=(const ServiceDiscardableManager&) =
+      delete;
+
   ~ServiceDiscardableManager() override;
 
   // base::trace_event::MemoryDumpProvider implementation.
@@ -127,8 +132,6 @@
 
   // The limit above which the cache will start evicting resources.
   size_t cache_size_limit_ = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(ServiceDiscardableManager);
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/service_transfer_cache.h b/gpu/command_buffer/service/service_transfer_cache.h
index 9c5d6f86..c0da2c5 100644
--- a/gpu/command_buffer/service/service_transfer_cache.h
+++ b/gpu/command_buffer/service/service_transfer_cache.h
@@ -50,6 +50,10 @@
   };
 
   explicit ServiceTransferCache(const GpuPreferences& preferences);
+
+  ServiceTransferCache(const ServiceTransferCache&) = delete;
+  ServiceTransferCache& operator=(const ServiceTransferCache&) = delete;
+
   ~ServiceTransferCache() override;
 
   bool CreateLockedEntry(const EntryKey& key,
@@ -143,8 +147,6 @@
 
   // The max number of entries we will hold in the cache.
   size_t max_cache_entries_;
-
-  DISALLOW_COPY_AND_ASSIGN(ServiceTransferCache);
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/shader_manager.h b/gpu/command_buffer/service/shader_manager.h
index 873f92dd..6d8f8a0 100644
--- a/gpu/command_buffer/service/shader_manager.h
+++ b/gpu/command_buffer/service/shader_manager.h
@@ -283,6 +283,10 @@
 class GPU_GLES2_EXPORT ShaderManager {
  public:
   ShaderManager(gl::ProgressReporter* progress_reporter);
+
+  ShaderManager(const ShaderManager&) = delete;
+  ShaderManager& operator=(const ShaderManager&) = delete;
+
   ~ShaderManager();
 
   // Must call before destruction.
@@ -326,12 +330,9 @@
   // preventing time-outs when destruction takes a long time. May be null when
   // using in-process command buffer.
   gl::ProgressReporter* progress_reporter_;
-
-  DISALLOW_COPY_AND_ASSIGN(ShaderManager);
 };
 
 }  // namespace gles2
 }  // namespace gpu
 
 #endif  // GPU_COMMAND_BUFFER_SERVICE_SHADER_MANAGER_H_
-
diff --git a/gpu/command_buffer/service/shader_translator.h b/gpu/command_buffer/service/shader_translator.h
index 745b027..2c16317a1 100644
--- a/gpu/command_buffer/service/shader_translator.h
+++ b/gpu/command_buffer/service/shader_translator.h
@@ -79,12 +79,13 @@
   class DestructionObserver {
    public:
     DestructionObserver();
+
+    DestructionObserver(const DestructionObserver&) = delete;
+    DestructionObserver& operator=(const DestructionObserver&) = delete;
+
     virtual ~DestructionObserver();
 
     virtual void OnDestruct(ShaderTranslator* translator) = 0;
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(DestructionObserver);
   };
 
   ShaderTranslator();
@@ -134,4 +135,3 @@
 }  // namespace gpu
 
 #endif  // GPU_COMMAND_BUFFER_SERVICE_SHADER_TRANSLATOR_H_
-
diff --git a/gpu/command_buffer/service/shader_translator_cache.h b/gpu/command_buffer/service/shader_translator_cache.h
index 5b5a54c..af81c6d9 100644
--- a/gpu/command_buffer/service/shader_translator_cache.h
+++ b/gpu/command_buffer/service/shader_translator_cache.h
@@ -31,6 +31,10 @@
     : public ShaderTranslator::DestructionObserver {
  public:
   explicit ShaderTranslatorCache(const GpuPreferences& gpu_preferences);
+
+  ShaderTranslatorCache(const ShaderTranslatorCache&) = delete;
+  ShaderTranslatorCache& operator=(const ShaderTranslatorCache&) = delete;
+
   ~ShaderTranslatorCache() override;
 
   // ShaderTranslator::DestructionObserver implementation
@@ -89,8 +93,6 @@
 
   typedef std::map<ShaderTranslatorInitParams, ShaderTranslator* > Cache;
   Cache cache_;
-
-  DISALLOW_COPY_AND_ASSIGN(ShaderTranslatorCache);
 };
 
 }  // namespace gles2
diff --git a/gpu/command_buffer/service/shared_image_backing.cc b/gpu/command_buffer/service/shared_image_backing.cc
index a1be683..885745d 100644
--- a/gpu/command_buffer/service/shared_image_backing.cc
+++ b/gpu/command_buffer/service/shared_image_backing.cc
@@ -47,6 +47,10 @@
   have_context_ = false;
 }
 
+bool SharedImageBacking::CopyToGpuMemoryBuffer() {
+  return false;
+}
+
 bool SharedImageBacking::PresentSwapChain() {
   return false;
 }
diff --git a/gpu/command_buffer/service/shared_image_backing.h b/gpu/command_buffer/service/shared_image_backing.h
index b03d38b..7bfaa92 100644
--- a/gpu/command_buffer/service/shared_image_backing.h
+++ b/gpu/command_buffer/service/shared_image_backing.h
@@ -112,6 +112,13 @@
 
   virtual void Update(std::unique_ptr<gfx::GpuFence> in_fence) = 0;
 
+  // Copy from the backing's GPU texture to its GpuMemoryBuffer if present. This
+  // is needed on Windows where the renderer process can only create shared
+  // memory GMBs and an explicit copy is needed. Returns true on success.
+  virtual bool CopyToGpuMemoryBuffer();
+
+  // Present the swap chain corresponding to this backing. Presents only if the
+  // backing is the back buffer of the swap chain. Returns true on success.
   virtual bool PresentSwapChain();
 
   virtual void MarkForDestruction() {}
@@ -217,6 +224,10 @@
   class ScopedWriteUMA {
    public:
     ScopedWriteUMA() = default;
+
+    ScopedWriteUMA(const ScopedWriteUMA&) = delete;
+    ScopedWriteUMA& operator=(const ScopedWriteUMA&) = delete;
+
     ~ScopedWriteUMA() {
       UMA_HISTOGRAM_BOOLEAN("GPU.SharedImage.ContentConsumed",
                             content_consumed_);
@@ -227,7 +238,6 @@
 
    private:
     bool content_consumed_ = false;
-    DISALLOW_COPY_AND_ASSIGN(ScopedWriteUMA);
   };
 
   const Mailbox mailbox_;
diff --git a/gpu/command_buffer/service/shared_image_backing_d3d.cc b/gpu/command_buffer/service/shared_image_backing_d3d.cc
index 0541dc4..dbb2a5e 100644
--- a/gpu/command_buffer/service/shared_image_backing_d3d.cc
+++ b/gpu/command_buffer/service/shared_image_backing_d3d.cc
@@ -4,6 +4,10 @@
 
 #include "gpu/command_buffer/service/shared_image_backing_d3d.h"
 
+#include <d3d11_3.h>
+
+#include "base/bind.h"
+#include "base/callback_helpers.h"
 #include "base/memory/ptr_util.h"
 #include "base/trace_event/memory_dump_manager.h"
 #include "components/viz/common/resources/resource_format_utils.h"
@@ -12,12 +16,16 @@
 #include "gpu/command_buffer/common/shared_image_trace_utils.h"
 #include "gpu/command_buffer/common/shared_image_usage.h"
 #include "gpu/command_buffer/service/shared_image_representation_d3d.h"
+#include "gpu/command_buffer/service/shared_image_representation_skia_gl.h"
+#include "gpu/command_buffer/service/shared_memory_region_wrapper.h"
+#include "ui/gfx/buffer_format_util.h"
+#include "ui/gl/gl_angle_util_win.h"
+#include "ui/gl/gl_image_shared_memory.h"
+#include "ui/gl/trace_util.h"
+
 #if BUILDFLAG(USE_DAWN) && BUILDFLAG(DAWN_ENABLE_BACKEND_OPENGLES)
 #include "gpu/command_buffer/service/shared_image_representation_dawn_egl_image.h"
 #endif
-#include "gpu/command_buffer/service/shared_image_representation_skia_gl.h"
-#include "ui/gfx/buffer_format_util.h"
-#include "ui/gl/trace_util.h"
 
 namespace gpu {
 
@@ -104,13 +112,15 @@
     prev_binding_ = binding;
   }
 
+  ScopedRestoreTexture(const ScopedRestoreTexture&) = delete;
+  ScopedRestoreTexture& operator=(const ScopedRestoreTexture&) = delete;
+
   ~ScopedRestoreTexture() { api_->glBindTextureFn(target_, prev_binding_); }
 
  private:
   gl::GLApi* const api_;
   const GLenum target_;
   GLuint prev_binding_ = 0;
-  DISALLOW_COPY_AND_ASSIGN(ScopedRestoreTexture);
 };
 
 scoped_refptr<gles2::TexturePassthrough> CreateGLTexture(
@@ -129,6 +139,15 @@
   api->glGenTexturesFn(1, &service_id);
   api->glBindTextureFn(texture_target, service_id);
 
+  // These need to be set for the texture to be considered mipmap complete.
+  api->glTexParameteriFn(texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+  api->glTexParameteriFn(texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+  // These are not strictly required but guard against some checks if NPOT
+  // texture support is disabled.
+  api->glTexParameteriFn(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+  api->glTexParameteriFn(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
   // The GL internal format can differ from the underlying swap chain or texture
   // format e.g. RGBA or RGB instead of BGRA or RED/RG for NV12 texture planes.
   // See EGL_ANGLE_d3d_texture_client_buffer spec for format restrictions.
@@ -159,19 +178,18 @@
 
   return texture;
 }
-
-}  // anonymous namespace
+}  // namespace
 
 SharedImageBackingD3D::SharedState::SharedState(
-    base::win::ScopedHandle shared_handle,
+    base::win::ScopedHandle dxgi_shared_handle,
     Microsoft::WRL::ComPtr<IDXGIKeyedMutex> dxgi_keyed_mutex)
-    : shared_handle_(std::move(shared_handle)),
+    : dxgi_shared_handle_(std::move(dxgi_shared_handle)),
       dxgi_keyed_mutex_(std::move(dxgi_keyed_mutex)) {}
 
 SharedImageBackingD3D::SharedState::~SharedState() {
   DCHECK(!acquired_for_d3d12_);
   DCHECK_EQ(acquired_for_d3d11_count_, 0);
-  shared_handle_.Close();
+  dxgi_shared_handle_.Close();
 }
 
 bool SharedImageBackingD3D::SharedState::BeginAccessD3D12() {
@@ -229,8 +247,8 @@
   }
 }
 
-HANDLE SharedImageBackingD3D::SharedState::GetSharedHandle() const {
-  return shared_handle_.Get();
+HANDLE SharedImageBackingD3D::SharedState::GetDXGISharedHandle() const {
+  return dxgi_shared_handle_.Get();
 }
 
 // static
@@ -245,7 +263,7 @@
     uint32_t usage,
     Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11_texture,
     Microsoft::WRL::ComPtr<IDXGISwapChain1> swap_chain,
-    size_t buffer_index) {
+    bool is_back_buffer) {
   auto gl_texture =
       CreateGLTexture(format, size, color_space, d3d11_texture, swap_chain);
   if (!gl_texture) {
@@ -254,8 +272,8 @@
   }
   return base::WrapUnique(new SharedImageBackingD3D(
       mailbox, format, size, color_space, surface_origin, alpha_type, usage,
-      std::move(d3d11_texture), std::move(gl_texture), std::move(swap_chain),
-      buffer_index));
+      std::move(d3d11_texture), std::move(gl_texture), /*shared_state=*/nullptr,
+      /*shared_memory_handle=*/{}, std::move(swap_chain), is_back_buffer));
 }
 
 // static
@@ -269,8 +287,8 @@
     SkAlphaType alpha_type,
     uint32_t usage,
     Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11_texture,
-    base::win::ScopedHandle shared_handle) {
-  DCHECK(shared_handle.IsValid());
+    base::win::ScopedHandle dxgi_shared_handle) {
+  DCHECK(dxgi_shared_handle.IsValid());
 
   const bool has_webgpu_usage = !!(usage & SHARED_IMAGE_USAGE_WEBGPU);
   // Keyed mutexes are required for Dawn interop but are not used for XR
@@ -280,7 +298,7 @@
   DCHECK(!has_webgpu_usage || dxgi_keyed_mutex);
 
   auto shared_state = base::MakeRefCounted<SharedState>(
-      std::move(shared_handle), std::move(dxgi_keyed_mutex));
+      std::move(dxgi_shared_handle), std::move(dxgi_keyed_mutex));
 
   // Do not cache a GL texture in the backing if it could be owned by WebGPU
   // since there's no GL context to MakeCurrent in the destructor.
@@ -294,10 +312,11 @@
       return nullptr;
     }
   }
-  return base::WrapUnique(new SharedImageBackingD3D(
+  auto backing = base::WrapUnique(new SharedImageBackingD3D(
       mailbox, format, size, color_space, surface_origin, alpha_type, usage,
-      std::move(d3d11_texture), std::move(gl_texture), /*swap_chain=*/nullptr,
-      /*buffer_index=*/0, std::move(shared_state)));
+      std::move(d3d11_texture), std::move(gl_texture),
+      std::move(shared_state)));
+  return backing;
 }
 
 std::unique_ptr<SharedImageBackingD3D>
@@ -325,7 +344,7 @@
     uint32_t usage,
     Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11_texture,
     unsigned array_slice,
-    base::win::ScopedHandle shared_handle) {
+    base::win::ScopedHandle dxgi_shared_handle) {
   DCHECK(d3d11_texture);
   DCHECK(SupportsVideoFormat(dxgi_format));
   DCHECK_EQ(mailboxes.size(), NumPlanes(dxgi_format));
@@ -334,11 +353,11 @@
   Microsoft::WRL::ComPtr<IDXGIKeyedMutex> dxgi_keyed_mutex;
   d3d11_texture.As(&dxgi_keyed_mutex);
   DCHECK(!(usage & gpu::SHARED_IMAGE_USAGE_WEBGPU) ||
-         (shared_handle.IsValid() && dxgi_keyed_mutex));
+         (dxgi_shared_handle.IsValid() && dxgi_keyed_mutex));
 
   // Share the same keyed mutex state for all the plane backings.
   auto shared_state = base::MakeRefCounted<SharedState>(
-      std::move(shared_handle), std::move(dxgi_keyed_mutex));
+      std::move(dxgi_shared_handle), std::move(dxgi_keyed_mutex));
 
   std::vector<std::unique_ptr<SharedImageBacking>> shared_images(
       NumPlanes(dxgi_format));
@@ -367,14 +386,38 @@
     shared_images[plane_index] = base::WrapUnique(new SharedImageBackingD3D(
         mailbox, plane_format, plane_size, kInvalidColorSpace,
         kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType, usage, d3d11_texture,
-        std::move(gl_texture), /*swap_chain=*/nullptr, /*buffer_index=*/0,
-        shared_state));
+        std::move(gl_texture), shared_state));
     shared_images[plane_index]->SetCleared();
   }
 
   return shared_images;
 }
 
+// static
+std::unique_ptr<SharedImageBackingD3D>
+SharedImageBackingD3D::CreateFromSharedMemoryHandle(
+    const Mailbox& mailbox,
+    viz::ResourceFormat format,
+    const gfx::Size& size,
+    const gfx::ColorSpace& color_space,
+    GrSurfaceOrigin surface_origin,
+    SkAlphaType alpha_type,
+    uint32_t usage,
+    Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11_texture,
+    gfx::GpuMemoryBufferHandle shared_memory_handle) {
+  DCHECK_EQ(shared_memory_handle.type, gfx::SHARED_MEMORY_BUFFER);
+  auto gl_texture = CreateGLTexture(format, size, color_space, d3d11_texture);
+  if (!gl_texture) {
+    DLOG(ERROR) << "Failed to create GL texture";
+    return nullptr;
+  }
+  auto backing = base::WrapUnique(new SharedImageBackingD3D(
+      mailbox, format, size, color_space, surface_origin, alpha_type, usage,
+      std::move(d3d11_texture), std::move(gl_texture), /*shared_state=*/nullptr,
+      std::move(shared_memory_handle)));
+  return backing;
+}
+
 SharedImageBackingD3D::SharedImageBackingD3D(
     const Mailbox& mailbox,
     viz::ResourceFormat format,
@@ -385,9 +428,10 @@
     uint32_t usage,
     Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11_texture,
     scoped_refptr<gles2::TexturePassthrough> gl_texture,
+    scoped_refptr<SharedState> shared_state,
+    gfx::GpuMemoryBufferHandle shared_memory_handle,
     Microsoft::WRL::ComPtr<IDXGISwapChain1> swap_chain,
-    size_t buffer_index,
-    scoped_refptr<SharedState> shared_state)
+    bool is_back_buffer)
     : ClearTrackingSharedImageBacking(
           mailbox,
           format,
@@ -402,9 +446,10 @@
           false /* is_thread_safe */),
       d3d11_texture_(std::move(d3d11_texture)),
       gl_texture_(std::move(gl_texture)),
+      shared_state_(std::move(shared_state)),
+      shared_memory_handle_(std::move(shared_memory_handle)),
       swap_chain_(std::move(swap_chain)),
-      buffer_index_(buffer_index),
-      shared_state_(std::move(shared_state)) {
+      is_back_buffer_(is_back_buffer) {
   const bool has_webgpu_usage = !!(usage & SHARED_IMAGE_USAGE_WEBGPU);
   DCHECK(has_webgpu_usage || gl_texture_);
 }
@@ -422,9 +467,178 @@
 #endif  // BUILDFLAG(USE_DAWN)
 }
 
+ID3D11Texture2D* SharedImageBackingD3D::GetOrCreateStagingTexture() {
+  if (!staging_texture_) {
+    D3D11_TEXTURE2D_DESC texture_desc;
+    d3d11_texture_->GetDesc(&texture_desc);
+
+    D3D11_TEXTURE2D_DESC staging_desc = {};
+    staging_desc.Width = texture_desc.Width;
+    staging_desc.Height = texture_desc.Height;
+    staging_desc.Format = texture_desc.Format;
+    staging_desc.MipLevels = 1;
+    staging_desc.ArraySize = 1;
+    staging_desc.SampleDesc.Count = 1;
+    staging_desc.Usage = D3D11_USAGE_STAGING;
+    staging_desc.CPUAccessFlags =
+        D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
+
+    Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device =
+        gl::QueryD3D11DeviceObjectFromANGLE();
+    HRESULT hr = d3d11_device->CreateTexture2D(&staging_desc, nullptr,
+                                               &staging_texture_);
+    if (FAILED(hr)) {
+      DLOG(ERROR) << "Failed to create staging texture. hr=" << std::hex << hr;
+      return nullptr;
+    }
+
+    constexpr char kStagingTextureLabel[] = "SharedImageD3D_StagingTexture";
+    // Add debug label to the long lived texture.
+    staging_texture_->SetPrivateData(WKPDID_D3DDebugObjectName,
+                                     strlen(kStagingTextureLabel),
+                                     kStagingTextureLabel);
+  }
+  return staging_texture_.Get();
+}
+
 void SharedImageBackingD3D::Update(std::unique_ptr<gfx::GpuFence> in_fence) {
-  DLOG(ERROR) << "SharedImageBackingD3D::Update : Trying to update "
-                 "Shared Images associated with swap chain.";
+  DCHECK(!in_fence);
+  if (!shared_memory_handle_.is_null())
+    needs_upload_to_gpu_ = true;
+}
+
+bool SharedImageBackingD3D::UploadToGpuIfNeeded() {
+  if (!needs_upload_to_gpu_)
+    return true;
+
+  gpu::SharedMemoryRegionWrapper mapped_shared_memory;
+  mapped_shared_memory.Initialize(shared_memory_handle_, size(), format());
+
+  if (!mapped_shared_memory.IsValid()) {
+    DLOG(ERROR) << "Failed to map shared memory";
+    return false;
+  }
+
+  const uint8_t* source_memory = mapped_shared_memory.GetMemory();
+  const size_t source_stride = mapped_shared_memory.GetStride();
+
+  Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device =
+      gl::QueryD3D11DeviceObjectFromANGLE();
+  Microsoft::WRL::ComPtr<ID3D11DeviceContext> device_context;
+  d3d11_device->GetImmediateContext(&device_context);
+
+  D3D11_TEXTURE2D_DESC texture_desc;
+  DCHECK(d3d11_texture_);
+  d3d11_texture_->GetDesc(&texture_desc);
+
+  if (texture_desc.CPUAccessFlags & D3D11_CPU_ACCESS_WRITE) {
+    Microsoft::WRL::ComPtr<ID3D11Device3> device3;
+    HRESULT hr = d3d11_device.As(&device3);
+    if (FAILED(hr)) {
+      DLOG(ERROR) << "Failed to retrieve ID3D11Device3. hr=" << std::hex << hr;
+      return false;
+    }
+    hr = device_context->Map(d3d11_texture_.Get(), 0, D3D11_MAP_WRITE, 0,
+                             nullptr);
+    if (FAILED(hr)) {
+      DLOG(ERROR) << "Failed to map texture for write. hr = " << std::hex << hr;
+      return false;
+    }
+    device3->WriteToSubresource(d3d11_texture_.Get(), 0, nullptr, source_memory,
+                                source_stride, 0);
+    device_context->Unmap(d3d11_texture_.Get(), 0);
+  } else {
+    ID3D11Texture2D* staging_texture = GetOrCreateStagingTexture();
+    if (!staging_texture)
+      return false;
+    D3D11_MAPPED_SUBRESOURCE mapped_resource = {};
+    HRESULT hr = device_context->Map(staging_texture, 0, D3D11_MAP_WRITE, 0,
+                                     &mapped_resource);
+    if (FAILED(hr)) {
+      DLOG(ERROR) << "Failed to map texture for write. hr=" << std::hex << hr;
+      return false;
+    }
+    uint8_t* dest_memory = static_cast<uint8_t*>(mapped_resource.pData);
+    const size_t dest_stride = mapped_resource.RowPitch;
+    const size_t row_bytes = size().width() * viz::BitsPerPixel(format()) / 8;
+    for (int i = 0; i < size().height(); i++) {
+      memcpy(dest_memory + i * dest_stride, source_memory + i * source_stride,
+             row_bytes);
+    }
+    device_context->Unmap(staging_texture, 0);
+    device_context->CopySubresourceRegion(d3d11_texture_.Get(), 0, 0, 0, 0,
+                                          staging_texture, 0, nullptr);
+  }
+  needs_upload_to_gpu_ = false;
+  return true;
+}
+
+bool SharedImageBackingD3D::CopyToGpuMemoryBuffer() {
+  if (shared_memory_handle_.is_null()) {
+    DLOG(ERROR)
+        << "Called CopyToGpuMemoryBuffer for backing without shared memory GMB";
+    return false;
+  }
+
+  gpu::SharedMemoryRegionWrapper mapped_shared_memory;
+  mapped_shared_memory.Initialize(shared_memory_handle_, size(), format());
+
+  if (!mapped_shared_memory.IsValid()) {
+    DLOG(ERROR) << "Failed to map shared memory";
+    return false;
+  }
+
+  uint8_t* dest_memory = mapped_shared_memory.GetMemory();
+  const size_t dest_stride = mapped_shared_memory.GetStride();
+
+  Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device =
+      gl::QueryD3D11DeviceObjectFromANGLE();
+  Microsoft::WRL::ComPtr<ID3D11DeviceContext> device_context;
+  d3d11_device->GetImmediateContext(&device_context);
+
+  D3D11_TEXTURE2D_DESC texture_desc;
+  DCHECK(d3d11_texture_);
+  d3d11_texture_->GetDesc(&texture_desc);
+
+  if (texture_desc.CPUAccessFlags & D3D11_CPU_ACCESS_READ) {
+    Microsoft::WRL::ComPtr<ID3D11Device3> device3;
+    HRESULT hr = d3d11_device.As(&device3);
+    if (FAILED(hr)) {
+      DLOG(ERROR) << "Failed to retrieve ID3D11Device3. hr=" << std::hex << hr;
+      return false;
+    }
+    hr = device_context->Map(d3d11_texture_.Get(), 0, D3D11_MAP_READ, 0,
+                             nullptr);
+    if (FAILED(hr)) {
+      DLOG(ERROR) << "Failed to map texture for read. hr=" << std::hex << hr;
+      return false;
+    }
+    device3->ReadFromSubresource(dest_memory, dest_stride, 0,
+                                 d3d11_texture_.Get(), 0, nullptr);
+    device_context->Unmap(d3d11_texture_.Get(), 0);
+  } else {
+    ID3D11Texture2D* staging_texture = GetOrCreateStagingTexture();
+    if (!staging_texture)
+      return false;
+    device_context->CopySubresourceRegion(staging_texture, 0, 0, 0, 0,
+                                          d3d11_texture_.Get(), 0, nullptr);
+    D3D11_MAPPED_SUBRESOURCE mapped_resource = {};
+    HRESULT hr = device_context->Map(staging_texture, 0, D3D11_MAP_READ, 0,
+                                     &mapped_resource);
+    if (FAILED(hr)) {
+      DLOG(ERROR) << "Failed to map texture for read. hr=" << std::hex << hr;
+      return false;
+    }
+    const uint8_t* source_memory = static_cast<uint8_t*>(mapped_resource.pData);
+    const size_t source_stride = mapped_resource.RowPitch;
+    const size_t row_bytes = size().width() * viz::BitsPerPixel(format()) / 8;
+    for (int i = 0; i < size().height(); i++) {
+      memcpy(dest_memory + i * dest_stride, source_memory + i * source_stride,
+             row_bytes);
+    }
+    device_context->Unmap(staging_texture, 0);
+  }
+  return true;
 }
 
 bool SharedImageBackingD3D::ProduceLegacyMailbox(
@@ -488,12 +702,14 @@
 
   // Persistently open the shared handle by caching it on this backing.
   if (!external_image_) {
-    DCHECK(base::win::HandleTraits::IsHandleValid(GetSharedHandle()));
+    DCHECK(shared_state_);
+    const HANDLE shared_handle = shared_state_->GetDXGISharedHandle();
+    DCHECK(base::win::HandleTraits::IsHandleValid(shared_handle));
 
     dawn_native::d3d12::ExternalImageDescriptorDXGISharedHandle
         externalImageDesc;
     externalImageDesc.cTextureDescriptor = &texture_descriptor;
-    externalImageDesc.sharedHandle = GetSharedHandle();
+    externalImageDesc.sharedHandle = shared_handle;
 
     external_image_ = dawn_native::d3d12::ExternalImageDXGI::Create(
         device, &externalImageDesc);
@@ -531,23 +747,33 @@
 }
 
 bool SharedImageBackingD3D::BeginAccessD3D12() {
-  return shared_state_->BeginAccessD3D12();
+  if (shared_state_)
+    return shared_state_->BeginAccessD3D12();
+  // D3D12 access is only allowed with shared handle and keyed mutex.
+  return false;
 }
 
 void SharedImageBackingD3D::EndAccessD3D12() {
-  shared_state_->EndAccessD3D12();
+  if (shared_state_)
+    shared_state_->EndAccessD3D12();
 }
 
 bool SharedImageBackingD3D::BeginAccessD3D11() {
-  return shared_state_->BeginAccessD3D11();
+  if (shared_state_)
+    return shared_state_->BeginAccessD3D11();
+  // D3D11 access is allowed without shared handle and keyed mutex.
+  return true;
 }
 
 void SharedImageBackingD3D::EndAccessD3D11() {
-  shared_state_->EndAccessD3D11();
+  if (shared_state_)
+    shared_state_->EndAccessD3D11();
 }
 
-HANDLE SharedImageBackingD3D::GetSharedHandle() const {
-  return shared_state_->GetSharedHandle();
+HANDLE SharedImageBackingD3D::GetDXGISharedHandleForTesting() const {
+  if (shared_state_)
+    return shared_state_->GetDXGISharedHandle();
+  return nullptr;
 }
 
 gl::GLImage* SharedImageBackingD3D::GetGLImage() const {
@@ -556,8 +782,8 @@
 
 bool SharedImageBackingD3D::PresentSwapChain() {
   TRACE_EVENT0("gpu", "SharedImageBackingD3D::PresentSwapChain");
-  if (buffer_index_ != 0) {
-    DLOG(ERROR) << "Swap chain backing does not correspond to back buffer";
+  if (!swap_chain_ || !is_back_buffer_) {
+    DLOG(ERROR) << "Backing does not correspond to back buffer of swap chain";
     return false;
   }
 
@@ -594,6 +820,10 @@
 SharedImageBackingD3D::ProduceGLTexturePassthrough(SharedImageManager* manager,
                                                    MemoryTypeTracker* tracker) {
   TRACE_EVENT0("gpu", "SharedImageBackingD3D::ProduceGLTexturePassthrough");
+  if (!UploadToGpuIfNeeded()) {
+    DLOG(ERROR) << "UploadToGpuIfNeeded failed";
+    return nullptr;
+  }
   // Lazily create a GL texture if it wasn't provided on initialization.
   auto gl_texture = gl_texture_;
   if (!gl_texture) {
@@ -622,8 +852,22 @@
 SharedImageBackingD3D::ProduceOverlay(SharedImageManager* manager,
                                       MemoryTypeTracker* tracker) {
   TRACE_EVENT0("gpu", "SharedImageBackingD3D::ProduceOverlay");
-  return std::make_unique<SharedImageRepresentationOverlayD3D>(manager, this,
-                                                               tracker);
+  // Prefer GLImageMemory for shared memory case so that we don't upload to a
+  // texture if it ends up in an overlay.
+  if (!shared_memory_handle_.is_null()) {
+    auto gl_image = base::MakeRefCounted<gl::GLImageSharedMemory>(size());
+    if (!gl_image->Initialize(
+            shared_memory_handle_.region, shared_memory_handle_.id,
+            viz::BufferFormat(format()), shared_memory_handle_.offset,
+            shared_memory_handle_.stride)) {
+      DLOG(ERROR) << "Failed to initialize GLImageSharedMemory";
+      return nullptr;
+    }
+    return std::make_unique<SharedImageRepresentationOverlayD3D>(
+        manager, this, tracker, std::move(gl_image));
+  }
+  return std::make_unique<SharedImageRepresentationOverlayD3D>(
+      manager, this, tracker, GetGLImage());
 }
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/shared_image_backing_d3d.h b/gpu/command_buffer/service/shared_image_backing_d3d.h
index c5b3719..59c76ba8 100644
--- a/gpu/command_buffer/service/shared_image_backing_d3d.h
+++ b/gpu/command_buffer/service/shared_image_backing_d3d.h
@@ -11,6 +11,7 @@
 #include <wrl/client.h>
 
 #include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
 #include "components/viz/common/resources/resource_format.h"
 #include "gpu/command_buffer/service/mailbox_manager.h"
 #include "gpu/command_buffer/service/memory_tracking.h"
@@ -18,6 +19,7 @@
 #include "gpu/command_buffer/service/shared_image_manager.h"
 #include "gpu/command_buffer/service/shared_image_representation.h"
 #include "gpu/command_buffer/service/texture_manager.h"
+#include "ui/gfx/gpu_memory_buffer.h"
 #include "ui/gl/buildflags.h"
 #include "ui/gl/gl_image_d3d.h"
 
@@ -52,7 +54,7 @@
       uint32_t usage,
       Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11_texture,
       Microsoft::WRL::ComPtr<IDXGISwapChain1> swap_chain,
-      size_t buffer_index);
+      bool is_back_buffer);
 
   static std::unique_ptr<SharedImageBackingD3D> CreateFromSharedHandle(
       const Mailbox& mailbox,
@@ -63,7 +65,7 @@
       SkAlphaType alpha_type,
       uint32_t usage,
       Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11_texture,
-      base::win::ScopedHandle shared_handle);
+      base::win::ScopedHandle dxgi_shared_handle);
 
   // TODO(sunnyps): Remove this after migrating DXVA decoder to EGLImage.
   static std::unique_ptr<SharedImageBackingD3D> CreateFromGLTexture(
@@ -85,14 +87,32 @@
       uint32_t usage,
       Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11_texture,
       unsigned array_slice,
-      base::win::ScopedHandle shared_handle = base::win::ScopedHandle());
+      base::win::ScopedHandle dxgi_shared_handle = base::win::ScopedHandle());
+
+  static std::unique_ptr<SharedImageBackingD3D> CreateFromSharedMemoryHandle(
+      const Mailbox& mailbox,
+      viz::ResourceFormat format,
+      const gfx::Size& size,
+      const gfx::ColorSpace& color_space,
+      GrSurfaceOrigin surface_origin,
+      SkAlphaType alpha_type,
+      uint32_t usage,
+      Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11_texture,
+      gfx::GpuMemoryBufferHandle shared_memory_handle);
+
+  SharedImageBackingD3D(const SharedImageBackingD3D&) = delete;
+  SharedImageBackingD3D& operator=(const SharedImageBackingD3D&) = delete;
 
   ~SharedImageBackingD3D() override;
 
   void Update(std::unique_ptr<gfx::GpuFence> in_fence) override;
 
+  bool CopyToGpuMemoryBuffer() override;
+
   bool ProduceLegacyMailbox(MailboxManager* mailbox_manager) override;
 
+  bool PresentSwapChain() override;
+
   std::unique_ptr<SharedImageRepresentationDawn> ProduceDawn(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker,
@@ -110,10 +130,7 @@
   bool BeginAccessD3D11();
   void EndAccessD3D11();
 
-  HANDLE GetSharedHandle() const;
-  gl::GLImage* GetGLImage() const;
-
-  bool PresentSwapChain() override;
+  HANDLE GetDXGISharedHandleForTesting() const;
 
  protected:
   std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
@@ -133,7 +150,7 @@
   class SharedState : public base::RefCountedThreadSafe<SharedState> {
    public:
     explicit SharedState(
-        base::win::ScopedHandle shared_handle = base::win::ScopedHandle(),
+        base::win::ScopedHandle dxgi_shared_handle,
         Microsoft::WRL::ComPtr<IDXGIKeyedMutex> dxgi_keyed_mutex = nullptr);
 
     bool BeginAccessD3D11();
@@ -142,7 +159,7 @@
     bool BeginAccessD3D12();
     void EndAccessD3D12();
 
-    HANDLE GetSharedHandle() const;
+    HANDLE GetDXGISharedHandle() const;
 
    private:
     friend class base::RefCountedThreadSafe<SharedState>;
@@ -154,7 +171,7 @@
     // keyed mutex. To create the corresponding D3D12 interface, pass the handle
     // stored in |shared_handle_| to ID3D12Device::OpenSharedHandle. Only one
     // component is allowed to read/write to the texture at a time.
-    base::win::ScopedHandle shared_handle_;
+    base::win::ScopedHandle dxgi_shared_handle_;
     Microsoft::WRL::ComPtr<IDXGIKeyedMutex> dxgi_keyed_mutex_;
     bool acquired_for_d3d12_ = false;
     int acquired_for_d3d11_count_ = 0;
@@ -170,24 +187,37 @@
       uint32_t usage,
       Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11_texture,
       scoped_refptr<gles2::TexturePassthrough> gl_texture,
+      scoped_refptr<SharedState> shared_state = nullptr,
+      gfx::GpuMemoryBufferHandle shared_memory_handle = {},
       Microsoft::WRL::ComPtr<IDXGISwapChain1> swap_chain = nullptr,
-      size_t buffer_index = 0,
-      scoped_refptr<SharedState> shared_state =
-          base::MakeRefCounted<SharedState>());
+      bool is_back_buffer = false);
 
   uint32_t GetAllowedDawnUsages() const;
 
+  gl::GLImage* GetGLImage() const;
+
+  ID3D11Texture2D* GetOrCreateStagingTexture();
+
+  bool UploadToGpuIfNeeded();
+
   // Texture could be nullptr if an empty backing is needed for testing.
   Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11_texture_;
 
   // Can be null for backings owned by non-GL producers e.g. WebGPU.
   scoped_refptr<gles2::TexturePassthrough> gl_texture_;
 
+  // Holds DXGI shared handle and the keyed mutex if present.  Can be shared
+  // between plane shared image backings of a multi-plane texture.
+  scoped_refptr<SharedState> shared_state_;
+
+  // Shared memory handle from CreateFromSharedMemoryHandle.
+  gfx::GpuMemoryBufferHandle shared_memory_handle_;
+
+  // Swap chain corresponding to this backing.
   Microsoft::WRL::ComPtr<IDXGISwapChain1> swap_chain_;
 
-  const size_t buffer_index_;
-
-  scoped_refptr<SharedState> shared_state_;
+  // Set if this backing corresponds to the back buffer of |swap_chain_|.
+  const bool is_back_buffer_;
 
   // If external_image_ exists, it means Dawn produced the D3D12 side of the
   // D3D11 texture created by ID3D12Device::OpenSharedHandle.
@@ -195,7 +225,12 @@
   std::unique_ptr<dawn_native::d3d12::ExternalImageDXGI> external_image_;
 #endif  // BUILDFLAG(USE_DAWN)
 
-  DISALLOW_COPY_AND_ASSIGN(SharedImageBackingD3D);
+  // Staging texture used for copy to/from shared memory GMB.
+  Microsoft::WRL::ComPtr<ID3D11Texture2D> staging_texture_;
+
+  // Tracks if we should upload from shared memory GMB to the GPU texture on the
+  // next BeginAccess.
+  bool needs_upload_to_gpu_ = false;
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/shared_image_backing_egl_image.cc b/gpu/command_buffer/service/shared_image_backing_egl_image.cc
index 884f3a8..556868a2 100644
--- a/gpu/command_buffer/service/shared_image_backing_egl_image.cc
+++ b/gpu/command_buffer/service/shared_image_backing_egl_image.cc
@@ -58,6 +58,9 @@
                          scoped_refptr<TextureHolder> texture_holder)
       : backing_(backing), texture_holder_(std::move(texture_holder)) {}
 
+  RepresentationGLShared(const RepresentationGLShared&) = delete;
+  RepresentationGLShared& operator=(const RepresentationGLShared&) = delete;
+
   ~RepresentationGLShared() {
     EndAccess();
     if (!backing_->have_context())
@@ -104,7 +107,6 @@
   SharedImageBackingEglImage* const backing_;
   scoped_refptr<TextureHolder> texture_holder_;
   RepresentationAccessMode mode_ = RepresentationAccessMode::kNone;
-  DISALLOW_COPY_AND_ASSIGN(RepresentationGLShared);
 };
 
 class SharedImageBackingEglImage::RepresentationGLTexture
@@ -117,6 +119,9 @@
       : SharedImageRepresentationGLTexture(manager, backing, tracker),
         shared_(backing, std::move(texture_holder)) {}
 
+  RepresentationGLTexture(const RepresentationGLTexture&) = delete;
+  RepresentationGLTexture& operator=(const RepresentationGLTexture&) = delete;
+
   ~RepresentationGLTexture() override = default;
 
   bool BeginAccess(GLenum mode) override { return shared_.BeginAccess(mode); }
@@ -131,7 +136,6 @@
 
  private:
   RepresentationGLShared shared_;
-  DISALLOW_COPY_AND_ASSIGN(RepresentationGLTexture);
 };
 
 class SharedImageBackingEglImage::RepresentationGLTexturePassthrough
@@ -147,6 +151,11 @@
                                                       tracker),
         shared_(backing, std::move(texture_holder)) {}
 
+  RepresentationGLTexturePassthrough(
+      const RepresentationGLTexturePassthrough&) = delete;
+  RepresentationGLTexturePassthrough& operator=(
+      const RepresentationGLTexturePassthrough&) = delete;
+
   ~RepresentationGLTexturePassthrough() override = default;
 
   bool BeginAccess(GLenum mode) override { return shared_.BeginAccess(mode); }
@@ -164,7 +173,6 @@
 
  private:
   RepresentationGLShared shared_;
-  DISALLOW_COPY_AND_ASSIGN(RepresentationGLTexturePassthrough);
 };
 
 SharedImageBackingEglImage::SharedImageBackingEglImage(
diff --git a/gpu/command_buffer/service/shared_image_backing_egl_image.h b/gpu/command_buffer/service/shared_image_backing_egl_image.h
index d75088eb..2d133d3 100644
--- a/gpu/command_buffer/service/shared_image_backing_egl_image.h
+++ b/gpu/command_buffer/service/shared_image_backing_egl_image.h
@@ -52,6 +52,10 @@
       bool use_passthrough,
       base::span<const uint8_t> pixel_data);
 
+  SharedImageBackingEglImage(const SharedImageBackingEglImage&) = delete;
+  SharedImageBackingEglImage& operator=(const SharedImageBackingEglImage&) =
+      delete;
+
   ~SharedImageBackingEglImage() override;
 
   void Update(std::unique_ptr<gfx::GpuFence> in_fence) override;
@@ -122,8 +126,6 @@
 
   const SharedImageBackingGLCommon::UnpackStateAttribs gl_unpack_attribs_;
   const bool use_passthrough_;
-
-  DISALLOW_COPY_AND_ASSIGN(SharedImageBackingEglImage);
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer.cc b/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer.cc
index 4d6991f7..bb18fcf 100644
--- a/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer.cc
+++ b/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer.cc
@@ -145,6 +145,9 @@
                         bool is_thread_safe,
                         base::ScopedFD initial_upload_fd);
 
+  SharedImageBackingAHB(const SharedImageBackingAHB&) = delete;
+  SharedImageBackingAHB& operator=(const SharedImageBackingAHB&) = delete;
+
   ~SharedImageBackingAHB() override;
 
   void Update(std::unique_ptr<gfx::GpuFence> in_fence) override;
@@ -183,8 +186,6 @@
   // mode.
   gles2::Texture* legacy_texture_ = nullptr;
   scoped_refptr<OverlayImage> overlay_image_ GUARDED_BY(lock_);
-
-  DISALLOW_COPY_AND_ASSIGN(SharedImageBackingAHB);
 };
 
 // Vk backed Skia representation of SharedImageBackingAHB.
diff --git a/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer.h b/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer.h
index d90fa27d..1c0ece3 100644
--- a/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer.h
+++ b/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer.h
@@ -29,6 +29,11 @@
  public:
   SharedImageBackingFactoryAHB(const GpuDriverBugWorkarounds& workarounds,
                                const GpuFeatureInfo& gpu_feature_info);
+
+  SharedImageBackingFactoryAHB(const SharedImageBackingFactoryAHB&) = delete;
+  SharedImageBackingFactoryAHB& operator=(const SharedImageBackingFactoryAHB&) =
+      delete;
+
   ~SharedImageBackingFactoryAHB() override;
 
   // SharedImageBackingFactory implementation.
@@ -111,8 +116,6 @@
 
   // Used to limit the max size of AHardwareBuffer.
   int32_t max_gl_texture_size_ = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(SharedImageBackingFactoryAHB);
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/shared_image_backing_factory_d3d.cc b/gpu/command_buffer/service/shared_image_backing_factory_d3d.cc
index ccf380a1..31ab652 100644
--- a/gpu/command_buffer/service/shared_image_backing_factory_d3d.cc
+++ b/gpu/command_buffer/service/shared_image_backing_factory_d3d.cc
@@ -6,6 +6,7 @@
 
 #include <d3d11_1.h>
 
+#include "base/memory/shared_memory_mapping.h"
 #include "components/viz/common/resources/resource_format_utils.h"
 #include "gpu/command_buffer/common/shared_image_usage.h"
 #include "gpu/command_buffer/service/shared_image_backing_d3d.h"
@@ -57,6 +58,10 @@
       return DXGI_FORMAT_B8G8R8A8_UNORM;
     case viz::RGBA_8888:
       return DXGI_FORMAT_R8G8B8A8_UNORM;
+    case viz::RED_8:
+      return DXGI_FORMAT_R8_UNORM;
+    case viz::RG_88:
+      return DXGI_FORMAT_R8G8_UNORM;
     default:
       NOTREACHED();
       return {};
@@ -264,7 +269,7 @@
   auto back_buffer_backing = SharedImageBackingD3D::CreateFromSwapChainBuffer(
       back_buffer_mailbox, format, size, color_space, surface_origin,
       alpha_type, usage, std::move(back_buffer_texture), swap_chain,
-      /*buffer_index=*/0);
+      /*is_back_buffer=*/true);
   if (!back_buffer_backing)
     return {nullptr, nullptr};
   back_buffer_backing->SetCleared();
@@ -278,7 +283,7 @@
   auto front_buffer_backing = SharedImageBackingD3D::CreateFromSwapChainBuffer(
       front_buffer_mailbox, format, size, color_space, surface_origin,
       alpha_type, usage, std::move(front_buffer_texture), swap_chain,
-      /*buffer_index=*/1);
+      /*is_back_buffer=*/false);
   if (!front_buffer_backing)
     return {nullptr, nullptr};
   front_buffer_backing->SetCleared();
@@ -390,27 +395,89 @@
     GrSurfaceOrigin surface_origin,
     SkAlphaType alpha_type,
     uint32_t usage) {
-  // TODO: Add support for shared memory GMBs.
-  if (!GetSupportedRGBAFormat(viz::GetResourceFormat(format))) {
-    DLOG(ERROR) << "Unsupported format " << gfx::BufferFormatToString(format);
-    return nullptr;
+  if (handle.type == gfx::DXGI_SHARED_HANDLE) {
+    if (!GetSupportedRGBAFormat(viz::GetResourceFormat(format))) {
+      DLOG(ERROR) << "Unsupported format " << gfx::BufferFormatToString(format);
+      return nullptr;
+    }
+
+    if (plane != gfx::BufferPlane::DEFAULT) {
+      DLOG(ERROR) << "Invalid plane " << gfx::BufferPlaneToString(plane);
+      return nullptr;
+    }
+
+    auto d3d11_texture =
+        ValidateAndOpenSharedHandle(d3d11_device_, handle, format, size);
+    if (!d3d11_texture)
+      return nullptr;
+
+    auto backing = SharedImageBackingD3D::CreateFromSharedHandle(
+        mailbox, viz::GetResourceFormat(format), size, color_space,
+        surface_origin, alpha_type, usage, std::move(d3d11_texture),
+        std::move(handle.dxgi_handle));
+    if (backing)
+      backing->SetCleared();
+    return backing;
   }
-  if (plane != gfx::BufferPlane::DEFAULT) {
-    DLOG(ERROR) << "Invalid plane " << gfx::BufferPlaneToString(plane);
+
+  DCHECK_EQ(handle.type, gfx::SHARED_MEMORY_BUFFER);
+  switch (plane) {
+    case gfx::BufferPlane::DEFAULT:
+    case gfx::BufferPlane::Y:
+    case gfx::BufferPlane::UV:
+      break;
+    default:
+      DLOG(ERROR) << "Invalid plane " << gfx::BufferPlaneToString(plane);
+      return nullptr;
+  }
+
+  const gfx::Size plane_size = GetPlaneSize(plane, size);
+  const viz::ResourceFormat plane_format =
+      viz::GetResourceFormat(GetPlaneBufferFormat(plane, format));
+
+  absl::optional<DXGI_FORMAT> dxgi_format =
+      GetSupportedRGBAFormat(plane_format);
+  if (!dxgi_format.has_value()) {
+    DLOG(ERROR) << "Invalid format " << gfx::BufferFormatToString(format);
     return nullptr;
   }
 
-  auto d3d11_texture =
-      ValidateAndOpenSharedHandle(d3d11_device_, handle, format, size);
-  if (!d3d11_texture)
-    return nullptr;
+  D3D11_TEXTURE2D_DESC desc;
+  desc.Width = plane_size.width();
+  desc.Height = plane_size.height();
+  desc.MipLevels = 1;
+  desc.ArraySize = 1;
+  desc.Format = dxgi_format.value();
+  desc.SampleDesc.Count = 1;
+  desc.SampleDesc.Quality = 0;
+  desc.Usage = D3D11_USAGE_DEFAULT;
+  desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
+  desc.CPUAccessFlags = UseMapOnDefaultTextures()
+                            ? (D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE)
+                            : 0;
+  desc.MiscFlags = 0;
 
-  auto backing = SharedImageBackingD3D::CreateFromSharedHandle(
-      mailbox, viz::GetResourceFormat(format), size, color_space,
-      surface_origin, alpha_type, usage, std::move(d3d11_texture),
-      std::move(handle.dxgi_handle));
-  if (backing)
+  Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11_texture;
+  HRESULT hr = d3d11_device_->CreateTexture2D(&desc, nullptr, &d3d11_texture);
+  if (FAILED(hr)) {
+    DLOG(ERROR) << "CreateTexture2D failed. hr = " << std::hex << hr;
+    return nullptr;
+  }
+
+  // Adjust offset to include plane offset.
+  const size_t plane_index = plane == gfx::BufferPlane::UV ? 1 : 0;
+  handle.offset += gfx::BufferOffsetForBufferFormat(size, format, plane_index);
+
+  auto backing = SharedImageBackingD3D::CreateFromSharedMemoryHandle(
+      mailbox, plane_format, plane_size, color_space, surface_origin,
+      alpha_type, usage, std::move(d3d11_texture), std::move(handle));
+  if (backing) {
+    // This marks the needs_upload_to_gpu_ flag to defer uploading the GMB which
+    // is unnecessary for the GPU write CPU read e.g. two copy canvas capture,
+    // but is needed for CPU write GPU read e.g. software video decoder.
+    backing->Update(/*in_fence=*/nullptr);
     backing->SetCleared();
+  }
   return backing;
 }
 
@@ -437,11 +504,33 @@
       /*array_slice=*/0, std::move(handle.dxgi_handle));
 }
 
+bool SharedImageBackingFactoryD3D::UseMapOnDefaultTextures() {
+  if (!map_on_default_textures_.has_value()) {
+    D3D11_FEATURE_DATA_D3D11_OPTIONS2 features;
+    HRESULT hr = d3d11_device_->CheckFeatureSupport(
+        D3D11_FEATURE_D3D11_OPTIONS2, &features,
+        sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS2));
+    if (SUCCEEDED(hr)) {
+      map_on_default_textures_.emplace(features.MapOnDefaultTextures);
+    } else {
+      DLOG(ERROR) << "Failed to retrieve D3D11_FEATURE_D3D11_OPTIONS2. hr = "
+                  << std::hex << hr;
+      map_on_default_textures_.emplace(false);
+    }
+  }
+  return map_on_default_textures_.value();
+}
+
 // Returns true if the specified GpuMemoryBufferType can be imported using
 // this factory.
 bool SharedImageBackingFactoryD3D::CanImportGpuMemoryBuffer(
-    gfx::GpuMemoryBufferType memory_buffer_type) {
-  return (memory_buffer_type == gfx::DXGI_SHARED_HANDLE);
+    gfx::GpuMemoryBufferType gmb_type,
+    viz::ResourceFormat format) {
+  return gmb_type == gfx::DXGI_SHARED_HANDLE ||
+         // Only allow single NV12 shared memory GMBs for now. This excludes
+         // dual shared memory GMBs used by software video decoder.
+         (gmb_type == gfx::SHARED_MEMORY_BUFFER &&
+          format == viz::YUV_420_BIPLANAR);
 }
 
 bool SharedImageBackingFactoryD3D::IsSupported(
@@ -455,7 +544,8 @@
   if (is_pixel_used) {
     return false;
   }
-  if (gmb_type != gfx::EMPTY_BUFFER && !CanImportGpuMemoryBuffer(gmb_type)) {
+  if (gmb_type != gfx::EMPTY_BUFFER &&
+      !CanImportGpuMemoryBuffer(gmb_type, format)) {
     return false;
   }
   // TODO(crbug.com/969114): Not all shared image factory implementations
diff --git a/gpu/command_buffer/service/shared_image_backing_factory_d3d.h b/gpu/command_buffer/service/shared_image_backing_factory_d3d.h
index abc82e4..bccd34e 100644
--- a/gpu/command_buffer/service/shared_image_backing_factory_d3d.h
+++ b/gpu/command_buffer/service/shared_image_backing_factory_d3d.h
@@ -16,6 +16,7 @@
 #include "components/viz/common/resources/resource_format.h"
 #include "gpu/command_buffer/service/shared_image_backing_factory.h"
 #include "gpu/gpu_gles2_export.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace gfx {
 class Size;
@@ -30,6 +31,11 @@
     : public SharedImageBackingFactory {
  public:
   SharedImageBackingFactoryD3D();
+
+  SharedImageBackingFactoryD3D(const SharedImageBackingFactoryD3D&) = delete;
+  SharedImageBackingFactoryD3D& operator=(const SharedImageBackingFactoryD3D&) =
+      delete;
+
   ~SharedImageBackingFactoryD3D() override;
 
   // Returns true if DXGI swap chain shared images for overlays are supported.
@@ -38,15 +44,16 @@
   struct GPU_GLES2_EXPORT SwapChainBackings {
     SwapChainBackings(std::unique_ptr<SharedImageBacking> front_buffer,
                       std::unique_ptr<SharedImageBacking> back_buffer);
+
+    SwapChainBackings(const SwapChainBackings&) = delete;
+    SwapChainBackings& operator=(const SwapChainBackings&) = delete;
+
     ~SwapChainBackings();
     SwapChainBackings(SwapChainBackings&&);
     SwapChainBackings& operator=(SwapChainBackings&&);
 
     std::unique_ptr<SharedImageBacking> front_buffer;
     std::unique_ptr<SharedImageBacking> back_buffer;
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(SwapChainBackings);
   };
 
   // Creates IDXGI Swap Chain and exposes front and back buffers as Shared Image
@@ -108,15 +115,18 @@
 
   // Returns true if the specified GpuMemoryBufferType can be imported using
   // this factory.
-  bool CanImportGpuMemoryBuffer(gfx::GpuMemoryBufferType memory_buffer_type);
+  bool CanImportGpuMemoryBuffer(gfx::GpuMemoryBufferType memory_buffer_type,
+                                viz::ResourceFormat format);
 
   Microsoft::WRL::ComPtr<ID3D11Device> GetDeviceForTesting() const {
     return d3d11_device_;
   }
 
  private:
+  bool UseMapOnDefaultTextures();
+
   Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device_;
-  DISALLOW_COPY_AND_ASSIGN(SharedImageBackingFactoryD3D);
+  absl::optional<bool> map_on_default_textures_;
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/shared_image_backing_factory_d3d_unittest.cc b/gpu/command_buffer/service/shared_image_backing_factory_d3d_unittest.cc
index bf7669f0..6ba72818f 100644
--- a/gpu/command_buffer/service/shared_image_backing_factory_d3d_unittest.cc
+++ b/gpu/command_buffer/service/shared_image_backing_factory_d3d_unittest.cc
@@ -8,6 +8,9 @@
 #include <utility>
 
 #include "base/callback_helpers.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/memory/unsafe_shared_memory_region.h"
+#include "components/viz/common/resources/resource_format_utils.h"
 #include "gpu/command_buffer/common/shared_image_usage.h"
 #include "gpu/command_buffer/service/service_utils.h"
 #include "gpu/command_buffer/service/shared_context_state.h"
@@ -20,10 +23,14 @@
 #include "third_party/skia/include/core/SkImage.h"
 #include "third_party/skia/include/core/SkPromiseImageTexture.h"
 #include "third_party/skia/include/core/SkSurface.h"
+#include "ui/gfx/buffer_format_util.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/gpu_memory_buffer.h"
 #include "ui/gl/buildflags.h"
 #include "ui/gl/gl_angle_util_win.h"
 #include "ui/gl/gl_context.h"
 #include "ui/gl/gl_image_d3d.h"
+#include "ui/gl/gl_image_memory.h"
 #include "ui/gl/gl_surface.h"
 #include "ui/gl/init/gl_factory.h"
 
@@ -61,6 +68,41 @@
     "  gl_FragColor = texture2D(u_texture, v_texCoord);"
     "}\n";
 
+void FillYUV(uint8_t* data,
+             const gfx::Size& size,
+             uint8_t y_fill_value,
+             uint8_t u_fill_value,
+             uint8_t v_fill_value) {
+  const size_t kYPlaneSize = size.width() * size.height();
+  memset(data, y_fill_value, kYPlaneSize);
+  uint8_t* uv_data = data + kYPlaneSize;
+  const size_t kUVPlaneSize = kYPlaneSize / 2;
+  for (size_t i = 0; i < kUVPlaneSize; i += 2) {
+    uv_data[i] = u_fill_value;
+    uv_data[i + 1] = v_fill_value;
+  }
+}
+
+void CheckYUV(const uint8_t* data,
+              size_t stride,
+              const gfx::Size& size,
+              uint8_t y_fill_value,
+              uint8_t u_fill_value,
+              uint8_t v_fill_value) {
+  const size_t kYPlaneSize = stride * size.height();
+  const uint8_t* uv_data = data + kYPlaneSize;
+  for (int i = 0; i < size.height(); i++) {
+    for (int j = 0; j < size.width(); j++) {
+      // ASSERT instead of EXPECT to exit on first failure to avoid log spam.
+      ASSERT_EQ(*(data + i * stride + j), y_fill_value);
+      if (i < size.height() / 2) {
+        const uint8_t uv_value = (j % 2 == 0) ? u_fill_value : v_fill_value;
+        ASSERT_EQ(*(uv_data + i * stride + j), uv_value);
+      }
+    }
+  }
+}
+
 GLuint MakeTextureAndSetParameters(gl::GLApi* api, GLenum target, bool fbo) {
   GLuint texture_id = 0;
   api->glGenTexturesFn(1, &texture_id);
@@ -362,7 +404,8 @@
     GLint vertex_location = api->glGetAttribLocationFn(program, "a_position");
     ASSERT_NE(vertex_location, -1);
     api->glEnableVertexAttribArrayFn(vertex_location);
-    api->glVertexAttribPointerFn(vertex_location, 2, GL_FLOAT, GL_FALSE, 0, 0);
+    api->glVertexAttribPointerFn(vertex_location, 2, GL_FLOAT, GL_FALSE, 0,
+                                 nullptr);
 
     GLint sampler_location = api->glGetUniformLocationFn(program, "u_texture");
     ASSERT_NE(sampler_location, -1);
@@ -463,9 +506,9 @@
 
   std::vector<std::unique_ptr<SharedImageRepresentationFactoryRef>>
   CreateVideoImages(const gfx::Size& size,
-                    unsigned char y_fill_value,
-                    unsigned char u_fill_value,
-                    unsigned char v_fill_value,
+                    uint8_t y_fill_value,
+                    uint8_t u_fill_value,
+                    uint8_t v_fill_value,
                     bool use_shared_handle,
                     bool use_factory);
   void RunVideoTest(bool use_shared_handle, bool use_factory);
@@ -889,8 +932,8 @@
   if (!IsD3DSharedImageSupported())
     return;
 
-  EXPECT_TRUE(
-      shared_image_factory_->CanImportGpuMemoryBuffer(gfx::DXGI_SHARED_HANDLE));
+  EXPECT_TRUE(shared_image_factory_->CanImportGpuMemoryBuffer(
+      gfx::DXGI_SHARED_HANDLE, viz::RGBA_8888));
 
   Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device =
       shared_image_factory_->GetDeviceForTesting();
@@ -950,7 +993,7 @@
 
   SharedImageBackingD3D* backing_d3d =
       static_cast<SharedImageBackingD3D*>(backing.get());
-  EXPECT_EQ(backing_d3d->GetSharedHandle(), shared_handle);
+  EXPECT_EQ(backing_d3d->GetDXGISharedHandleForTesting(), shared_handle);
 }
 
 TEST_F(SharedImageBackingFactoryD3DTest,
@@ -1167,9 +1210,9 @@
 
 std::vector<std::unique_ptr<SharedImageRepresentationFactoryRef>>
 SharedImageBackingFactoryD3DTest::CreateVideoImages(const gfx::Size& size,
-                                                    unsigned char y_fill_value,
-                                                    unsigned char u_fill_value,
-                                                    unsigned char v_fill_value,
+                                                    uint8_t y_fill_value,
+                                                    uint8_t u_fill_value,
+                                                    uint8_t v_fill_value,
                                                     bool use_shared_handle,
                                                     bool use_factory) {
   DCHECK(IsD3DSharedImageSupported());
@@ -1177,15 +1220,10 @@
   Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device =
       shared_image_factory_->GetDeviceForTesting();
 
-  const size_t kYPlaneSize = size.width() * size.height();
+  const size_t kDataSize = size.width() * size.height() * 3 / 2;
 
-  std::vector<unsigned char> video_data;
-  video_data.resize(kYPlaneSize * 3 / 2);
-  memset(video_data.data(), y_fill_value, kYPlaneSize);
-  for (size_t i = 0; i < kYPlaneSize / 2; i += 2) {
-    video_data[kYPlaneSize + i] = u_fill_value;
-    video_data[kYPlaneSize + i + 1] = v_fill_value;
-  }
+  std::vector<uint8_t> video_data(kDataSize);
+  FillYUV(video_data.data(), size, y_fill_value, u_fill_value, v_fill_value);
 
   D3D11_SUBRESOURCE_DATA data = {};
   data.pSysMem = static_cast<const void*>(video_data.data());
@@ -1227,9 +1265,10 @@
     usage |= gpu::SHARED_IMAGE_USAGE_WEBGPU;
   }
 
-  const gpu::Mailbox mailboxes[] = {gpu::Mailbox::GenerateForSharedImage(),
-                                    gpu::Mailbox::GenerateForSharedImage()};
-
+  const size_t kNumPlanes = 2;
+  const gpu::Mailbox mailboxes[kNumPlanes] = {
+      gpu::Mailbox::GenerateForSharedImage(),
+      gpu::Mailbox::GenerateForSharedImage()};
   std::vector<std::unique_ptr<SharedImageBacking>> shared_image_backings;
   if (use_factory) {
     gfx::GpuMemoryBufferHandle gmb_handle;
@@ -1243,15 +1282,17 @@
         mailboxes, DXGI_FORMAT_NV12, size, usage, d3d11_texture,
         /*array_slice=*/0, std::move(shared_handle));
   }
-  EXPECT_EQ(shared_image_backings.size(), 2u);
+  EXPECT_EQ(shared_image_backings.size(), kNumPlanes);
 
-  const gfx::Size plane_sizes[] = {
+  const gfx::Size plane_sizes[kNumPlanes] = {
       size, gfx::Size(size.width() / 2, size.height() / 2)};
-  const viz::ResourceFormat plane_formats[] = {viz::RED_8, viz::RG_88};
+  const viz::ResourceFormat plane_formats[kNumPlanes] = {viz::RED_8,
+                                                         viz::RG_88};
 
   std::vector<std::unique_ptr<SharedImageRepresentationFactoryRef>>
       shared_image_refs;
-  for (size_t i = 0; i < shared_image_backings.size(); i++) {
+  for (size_t i = 0; i < std::min(shared_image_backings.size(), kNumPlanes);
+       i++) {
     auto& backing = shared_image_backings[i];
 
     EXPECT_EQ(backing->mailbox(), mailboxes[i]);
@@ -1277,9 +1318,9 @@
 
   const gfx::Size size(32, 32);
 
-  const unsigned char kYFillValue = 0x12;
-  const unsigned char kUFillValue = 0x23;
-  const unsigned char kVFillValue = 0x34;
+  const uint8_t kYFillValue = 0x12;
+  const uint8_t kUFillValue = 0x23;
+  const uint8_t kVFillValue = 0x34;
 
   auto shared_image_refs =
       CreateVideoImages(size, kYFillValue, kUFillValue, kVFillValue,
@@ -1411,7 +1452,8 @@
     api->glUseProgramFn(program);
 
     api->glEnableVertexAttribArrayFn(vertex_location);
-    api->glVertexAttribPointerFn(vertex_location, 2, GL_FLOAT, GL_FALSE, 0, 0);
+    api->glVertexAttribPointerFn(vertex_location, 2, GL_FLOAT, GL_FALSE, 0,
+                                 nullptr);
 
     api->glUniform1iFn(y_texture_location, 0);
     api->glUniform1iFn(uv_texture_location, 1);
@@ -1425,7 +1467,7 @@
     EXPECT_EQ(kYFillValue, pixel_color[0]);
     EXPECT_EQ(kUFillValue, pixel_color[1]);
     EXPECT_EQ(kVFillValue, pixel_color[2]);
-    EXPECT_EQ(0xff, pixel_color[3]);
+    EXPECT_EQ(255, pixel_color[3]);
   }
   // TODO(dawn:551): Test Dawn access after multi-planar support lands in Dawn.
 }
@@ -1447,11 +1489,11 @@
   if (!IsD3DSharedImageSupported())
     return;
 
-  const gfx::Size size(32, 32);
+  constexpr gfx::Size size(32, 32);
 
-  const unsigned char kYFillValue = 0x12;
-  const unsigned char kUFillValue = 0x23;
-  const unsigned char kVFillValue = 0x34;
+  constexpr uint8_t kYFillValue = 0x12;
+  constexpr uint8_t kUFillValue = 0x23;
+  constexpr uint8_t kVFillValue = 0x34;
 
   auto shared_image_refs =
       CreateVideoImages(size, kYFillValue, kUFillValue, kVFillValue,
@@ -1492,19 +1534,9 @@
                            &mapped_resource);
   ASSERT_EQ(hr, S_OK);
 
-  const unsigned char* pixels =
-      static_cast<const unsigned char*>(mapped_resource.pData);
-  const size_t stride = mapped_resource.RowPitch;
-  const size_t kYPlaneSize = stride * size.height();
-  for (size_t i = 0; i < size.height(); i++) {
-    for (size_t j = 0; j < size.width(); j++) {
-      EXPECT_EQ(*(pixels + i * stride + j), kYFillValue);
-      if (i < size.height() / 2 && j % 2 == 0) {
-        EXPECT_EQ(*(pixels + kYPlaneSize + i * stride + j), kUFillValue);
-        EXPECT_EQ(*(pixels + kYPlaneSize + i * stride + j + 1), kVFillValue);
-      }
-    }
-  }
+  CheckYUV(static_cast<const uint8_t*>(mapped_resource.pData),
+           mapped_resource.RowPitch, size, kYFillValue, kUFillValue,
+           kVFillValue);
 
   device_context->Unmap(staging_texture.Get(), 0);
 }
@@ -1522,5 +1554,170 @@
   RunOverlayTest(/*use_shared_handle=*/true, /*use_factory=*/true);
 }
 
+TEST_F(SharedImageBackingFactoryD3DTest, CreateFromSharedMemory) {
+  if (!IsD3DSharedImageSupported())
+    return;
+
+  constexpr gfx::Size size(32, 32);
+  constexpr size_t kDataSize = size.width() * size.height() * 3 / 2;
+
+  base::UnsafeSharedMemoryRegion shm_region =
+      base::UnsafeSharedMemoryRegion::Create(kDataSize);
+  {
+    base::WritableSharedMemoryMapping shm_mapping = shm_region.Map();
+    FillYUV(shm_mapping.GetMemoryAs<uint8_t>(), size, 255, 255, 255);
+  }
+
+  constexpr size_t kNumPlanes = 2;
+  const gpu::Mailbox mailboxes[kNumPlanes] = {
+      gpu::Mailbox::GenerateForSharedImage(),
+      gpu::Mailbox::GenerateForSharedImage()};
+  const gfx::BufferPlane planes[kNumPlanes] = {gfx::BufferPlane::Y,
+                                               gfx::BufferPlane::UV};
+  constexpr uint32_t usage =
+      gpu::SHARED_IMAGE_USAGE_VIDEO_DECODE | gpu::SHARED_IMAGE_USAGE_GLES2 |
+      gpu::SHARED_IMAGE_USAGE_RASTER | gpu::SHARED_IMAGE_USAGE_DISPLAY |
+      gpu::SHARED_IMAGE_USAGE_SCANOUT;
+  std::vector<std::unique_ptr<SharedImageBacking>> shared_image_backings;
+  for (size_t i = 0; i < kNumPlanes; i++) {
+    gfx::GpuMemoryBufferHandle shm_gmb_handle;
+    shm_gmb_handle.type = gfx::SHARED_MEMORY_BUFFER;
+    shm_gmb_handle.region = shm_region.Duplicate();
+    DCHECK(shm_gmb_handle.region.IsValid());
+    shm_gmb_handle.stride = size.width();
+
+    auto backing = shared_image_factory_->CreateSharedImage(
+        mailboxes[i], /*client_id=*/0, std::move(shm_gmb_handle),
+        gfx::BufferFormat::YUV_420_BIPLANAR, planes[i], kNullSurfaceHandle,
+        size, gfx::ColorSpace(), kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType,
+        usage);
+    EXPECT_NE(backing, nullptr);
+
+    shared_image_backings.push_back(std::move(backing));
+  }
+  EXPECT_EQ(shared_image_backings.size(), kNumPlanes);
+
+  const gfx::Size plane_sizes[kNumPlanes] = {
+      size, gfx::Size(size.width() / 2, size.height() / 2)};
+  const viz::ResourceFormat plane_formats[kNumPlanes] = {viz::RED_8,
+                                                         viz::RG_88};
+
+  std::vector<std::unique_ptr<SharedImageRepresentationFactoryRef>>
+      shared_image_refs;
+  for (size_t i = 0; i < shared_image_backings.size(); i++) {
+    auto& backing = shared_image_backings[i];
+
+    EXPECT_EQ(backing->mailbox(), mailboxes[i]);
+    EXPECT_EQ(backing->size(), plane_sizes[i]);
+    EXPECT_EQ(backing->format(), plane_formats[i]);
+    EXPECT_EQ(backing->color_space(), gfx::ColorSpace());
+    EXPECT_EQ(backing->surface_origin(), kTopLeft_GrSurfaceOrigin);
+    EXPECT_EQ(backing->alpha_type(), kPremul_SkAlphaType);
+    EXPECT_EQ(backing->usage(), usage);
+    EXPECT_TRUE(backing->IsCleared());
+
+    shared_image_refs.push_back(shared_image_manager_.Register(
+        std::move(backing), memory_type_tracker_.get()));
+  }
+  ASSERT_EQ(shared_image_refs.size(), 2u);
+
+  constexpr uint8_t kYClearValue = 0x12;
+  constexpr uint8_t kUClearValue = 0x23;
+  constexpr uint8_t kVClearValue = 0x34;
+
+  gl::GLApi* api = gl::g_current_gl_context;
+
+  GLuint fbo;
+  api->glGenFramebuffersEXTFn(1, &fbo);
+  ASSERT_NE(fbo, 0u);
+  SCOPED_GL_CLEANUP_PTR(api, DeleteFramebuffersEXT, 1, fbo);
+  api->glBindFramebufferEXTFn(GL_FRAMEBUFFER, fbo);
+
+  auto y_texture =
+      shared_image_representation_factory_->ProduceGLTexturePassthrough(
+          shared_image_refs[0]->mailbox());
+  ASSERT_NE(y_texture, nullptr);
+
+  GLuint y_texture_id = y_texture->GetTextureBase()->service_id();
+  api->glBindTextureFn(GL_TEXTURE_2D, y_texture_id);
+  api->glFramebufferTexture2DEXTFn(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+                                   GL_TEXTURE_2D, y_texture_id, 0);
+  ASSERT_EQ(api->glCheckFramebufferStatusEXTFn(GL_FRAMEBUFFER),
+            static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE));
+  ASSERT_EQ(api->glGetErrorFn(), static_cast<GLenum>(GL_NO_ERROR));
+
+  GLubyte y_value;
+  api->glReadPixelsFn(size.width() / 2, size.height() / 2, 1, 1, GL_RED,
+                      GL_UNSIGNED_BYTE, &y_value);
+  EXPECT_EQ(255, y_value);
+
+  api->glViewportFn(0, 0, size.width(), size.height());
+  api->glClearColorFn(kYClearValue / 255.0f, 0, 0, 0);
+  api->glClearFn(GL_COLOR_BUFFER_BIT);
+
+  api->glReadPixelsFn(size.width() / 2, size.height() / 2, 1, 1, GL_RED,
+                      GL_UNSIGNED_BYTE, &y_value);
+  EXPECT_EQ(kYClearValue, y_value);
+
+  y_texture.reset();
+  EXPECT_TRUE(shared_image_refs[0]->CopyToGpuMemoryBuffer());
+
+  auto uv_texture =
+      shared_image_representation_factory_->ProduceGLTexturePassthrough(
+          shared_image_refs[1]->mailbox());
+  ASSERT_NE(uv_texture, nullptr);
+
+  GLuint uv_texture_id = uv_texture->GetTextureBase()->service_id();
+  api->glBindTextureFn(GL_TEXTURE_2D, uv_texture_id);
+  api->glFramebufferTexture2DEXTFn(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+                                   GL_TEXTURE_2D, uv_texture_id, 0);
+  ASSERT_EQ(api->glCheckFramebufferStatusEXTFn(GL_FRAMEBUFFER),
+            static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE));
+  ASSERT_EQ(api->glGetErrorFn(), static_cast<GLenum>(GL_NO_ERROR));
+
+  GLubyte uv_value[2];
+  api->glReadPixelsFn(size.width() / 4, size.height() / 4, 1, 1, GL_RG,
+                      GL_UNSIGNED_BYTE, uv_value);
+  EXPECT_EQ(255, uv_value[0]);
+  EXPECT_EQ(255, uv_value[1]);
+
+  api->glViewportFn(0, 0, size.width(), size.height());
+  api->glClearColorFn(kUClearValue / 255.0f, kVClearValue / 255.0f, 0, 0);
+  api->glClearFn(GL_COLOR_BUFFER_BIT);
+
+  api->glReadPixelsFn(size.width() / 4, size.height() / 4, 1, 1, GL_RG,
+                      GL_UNSIGNED_BYTE, uv_value);
+  EXPECT_EQ(kUClearValue, uv_value[0]);
+  EXPECT_EQ(kVClearValue, uv_value[1]);
+
+  uv_texture.reset();
+  EXPECT_TRUE(shared_image_refs[1]->CopyToGpuMemoryBuffer());
+
+  {
+    base::WritableSharedMemoryMapping shm_mapping = shm_region.Map();
+    CheckYUV(shm_mapping.GetMemoryAs<uint8_t>(), size.width(), size,
+             kYClearValue, kUClearValue, kVClearValue);
+  }
+
+  // Both planes use the same underlying shared memory buffer with different
+  // offsets. Accessing via the Y plane overlay allows reading both planes.
+  {
+    auto overlay_representation =
+        shared_image_representation_factory_->ProduceOverlay(
+            shared_image_refs[0]->mailbox());
+
+    auto scoped_read_access =
+        overlay_representation->BeginScopedReadAccess(/*needs_gl_image=*/true);
+    ASSERT_TRUE(scoped_read_access);
+
+    auto* gl_image_memory =
+        gl::GLImageMemory::FromGLImage(scoped_read_access->gl_image());
+    ASSERT_TRUE(gl_image_memory);
+
+    CheckYUV(gl_image_memory->memory(), gl_image_memory->stride(), size,
+             kYClearValue, kUClearValue, kVClearValue);
+  }
+}
+
 }  // anonymous namespace
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/shared_image_backing_gl_common.h b/gpu/command_buffer/service/shared_image_backing_gl_common.h
index 535ae78..2adf1c95 100644
--- a/gpu/command_buffer/service/shared_image_backing_gl_common.h
+++ b/gpu/command_buffer/service/shared_image_backing_gl_common.h
@@ -40,6 +40,12 @@
     ScopedResetAndRestoreUnpackState(gl::GLApi* api,
                                      const UnpackStateAttribs& attribs,
                                      bool uploading_data);
+
+    ScopedResetAndRestoreUnpackState(const ScopedResetAndRestoreUnpackState&) =
+        delete;
+    ScopedResetAndRestoreUnpackState& operator=(
+        const ScopedResetAndRestoreUnpackState&) = delete;
+
     ~ScopedResetAndRestoreUnpackState();
 
    private:
@@ -64,21 +70,22 @@
     // Used when |desktop_gl|.
     GLboolean unpack_swap_bytes_ = GL_FALSE;
     GLboolean unpack_lsb_first_ = GL_FALSE;
-
-    DISALLOW_COPY_AND_ASSIGN(ScopedResetAndRestoreUnpackState);
   };
 
   // Object used to restore texture bindings.
   class ScopedRestoreTexture {
    public:
     ScopedRestoreTexture(gl::GLApi* api, GLenum target);
+
+    ScopedRestoreTexture(const ScopedRestoreTexture&) = delete;
+    ScopedRestoreTexture& operator=(const ScopedRestoreTexture&) = delete;
+
     ~ScopedRestoreTexture();
 
    private:
     gl::GLApi* api_;
     GLenum target_;
     GLuint old_binding_ = 0;
-    DISALLOW_COPY_AND_ASSIGN(ScopedRestoreTexture);
   };
 
   // Helper function to create a GL texture.
diff --git a/gpu/command_buffer/service/shared_image_backing_ozone.h b/gpu/command_buffer/service/shared_image_backing_ozone.h
index a40105c1..5d93a62 100644
--- a/gpu/command_buffer/service/shared_image_backing_ozone.h
+++ b/gpu/command_buffer/service/shared_image_backing_ozone.h
@@ -47,6 +47,9 @@
       scoped_refptr<gfx::NativePixmap> pixmap,
       scoped_refptr<base::RefCountedData<DawnProcTable>> dawn_procs);
 
+  SharedImageBackingOzone(const SharedImageBackingOzone&) = delete;
+  SharedImageBackingOzone& operator=(const SharedImageBackingOzone&) = delete;
+
   ~SharedImageBackingOzone() override;
 
   // gpu::SharedImageBacking:
@@ -110,8 +113,6 @@
   // Set for shared memory GMB.
   SharedMemoryRegionWrapper shared_memory_wrapper_;
   scoped_refptr<SharedContextState> context_state_;
-
-  DISALLOW_COPY_AND_ASSIGN(SharedImageBackingOzone);
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/shared_image_backing_scoped_hardware_buffer_fence_sync.h b/gpu/command_buffer/service/shared_image_backing_scoped_hardware_buffer_fence_sync.h
index 78dee4b6..8c806a22 100644
--- a/gpu/command_buffer/service/shared_image_backing_scoped_hardware_buffer_fence_sync.h
+++ b/gpu/command_buffer/service/shared_image_backing_scoped_hardware_buffer_fence_sync.h
@@ -35,6 +35,12 @@
       SkAlphaType alpha_type,
       uint32_t usage,
       bool is_thread_safe);
+
+  SharedImageBackingScopedHardwareBufferFenceSync(
+      const SharedImageBackingScopedHardwareBufferFenceSync&) = delete;
+  SharedImageBackingScopedHardwareBufferFenceSync& operator=(
+      const SharedImageBackingScopedHardwareBufferFenceSync&) = delete;
+
   ~SharedImageBackingScopedHardwareBufferFenceSync() override;
 
   // SharedImageBacking implementation.
@@ -89,8 +95,6 @@
   // Fence which needs to be waited upon before reading the
   // |scoped_hardware_buffer_|.
   base::ScopedFD ahb_read_fence_;
-
-  DISALLOW_COPY_AND_ASSIGN(SharedImageBackingScopedHardwareBufferFenceSync);
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/shared_image_batch_access_manager.h b/gpu/command_buffer/service/shared_image_batch_access_manager.h
index af26af6..a1717e5 100644
--- a/gpu/command_buffer/service/shared_image_batch_access_manager.h
+++ b/gpu/command_buffer/service/shared_image_batch_access_manager.h
@@ -21,6 +21,11 @@
 class GPU_GLES2_EXPORT SharedImageBatchAccessManager {
  public:
   SharedImageBatchAccessManager();
+
+  SharedImageBatchAccessManager(const SharedImageBatchAccessManager&) = delete;
+  SharedImageBatchAccessManager& operator=(
+      const SharedImageBatchAccessManager&) = delete;
+
   ~SharedImageBatchAccessManager();
 
   bool IsDoingBatchReads();
@@ -39,8 +44,6 @@
 
   base::Lock lock_;
   base::flat_map<gl::GLApi*, SetOfBackings> backings_ GUARDED_BY(lock_);
-
-  DISALLOW_COPY_AND_ASSIGN(SharedImageBatchAccessManager);
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/shared_image_factory.cc b/gpu/command_buffer/service/shared_image_factory.cc
index e8a306e..5915aca 100644
--- a/gpu/command_buffer/service/shared_image_factory.cc
+++ b/gpu/command_buffer/service/shared_image_factory.cc
@@ -492,6 +492,15 @@
   }
   return true;
 }
+
+bool SharedImageFactory::CopyToGpuMemoryBuffer(const Mailbox& mailbox) {
+  auto it = shared_images_.find(mailbox);
+  if (it == shared_images_.end()) {
+    DLOG(ERROR) << "UpdateSharedImage: Could not find shared image mailbox";
+    return false;
+  }
+  return (*it)->CopyToGpuMemoryBuffer();
+}
 #endif
 
 #if defined(OS_ANDROID)
diff --git a/gpu/command_buffer/service/shared_image_factory.h b/gpu/command_buffer/service/shared_image_factory.h
index dc229c7..ae93daf 100644
--- a/gpu/command_buffer/service/shared_image_factory.h
+++ b/gpu/command_buffer/service/shared_image_factory.h
@@ -131,6 +131,7 @@
                                     gfx::BufferFormat format,
                                     const gfx::Size& size,
                                     uint32_t usage);
+  bool CopyToGpuMemoryBuffer(const Mailbox& mailbox);
 #endif
 
 #if defined(OS_ANDROID)
diff --git a/gpu/command_buffer/service/shared_image_manager.cc b/gpu/command_buffer/service/shared_image_manager.cc
index 35679a04..d02ec31 100644
--- a/gpu/command_buffer/service/shared_image_manager.cc
+++ b/gpu/command_buffer/service/shared_image_manager.cc
@@ -67,13 +67,14 @@
     }
   }
 
+  AutoLock(const AutoLock&) = delete;
+  AutoLock& operator=(const AutoLock&) = delete;
+
   ~AutoLock() UNLOCK_FUNCTION() = default;
 
  private:
   base::TimeTicks start_time_;
   base::AutoLockMaybe auto_lock_;
-
-  DISALLOW_COPY_AND_ASSIGN(AutoLock);
 };
 
 SharedImageManager::SharedImageManager(bool thread_safe,
diff --git a/gpu/command_buffer/service/shared_image_manager.h b/gpu/command_buffer/service/shared_image_manager.h
index b76b96d..6f32228d 100644
--- a/gpu/command_buffer/service/shared_image_manager.h
+++ b/gpu/command_buffer/service/shared_image_manager.h
@@ -31,6 +31,10 @@
   // that holds the display context.
   explicit SharedImageManager(bool thread_safe = false,
                               bool display_context_on_another_thread = false);
+
+  SharedImageManager(const SharedImageManager&) = delete;
+  SharedImageManager& operator=(const SharedImageManager&) = delete;
+
   ~SharedImageManager();
 
   // Registers a SharedImageBacking with the manager and returns a
@@ -131,8 +135,6 @@
 #endif
 
   THREAD_CHECKER(thread_checker_);
-
-  DISALLOW_COPY_AND_ASSIGN(SharedImageManager);
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/shared_image_representation.h b/gpu/command_buffer/service/shared_image_representation.h
index 98c691f5..0703104 100644
--- a/gpu/command_buffer/service/shared_image_representation.h
+++ b/gpu/command_buffer/service/shared_image_representation.h
@@ -113,6 +113,10 @@
       DCHECK(!representation_->has_scoped_access_);
       representation_->has_scoped_access_ = true;
     }
+
+    ScopedAccessBase(const ScopedAccessBase&) = delete;
+    ScopedAccessBase& operator=(const ScopedAccessBase&) = delete;
+
     ~ScopedAccessBase() {
       DCHECK(representation_->has_scoped_access_);
       representation_->has_scoped_access_ = false;
@@ -125,8 +129,6 @@
 
    private:
     RepresentationClass* const representation_;
-
-    DISALLOW_COPY_AND_ASSIGN(ScopedAccessBase);
   };
 
  private:
@@ -151,6 +153,7 @@
     backing()->Update(std::move(in_fence));
     backing()->OnWriteSucceeded();
   }
+  bool CopyToGpuMemoryBuffer() { return backing()->CopyToGpuMemoryBuffer(); }
   bool ProduceLegacyMailbox(MailboxManager* mailbox_manager) {
     return backing()->ProduceLegacyMailbox(mailbox_manager);
   }
diff --git a/gpu/command_buffer/service/shared_image_representation_d3d.cc b/gpu/command_buffer/service/shared_image_representation_d3d.cc
index 9ce4ef6..c08eae97 100644
--- a/gpu/command_buffer/service/shared_image_representation_d3d.cc
+++ b/gpu/command_buffer/service/shared_image_representation_d3d.cc
@@ -118,22 +118,32 @@
 SharedImageRepresentationOverlayD3D::SharedImageRepresentationOverlayD3D(
     SharedImageManager* manager,
     SharedImageBacking* backing,
-    MemoryTypeTracker* tracker)
-    : SharedImageRepresentationOverlay(manager, backing, tracker) {}
+    MemoryTypeTracker* tracker,
+    scoped_refptr<gl::GLImage> gl_image)
+    : SharedImageRepresentationOverlay(manager, backing, tracker),
+      gl_image_(std::move(gl_image)) {}
+
+SharedImageRepresentationOverlayD3D::~SharedImageRepresentationOverlayD3D() =
+    default;
 
 bool SharedImageRepresentationOverlayD3D::BeginReadAccess(
     std::vector<gfx::GpuFence>* acquire_fences) {
-  return static_cast<SharedImageBackingD3D*>(backing())->BeginAccessD3D11();
+  // Only D3D images need keyed mutex synchronization.
+  if (gl_image_->GetType() == gl::GLImage::Type::D3D)
+    return static_cast<SharedImageBackingD3D*>(backing())->BeginAccessD3D11();
+  return true;
 }
 
 void SharedImageRepresentationOverlayD3D::EndReadAccess(
     gfx::GpuFenceHandle release_fence) {
   DCHECK(release_fence.is_null());
-  static_cast<SharedImageBackingD3D*>(backing())->EndAccessD3D11();
+  // Only D3D images need keyed mutex synchronization.
+  if (gl_image_->GetType() == gl::GLImage::Type::D3D)
+    static_cast<SharedImageBackingD3D*>(backing())->EndAccessD3D11();
 }
 
 gl::GLImage* SharedImageRepresentationOverlayD3D::GetGLImage() {
-  return static_cast<SharedImageBackingD3D*>(backing())->GetGLImage();
+  return gl_image_.get();
 }
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/shared_image_representation_d3d.h b/gpu/command_buffer/service/shared_image_representation_d3d.h
index 6348588..c89071b 100644
--- a/gpu/command_buffer/service/shared_image_representation_d3d.h
+++ b/gpu/command_buffer/service/shared_image_representation_d3d.h
@@ -76,14 +76,17 @@
  public:
   SharedImageRepresentationOverlayD3D(SharedImageManager* manager,
                                       SharedImageBacking* backing,
-                                      MemoryTypeTracker* tracker);
-  ~SharedImageRepresentationOverlayD3D() override = default;
+                                      MemoryTypeTracker* tracker,
+                                      scoped_refptr<gl::GLImage> gl_image);
+  ~SharedImageRepresentationOverlayD3D() override;
 
  private:
   bool BeginReadAccess(std::vector<gfx::GpuFence>* acquire_fences) override;
   void EndReadAccess(gfx::GpuFenceHandle release_fence) override;
 
   gl::GLImage* GetGLImage() override;
+
+  scoped_refptr<gl::GLImage> gl_image_;
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/shared_image_representation_dawn_ozone.h b/gpu/command_buffer/service/shared_image_representation_dawn_ozone.h
index 6fa1145..1ab0654 100644
--- a/gpu/command_buffer/service/shared_image_representation_dawn_ozone.h
+++ b/gpu/command_buffer/service/shared_image_representation_dawn_ozone.h
@@ -34,6 +34,11 @@
       scoped_refptr<gfx::NativePixmap> pixmap,
       scoped_refptr<base::RefCountedData<DawnProcTable>> dawn_procs);
 
+  SharedImageRepresentationDawnOzone(
+      const SharedImageRepresentationDawnOzone&) = delete;
+  SharedImageRepresentationDawnOzone& operator=(
+      const SharedImageRepresentationDawnOzone&) = delete;
+
   ~SharedImageRepresentationDawnOzone() override;
 
   WGPUTexture BeginAccess(WGPUTextureUsage usage) override;
@@ -51,8 +56,6 @@
   scoped_refptr<gfx::NativePixmap> pixmap_;
   WGPUTexture texture_ = nullptr;
   scoped_refptr<base::RefCountedData<DawnProcTable>> dawn_procs_;
-
-  DISALLOW_COPY_AND_ASSIGN(SharedImageRepresentationDawnOzone);
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/sync_point_manager.h b/gpu/command_buffer/service/sync_point_manager.h
index 496840b..42ed4c6 100644
--- a/gpu/command_buffer/service/sync_point_manager.h
+++ b/gpu/command_buffer/service/sync_point_manager.h
@@ -259,6 +259,10 @@
 class GPU_EXPORT SyncPointManager {
  public:
   SyncPointManager();
+
+  SyncPointManager(const SyncPointManager&) = delete;
+  SyncPointManager& operator=(const SyncPointManager&) = delete;
+
   ~SyncPointManager();
 
   scoped_refptr<SyncPointOrderData> CreateSyncPointOrderData();
@@ -341,8 +345,6 @@
   SequenceId::Generator sequence_id_generator_;
 
   mutable base::Lock lock_;
-
-  DISALLOW_COPY_AND_ASSIGN(SyncPointManager);
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/texture_manager.h b/gpu/command_buffer/service/texture_manager.h
index ae2e6eee..d1139c8 100644
--- a/gpu/command_buffer/service/texture_manager.h
+++ b/gpu/command_buffer/service/texture_manager.h
@@ -829,6 +829,10 @@
   class GPU_GLES2_EXPORT DestructionObserver {
    public:
     DestructionObserver();
+
+    DestructionObserver(const DestructionObserver&) = delete;
+    DestructionObserver& operator=(const DestructionObserver&) = delete;
+
     virtual ~DestructionObserver();
 
     // Called in ~TextureManager.
@@ -836,9 +840,6 @@
 
     // Called via ~TextureRef.
     virtual void OnTextureRefDestroying(TextureRef* texture) = 0;
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(DestructionObserver);
   };
 
   enum DefaultAndBlackTextures {
@@ -861,6 +862,10 @@
                  bool use_default_textures,
                  gl::ProgressReporter* progress_reporter,
                  ServiceDiscardableManager* discardable_manager);
+
+  TextureManager(const TextureManager&) = delete;
+  TextureManager& operator=(const TextureManager&) = delete;
+
   ~TextureManager() override;
 
   void AddFramebufferManager(FramebufferManager* framebuffer_manager);
@@ -1373,8 +1378,6 @@
   gl::ProgressReporter* progress_reporter_;
 
   ServiceDiscardableManager* discardable_manager_;
-
-  DISALLOW_COPY_AND_ASSIGN(TextureManager);
 };
 
 }  // namespace gles2
diff --git a/gpu/command_buffer/service/texture_manager_unittest.cc b/gpu/command_buffer/service/texture_manager_unittest.cc
index e1f3d4c..ff30254 100644
--- a/gpu/command_buffer/service/texture_manager_unittest.cc
+++ b/gpu/command_buffer/service/texture_manager_unittest.cc
@@ -2144,6 +2144,10 @@
   CountingMemoryTracker() {
     current_size_ = 0;
   }
+
+  CountingMemoryTracker(const CountingMemoryTracker&) = delete;
+  CountingMemoryTracker& operator=(const CountingMemoryTracker&) = delete;
+
   ~CountingMemoryTracker() override = default;
 
   void TrackMemoryAllocatedChange(int64_t delta) override {
@@ -2161,7 +2165,6 @@
 
  private:
   uint64_t current_size_;
-  DISALLOW_COPY_AND_ASSIGN(CountingMemoryTracker);
 };
 
 class SharedTextureTest : public GpuServiceTest {
diff --git a/gpu/command_buffer/service/transfer_buffer_manager.h b/gpu/command_buffer/service/transfer_buffer_manager.h
index 1e9dacf..8a69ade 100644
--- a/gpu/command_buffer/service/transfer_buffer_manager.h
+++ b/gpu/command_buffer/service/transfer_buffer_manager.h
@@ -22,6 +22,10 @@
     : public base::trace_event::MemoryDumpProvider {
  public:
   explicit TransferBufferManager(MemoryTracker* memory_tracker);
+
+  TransferBufferManager(const TransferBufferManager&) = delete;
+  TransferBufferManager& operator=(const TransferBufferManager&) = delete;
+
   ~TransferBufferManager() override;
 
   // Overridden from base::trace_event::MemoryDumpProvider:
@@ -41,8 +45,6 @@
   BufferMap registered_buffers_;
   size_t shared_memory_bytes_allocated_;
   MemoryTracker* memory_tracker_;
-
-  DISALLOW_COPY_AND_ASSIGN(TransferBufferManager);
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/transform_feedback_manager.h b/gpu/command_buffer/service/transform_feedback_manager.h
index dc55079..e76c4be 100644
--- a/gpu/command_buffer/service/transform_feedback_manager.h
+++ b/gpu/command_buffer/service/transform_feedback_manager.h
@@ -105,6 +105,10 @@
   // out-of-bounds buffer accesses.
   TransformFeedbackManager(GLuint max_transform_feedback_separate_attribs,
                            bool needs_emulation);
+
+  TransformFeedbackManager(const TransformFeedbackManager&) = delete;
+  TransformFeedbackManager& operator=(const TransformFeedbackManager&) = delete;
+
   ~TransformFeedbackManager();
 
   void MarkContextLost() {
@@ -145,8 +149,6 @@
 
   bool needs_emulation_;
   bool lost_context_;
-
-  DISALLOW_COPY_AND_ASSIGN(TransformFeedbackManager);
 };
 
 }  // namespace gles2
diff --git a/gpu/command_buffer/service/vertex_array_manager.h b/gpu/command_buffer/service/vertex_array_manager.h
index cc1f84a..e489c4fa 100644
--- a/gpu/command_buffer/service/vertex_array_manager.h
+++ b/gpu/command_buffer/service/vertex_array_manager.h
@@ -24,6 +24,10 @@
 class GPU_GLES2_EXPORT VertexArrayManager {
  public:
   VertexArrayManager();
+
+  VertexArrayManager(const VertexArrayManager&) = delete;
+  VertexArrayManager& operator=(const VertexArrayManager&) = delete;
+
   ~VertexArrayManager();
 
   // Must call before destruction.
@@ -68,8 +72,6 @@
   unsigned int vertex_attrib_manager_count_;
 
   bool have_context_;
-
-  DISALLOW_COPY_AND_ASSIGN(VertexArrayManager);
 };
 
 }  // namespace gles2
diff --git a/gpu/command_buffer/service/webgpu_decoder.h b/gpu/command_buffer/service/webgpu_decoder.h
index 86f835b..67ade5f 100644
--- a/gpu/command_buffer/service/webgpu_decoder.h
+++ b/gpu/command_buffer/service/webgpu_decoder.h
@@ -33,6 +33,9 @@
                                gles2::Outputter* outputter,
                                const GpuPreferences& gpu_preferences);
 
+  WebGPUDecoder(const WebGPUDecoder&) = delete;
+  WebGPUDecoder& operator=(const WebGPUDecoder&) = delete;
+
   ~WebGPUDecoder() override;
 
   // WebGPU-specific initialization that's different than DecoderContext's
@@ -49,9 +52,6 @@
   WebGPUDecoder(DecoderClient* client,
                 CommandBufferServiceBase* command_buffer_service,
                 gles2::Outputter* outputter);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(WebGPUDecoder);
 };
 
 }  // namespace webgpu
diff --git a/gpu/command_buffer/service/webgpu_decoder_impl.cc b/gpu/command_buffer/service/webgpu_decoder_impl.cc
index ef2c8669..08356b30 100644
--- a/gpu/command_buffer/service/webgpu_decoder_impl.cc
+++ b/gpu/command_buffer/service/webgpu_decoder_impl.cc
@@ -169,6 +169,10 @@
                     MemoryTracker* memory_tracker,
                     gles2::Outputter* outputter,
                     const GpuPreferences& gpu_preferences);
+
+  WebGPUDecoderImpl(const WebGPUDecoderImpl&) = delete;
+  WebGPUDecoderImpl& operator=(const WebGPUDecoderImpl&) = delete;
+
   ~WebGPUDecoderImpl() override;
 
   // WebGPUDecoder implementation
@@ -483,8 +487,6 @@
   scoped_refptr<gl::GLSurface> gl_surface_;
 
   base::WeakPtrFactory<WebGPUDecoderImpl> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(WebGPUDecoderImpl);
 };
 
 constexpr WebGPUDecoderImpl::CommandInfo WebGPUDecoderImpl::command_info[] = {
diff --git a/gpu/command_buffer/service/wrapped_sk_image.cc b/gpu/command_buffer/service/wrapped_sk_image.cc
index 6aea8ed..d7016cd 100644
--- a/gpu/command_buffer/service/wrapped_sk_image.cc
+++ b/gpu/command_buffer/service/wrapped_sk_image.cc
@@ -125,6 +125,9 @@
     DCHECK(!!context_state_);
   }
 
+  WrappedSkImage(const WrappedSkImage&) = delete;
+  WrappedSkImage& operator=(const WrappedSkImage&) = delete;
+
   ~WrappedSkImage() override {
     context_state_->MakeCurrent(nullptr);
     promise_texture_.reset();
@@ -338,8 +341,6 @@
   SharedMemoryRegionWrapper shared_memory_wrapper_;
 
   uint64_t tracing_id_ = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(WrappedSkImage);
 };
 
 class WrappedSkImage::RepresentationSkia
diff --git a/gpu/command_buffer/service/wrapped_sk_image.h b/gpu/command_buffer/service/wrapped_sk_image.h
index 55a66c0b..7491c669 100644
--- a/gpu/command_buffer/service/wrapped_sk_image.h
+++ b/gpu/command_buffer/service/wrapped_sk_image.h
@@ -26,6 +26,10 @@
  public:
   explicit WrappedSkImageFactory(
       scoped_refptr<SharedContextState> context_state);
+
+  WrappedSkImageFactory(const WrappedSkImageFactory&) = delete;
+  WrappedSkImageFactory& operator=(const WrappedSkImageFactory&) = delete;
+
   ~WrappedSkImageFactory() override;
 
   // SharedImageBackingFactory implementation:
@@ -74,8 +78,6 @@
                             GrContextType gr_context_type) const;
 
   scoped_refptr<SharedContextState> context_state_;
-
-  DISALLOW_COPY_AND_ASSIGN(WrappedSkImageFactory);
 };
 
 }  // namespace raster
diff --git a/gpu/config/gpu_blocklist.h b/gpu/config/gpu_blocklist.h
index f5ba03f0..2b698a4 100644
--- a/gpu/config/gpu_blocklist.h
+++ b/gpu/config/gpu_blocklist.h
@@ -14,6 +14,9 @@
 
 class GPU_EXPORT GpuBlocklist : public GpuControlList {
  public:
+  GpuBlocklist(const GpuBlocklist&) = delete;
+  GpuBlocklist& operator=(const GpuBlocklist&) = delete;
+
   ~GpuBlocklist() override;
 
   static std::unique_ptr<GpuBlocklist> Create();
@@ -23,8 +26,6 @@
 
  private:
   explicit GpuBlocklist(const GpuControlListData& data);
-
-  DISALLOW_COPY_AND_ASSIGN(GpuBlocklist);
 };
 
 }  // namespace gpu
diff --git a/gpu/config/gpu_driver_bug_list.h b/gpu/config/gpu_driver_bug_list.h
index be8d557..1bca4d2 100644
--- a/gpu/config/gpu_driver_bug_list.h
+++ b/gpu/config/gpu_driver_bug_list.h
@@ -17,6 +17,9 @@
 
 class GPU_EXPORT GpuDriverBugList : public GpuControlList {
  public:
+  GpuDriverBugList(const GpuDriverBugList&) = delete;
+  GpuDriverBugList& operator=(const GpuDriverBugList&) = delete;
+
   ~GpuDriverBugList() override;
 
   static std::unique_ptr<GpuDriverBugList> Create();
@@ -38,8 +41,6 @@
 
  private:
   explicit GpuDriverBugList(const GpuControlListData& data);
-
-  DISALLOW_COPY_AND_ASSIGN(GpuDriverBugList);
 };
 
 }  // namespace gpu
diff --git a/gpu/gles2_conform_support/egl/config.h b/gpu/gles2_conform_support/egl/config.h
index 1a09a99..3e2bad2 100644
--- a/gpu/gles2_conform_support/egl/config.h
+++ b/gpu/gles2_conform_support/egl/config.h
@@ -15,6 +15,10 @@
 class Config {
  public:
   explicit Config(EGLint surface_type);
+
+  Config(const Config&) = delete;
+  Config& operator=(const Config&) = delete;
+
   ~Config();
   bool Matches(const EGLint* attrib_list) const;
   bool GetAttrib(EGLint attribute, EGLint* value) const;
@@ -85,8 +89,6 @@
   EGLint transparent_green_value_;
   // Transparent blue value
   EGLint transparent_blue_value_;
-
-  DISALLOW_COPY_AND_ASSIGN(Config);
 };
 
 }  // namespace egl
diff --git a/gpu/gles2_conform_support/egl/display.h b/gpu/gles2_conform_support/egl/display.h
index bd42604..448b9660 100644
--- a/gpu/gles2_conform_support/egl/display.h
+++ b/gpu/gles2_conform_support/egl/display.h
@@ -27,6 +27,10 @@
 class Display {
  public:
   explicit Display();
+
+  Display(const Display&) = delete;
+  Display& operator=(const Display&) = delete;
+
   ~Display();
 
   bool is_initialized() const { return is_initialized_; }
@@ -100,8 +104,6 @@
   bool next_create_window_surface_creates_pbuffer_;
   EGLint window_surface_pbuffer_width_;
   EGLint window_surface_pbuffer_height_;
-
-  DISALLOW_COPY_AND_ASSIGN(Display);
 };
 
 }  // namespace egl
diff --git a/gpu/gles2_conform_support/egl/thread_state.h b/gpu/gles2_conform_support/egl/thread_state.h
index 179dc451..fd9a58c7 100644
--- a/gpu/gles2_conform_support/egl/thread_state.h
+++ b/gpu/gles2_conform_support/egl/thread_state.h
@@ -47,12 +47,16 @@
   class AutoCurrentContextRestore {
    public:
     AutoCurrentContextRestore(ThreadState*);
+
+    AutoCurrentContextRestore(const AutoCurrentContextRestore&) = delete;
+    AutoCurrentContextRestore& operator=(const AutoCurrentContextRestore&) =
+        delete;
+
     ~AutoCurrentContextRestore();
     void SetCurrent(Surface*, Context*);
 
    private:
     ThreadState* thread_state_;
-    DISALLOW_COPY_AND_ASSIGN(AutoCurrentContextRestore);
   };
 
  private:
diff --git a/gpu/ipc/client/client_shared_image_interface.cc b/gpu/ipc/client/client_shared_image_interface.cc
index 701bd23..20a719e 100644
--- a/gpu/ipc/client/client_shared_image_interface.cc
+++ b/gpu/ipc/client/client_shared_image_interface.cc
@@ -129,6 +129,12 @@
   }
   return mailboxes;
 }
+
+void ClientSharedImageInterface::CopyToGpuMemoryBuffer(
+    const SyncToken& sync_token,
+    const Mailbox& mailbox) {
+  proxy_->CopyToGpuMemoryBuffer(sync_token, mailbox);
+}
 #endif
 
 #if defined(OS_ANDROID)
diff --git a/gpu/ipc/client/client_shared_image_interface.h b/gpu/ipc/client/client_shared_image_interface.h
index 9aee73c..18a74b78 100644
--- a/gpu/ipc/client/client_shared_image_interface.h
+++ b/gpu/ipc/client/client_shared_image_interface.h
@@ -71,6 +71,8 @@
       gfx::GpuMemoryBuffer* gpu_memory_buffer,
       GpuMemoryBufferManager* gpu_memory_buffer_manager,
       uint32_t usage) override;
+  void CopyToGpuMemoryBuffer(const SyncToken& sync_token,
+                             const Mailbox& mailbox) override;
 #endif
 #if defined(OS_ANDROID)
   Mailbox CreateSharedImageWithAHB(const Mailbox& mailbox,
diff --git a/gpu/ipc/client/image_decode_accelerator_proxy.h b/gpu/ipc/client/image_decode_accelerator_proxy.h
index 1fd6f91..7f9c8fa 100644
--- a/gpu/ipc/client/image_decode_accelerator_proxy.h
+++ b/gpu/ipc/client/image_decode_accelerator_proxy.h
@@ -50,6 +50,11 @@
     : public ImageDecodeAcceleratorInterface {
  public:
   ImageDecodeAcceleratorProxy(GpuChannelHost* host, int32_t route_id);
+
+  ImageDecodeAcceleratorProxy(const ImageDecodeAcceleratorProxy&) = delete;
+  ImageDecodeAcceleratorProxy& operator=(const ImageDecodeAcceleratorProxy&) =
+      delete;
+
   ~ImageDecodeAcceleratorProxy() override;
 
   // Determines if |image_metadata| corresponds to an image that can be decoded
@@ -94,8 +99,6 @@
 
   base::Lock lock_;
   uint64_t next_release_count_ GUARDED_BY(lock_) = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(ImageDecodeAcceleratorProxy);
 };
 
 }  // namespace gpu
diff --git a/gpu/ipc/client/shared_image_interface_proxy.cc b/gpu/ipc/client/shared_image_interface_proxy.cc
index 4050e4c..6d7757ee 100644
--- a/gpu/ipc/client/shared_image_interface_proxy.cc
+++ b/gpu/ipc/client/shared_image_interface_proxy.cc
@@ -260,7 +260,23 @@
   }
   return mailboxes;
 }
-#endif
+
+void SharedImageInterfaceProxy::CopyToGpuMemoryBuffer(
+    const SyncToken& sync_token,
+    const Mailbox& mailbox) {
+  std::vector<SyncToken> dependencies =
+      GenerateDependenciesFromSyncToken(std::move(sync_token), host_);
+  {
+    base::AutoLock lock(lock_);
+    last_flush_id_ = host_->EnqueueDeferredMessage(
+        mojom::DeferredRequestParams::NewSharedImageRequest(
+            mojom::DeferredSharedImageRequest::NewCopyToGpuMemoryBuffer(
+                mojom::CopyToGpuMemoryBufferParams::New(mailbox,
+                                                        ++next_release_id_))),
+        std::move(dependencies));
+  }
+}
+#endif  // OS_WIN
 
 #if defined(OS_ANDROID)
 Mailbox SharedImageInterfaceProxy::CreateSharedImageWithAHB(
diff --git a/gpu/ipc/client/shared_image_interface_proxy.h b/gpu/ipc/client/shared_image_interface_proxy.h
index 68b7fd2..9637ee65 100644
--- a/gpu/ipc/client/shared_image_interface_proxy.h
+++ b/gpu/ipc/client/shared_image_interface_proxy.h
@@ -47,7 +47,9 @@
       gfx::GpuMemoryBuffer* gpu_memory_buffer,
       GpuMemoryBufferManager* gpu_memory_buffer_manager,
       uint32_t usage);
-#endif
+  void CopyToGpuMemoryBuffer(const SyncToken& sync_token,
+                             const Mailbox& mailbox);
+#endif  // OS_WIN
 
 #if defined(OS_ANDROID)
   Mailbox CreateSharedImageWithAHB(const Mailbox& mailbox,
diff --git a/gpu/ipc/command_buffer_task_executor.h b/gpu/ipc/command_buffer_task_executor.h
index 3b34f04d..a0634fc 100644
--- a/gpu/ipc/command_buffer_task_executor.h
+++ b/gpu/ipc/command_buffer_task_executor.h
@@ -50,6 +50,11 @@
                             gl::GLSurfaceFormat share_group_surface_format,
                             SharedImageManager* shared_image_manager,
                             gles2::ProgramCache* program_cache);
+
+  CommandBufferTaskExecutor(const CommandBufferTaskExecutor&) = delete;
+  CommandBufferTaskExecutor& operator=(const CommandBufferTaskExecutor&) =
+      delete;
+
   virtual ~CommandBufferTaskExecutor();
 
   // Always use virtualized GL contexts if this returns true.
@@ -122,8 +127,6 @@
 
   // No-op default initialization is used in in-process mode.
   GpuProcessActivityFlags activity_flags_;
-
-  DISALLOW_COPY_AND_ASSIGN(CommandBufferTaskExecutor);
 };
 
 }  // namespace gpu
diff --git a/gpu/ipc/common/gpu_channel.mojom b/gpu/ipc/common/gpu_channel.mojom
index ace81d66..cccc79f 100644
--- a/gpu/ipc/common/gpu_channel.mojom
+++ b/gpu/ipc/common/gpu_channel.mojom
@@ -478,6 +478,10 @@
   // See UpdateSharedImageParams.
   UpdateSharedImageParams update_shared_image;
 
+  // See CopyToGpuMemoryBufferParams.
+  [EnableIf=is_win]
+  CopyToGpuMemoryBufferParams copy_to_gpu_memory_buffer;
+
   // Destroys the shared image identified by this Mailbox.
   Mailbox destroy_shared_image;
 
@@ -670,6 +674,17 @@
   gfx.mojom.GpuFenceHandle? in_fence_handle;
 };
 
+// Updates the contents of the GpuMemoryBuffer associated with the shared image.
+// Necessary on platforms like Windows where renderer cannot create native GMBs.
+[EnableIf=is_win]
+struct CopyToGpuMemoryBufferParams {
+  // The mailbox identifying the shared image which should update its GMB.
+  Mailbox mailbox;
+
+  // The fence to release once the GMB has been updated.
+  uint32 release_id;
+};
+
 [EnableIf=is_win]
 struct CreateSwapChainParams {
   // Mailbox identifying the front buffer of the swap chain.
diff --git a/gpu/ipc/common/gpu_memory_buffer_impl.h b/gpu/ipc/common/gpu_memory_buffer_impl.h
index e68c2cc..6ee7e93 100644
--- a/gpu/ipc/common/gpu_memory_buffer_impl.h
+++ b/gpu/ipc/common/gpu_memory_buffer_impl.h
@@ -22,6 +22,9 @@
  public:
   using DestructionCallback = base::OnceCallback<void(const gpu::SyncToken&)>;
 
+  GpuMemoryBufferImpl(const GpuMemoryBufferImpl&) = delete;
+  GpuMemoryBufferImpl& operator=(const GpuMemoryBufferImpl&) = delete;
+
   ~GpuMemoryBufferImpl() override;
 
   // Overridden from gfx::GpuMemoryBuffer:
@@ -57,9 +60,6 @@
   // Unmap() operations to avoid corrupt mutation across multiple threads.
   base::Lock map_lock_;
   uint32_t map_count_ GUARDED_BY(map_lock_) = 0u;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferImpl);
 };
 
 }  // namespace gpu
diff --git a/gpu/ipc/common/gpu_memory_buffer_impl_android_hardware_buffer.h b/gpu/ipc/common/gpu_memory_buffer_impl_android_hardware_buffer.h
index e7d04d3..d725eefd 100644
--- a/gpu/ipc/common/gpu_memory_buffer_impl_android_hardware_buffer.h
+++ b/gpu/ipc/common/gpu_memory_buffer_impl_android_hardware_buffer.h
@@ -15,6 +15,11 @@
 class GPU_EXPORT GpuMemoryBufferImplAndroidHardwareBuffer
     : public GpuMemoryBufferImpl {
  public:
+  GpuMemoryBufferImplAndroidHardwareBuffer(
+      const GpuMemoryBufferImplAndroidHardwareBuffer&) = delete;
+  GpuMemoryBufferImplAndroidHardwareBuffer& operator=(
+      const GpuMemoryBufferImplAndroidHardwareBuffer&) = delete;
+
   ~GpuMemoryBufferImplAndroidHardwareBuffer() override;
 
   static constexpr gfx::GpuMemoryBufferType kBufferType =
@@ -57,8 +62,6 @@
       base::android::ScopedHardwareBufferHandle handle);
 
   base::android::ScopedHardwareBufferHandle hardware_buffer_handle_;
-
-  DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferImplAndroidHardwareBuffer);
 };
 
 }  // namespace gpu
diff --git a/gpu/ipc/common/gpu_memory_buffer_impl_dxgi.h b/gpu/ipc/common/gpu_memory_buffer_impl_dxgi.h
index 4b1c371b..4d65aab 100644
--- a/gpu/ipc/common/gpu_memory_buffer_impl_dxgi.h
+++ b/gpu/ipc/common/gpu_memory_buffer_impl_dxgi.h
@@ -24,6 +24,9 @@
 // Implementation of GPU memory buffer based on dxgi textures.
 class GPU_EXPORT GpuMemoryBufferImplDXGI : public GpuMemoryBufferImpl {
  public:
+  GpuMemoryBufferImplDXGI(const GpuMemoryBufferImplDXGI&) = delete;
+  GpuMemoryBufferImplDXGI& operator=(const GpuMemoryBufferImplDXGI&) = delete;
+
   ~GpuMemoryBufferImplDXGI() override;
 
   static constexpr gfx::GpuMemoryBufferType kBufferType =
@@ -74,8 +77,6 @@
   // Used to store shared memory passed from the capturer.
   base::UnsafeSharedMemoryRegion unowned_region_;
   base::WritableSharedMemoryMapping unowned_mapping_;
-
-  DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferImplDXGI);
 };
 
 }  // namespace gpu
diff --git a/gpu/ipc/common/gpu_memory_buffer_impl_io_surface.h b/gpu/ipc/common/gpu_memory_buffer_impl_io_surface.h
index cd32fbd..816450c 100644
--- a/gpu/ipc/common/gpu_memory_buffer_impl_io_surface.h
+++ b/gpu/ipc/common/gpu_memory_buffer_impl_io_surface.h
@@ -22,6 +22,10 @@
 // Implementation of GPU memory buffer based on IO surfaces.
 class GPU_EXPORT GpuMemoryBufferImplIOSurface : public GpuMemoryBufferImpl {
  public:
+  GpuMemoryBufferImplIOSurface(const GpuMemoryBufferImplIOSurface&) = delete;
+  GpuMemoryBufferImplIOSurface& operator=(const GpuMemoryBufferImplIOSurface&) =
+      delete;
+
   ~GpuMemoryBufferImplIOSurface() override;
 
   static constexpr gfx::GpuMemoryBufferType kBufferType =
@@ -63,8 +67,6 @@
   // Cache the color space, because re-assigning the same value can be
   // expensive.
   gfx::ColorSpace color_space_;
-
-  DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferImplIOSurface);
 };
 
 }  // namespace gpu
diff --git a/gpu/ipc/common/gpu_memory_buffer_impl_native_pixmap.h b/gpu/ipc/common/gpu_memory_buffer_impl_native_pixmap.h
index 360641e..e430f33a 100644
--- a/gpu/ipc/common/gpu_memory_buffer_impl_native_pixmap.h
+++ b/gpu/ipc/common/gpu_memory_buffer_impl_native_pixmap.h
@@ -24,6 +24,11 @@
 // Implementation of GPU memory buffer based on Ozone native pixmap.
 class GPU_EXPORT GpuMemoryBufferImplNativePixmap : public GpuMemoryBufferImpl {
  public:
+  GpuMemoryBufferImplNativePixmap(const GpuMemoryBufferImplNativePixmap&) =
+      delete;
+  GpuMemoryBufferImplNativePixmap& operator=(
+      const GpuMemoryBufferImplNativePixmap&) = delete;
+
   ~GpuMemoryBufferImplNativePixmap() override;
 
   static constexpr gfx::GpuMemoryBufferType kBufferType = gfx::NATIVE_PIXMAP;
@@ -59,8 +64,6 @@
       std::unique_ptr<gfx::ClientNativePixmap> native_pixmap);
 
   const std::unique_ptr<gfx::ClientNativePixmap> pixmap_;
-
-  DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferImplNativePixmap);
 };
 
 }  // namespace gpu
diff --git a/gpu/ipc/common/gpu_memory_buffer_impl_shared_memory.h b/gpu/ipc/common/gpu_memory_buffer_impl_shared_memory.h
index d67583e..96ece7f 100644
--- a/gpu/ipc/common/gpu_memory_buffer_impl_shared_memory.h
+++ b/gpu/ipc/common/gpu_memory_buffer_impl_shared_memory.h
@@ -18,6 +18,11 @@
 // Implementation of GPU memory buffer based on shared memory.
 class GPU_EXPORT GpuMemoryBufferImplSharedMemory : public GpuMemoryBufferImpl {
  public:
+  GpuMemoryBufferImplSharedMemory(const GpuMemoryBufferImplSharedMemory&) =
+      delete;
+  GpuMemoryBufferImplSharedMemory& operator=(
+      const GpuMemoryBufferImplSharedMemory&) = delete;
+
   ~GpuMemoryBufferImplSharedMemory() override;
 
   static constexpr gfx::GpuMemoryBufferType kBufferType =
@@ -87,8 +92,6 @@
   base::WritableSharedMemoryMapping shared_memory_mapping_;
   size_t offset_;
   int stride_;
-
-  DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferImplSharedMemory);
 };
 
 }  // namespace gpu
diff --git a/gpu/ipc/common/gpu_memory_buffer_support.cc b/gpu/ipc/common/gpu_memory_buffer_support.cc
index d63d36af..3205845 100644
--- a/gpu/ipc/common/gpu_memory_buffer_support.cc
+++ b/gpu/ipc/common/gpu_memory_buffer_support.cc
@@ -151,7 +151,6 @@
              format == gfx::BufferFormat::YUV_420_BIPLANAR;
     case gfx::BufferUsage::SCANOUT_CPU_READ_WRITE:
     case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE:
-      return format == gfx::BufferFormat::YUV_420_BIPLANAR;
     case gfx::BufferUsage::SCANOUT_VDA_WRITE:
     case gfx::BufferUsage::PROTECTED_SCANOUT_VDA_WRITE:
     case gfx::BufferUsage::SCANOUT_CAMERA_READ_WRITE:
diff --git a/gpu/ipc/common/gpu_memory_buffer_support.h b/gpu/ipc/common/gpu_memory_buffer_support.h
index 32428cc4..3349f1c 100644
--- a/gpu/ipc/common/gpu_memory_buffer_support.h
+++ b/gpu/ipc/common/gpu_memory_buffer_support.h
@@ -32,6 +32,10 @@
 class GPU_EXPORT GpuMemoryBufferSupport {
  public:
   GpuMemoryBufferSupport();
+
+  GpuMemoryBufferSupport(const GpuMemoryBufferSupport&) = delete;
+  GpuMemoryBufferSupport& operator=(const GpuMemoryBufferSupport&) = delete;
+
   virtual ~GpuMemoryBufferSupport();
 
   // Returns the native GPU memory buffer factory type. Returns EMPTY_BUFFER
@@ -73,8 +77,6 @@
 #if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(USE_OZONE)
   std::unique_ptr<gfx::ClientNativePixmapFactory> client_native_pixmap_factory_;
 #endif
-
-  DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferSupport);
 };
 
 }  // namespace gpu
diff --git a/gpu/ipc/common/gpu_surface_lookup.h b/gpu/ipc/common/gpu_surface_lookup.h
index 5ae2c15..c498bab 100644
--- a/gpu/ipc/common/gpu_surface_lookup.h
+++ b/gpu/ipc/common/gpu_surface_lookup.h
@@ -21,6 +21,10 @@
 class GPU_EXPORT GpuSurfaceLookup {
  public:
   GpuSurfaceLookup() {}
+
+  GpuSurfaceLookup(const GpuSurfaceLookup&) = delete;
+  GpuSurfaceLookup& operator=(const GpuSurfaceLookup&) = delete;
+
   virtual ~GpuSurfaceLookup() {}
 
   static GpuSurfaceLookup* GetInstance();
@@ -35,9 +39,6 @@
       int surface_id,
       bool* can_be_used_with_surface_control) = 0;
 #endif
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(GpuSurfaceLookup);
 };
 
 }  // namespace gpu
diff --git a/gpu/ipc/gl_in_process_context.h b/gpu/ipc/gl_in_process_context.h
index 5f0a0354..42b90e80 100644
--- a/gpu/ipc/gl_in_process_context.h
+++ b/gpu/ipc/gl_in_process_context.h
@@ -32,6 +32,10 @@
  public:
   // You must call Initialize() before using the context.
   GLInProcessContext();
+
+  GLInProcessContext(const GLInProcessContext&) = delete;
+  GLInProcessContext& operator=(const GLInProcessContext&) = delete;
+
   ~GLInProcessContext();
 
   // Initialize the GLInProcessContext, if |is_offscreen| is true, renders to an
@@ -70,8 +74,6 @@
   std::unique_ptr<gles2::GLES2CmdHelper> gles2_helper_;
   std::unique_ptr<TransferBuffer> transfer_buffer_;
   std::unique_ptr<gles2::GLES2Implementation> gles2_implementation_;
-
-  DISALLOW_COPY_AND_ASSIGN(GLInProcessContext);
 };
 
 }  // namespace gpu
diff --git a/gpu/ipc/gpu_in_process_thread_service.h b/gpu/ipc/gpu_in_process_thread_service.h
index 442861a..637a2a6 100644
--- a/gpu/ipc/gpu_in_process_thread_service.h
+++ b/gpu/ipc/gpu_in_process_thread_service.h
@@ -56,6 +56,11 @@
       const GpuPreferences& gpu_preferences,
       SharedImageManager* shared_image_manager,
       gles2::ProgramCache* program_cache);
+
+  GpuInProcessThreadService(const GpuInProcessThreadService&) = delete;
+  GpuInProcessThreadService& operator=(const GpuInProcessThreadService&) =
+      delete;
+
   ~GpuInProcessThreadService() override;
 
   // CommandBufferTaskExecutor implementation.
@@ -72,8 +77,6 @@
   GpuInProcessThreadServiceDelegate* const delegate_;
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
   Scheduler* scheduler_;
-
-  DISALLOW_COPY_AND_ASSIGN(GpuInProcessThreadService);
 };
 
 }  // namespace gpu
diff --git a/gpu/ipc/gpu_task_scheduler_helper.h b/gpu/ipc/gpu_task_scheduler_helper.h
index 01c9c8e..f537cfc89 100644
--- a/gpu/ipc/gpu_task_scheduler_helper.h
+++ b/gpu/ipc/gpu_task_scheduler_helper.h
@@ -47,6 +47,10 @@
   // This constructor is used for command buffer GLOutputSurface.
   explicit GpuTaskSchedulerHelper(
       CommandBufferTaskExecutor* command_buffer_task_executor);
+
+  GpuTaskSchedulerHelper(const GpuTaskSchedulerHelper&) = delete;
+  GpuTaskSchedulerHelper& operator=(const GpuTaskSchedulerHelper&) = delete;
+
   ~GpuTaskSchedulerHelper();
 
   // This function sets up the |command_buffer_helper| which flushes the command
@@ -102,8 +106,6 @@
   // chance to post any pending tasks and maintains the ordering between command
   // buffer and other user tasks.
   CommandBufferHelper* command_buffer_helper_ = nullptr;
-
-  DISALLOW_COPY_AND_ASSIGN(GpuTaskSchedulerHelper);
 };
 
 }  // namespace gpu
diff --git a/gpu/ipc/host/shader_disk_cache.cc b/gpu/ipc/host/shader_disk_cache.cc
index 52dbcde8..fb683a46 100644
--- a/gpu/ipc/host/shader_disk_cache.cc
+++ b/gpu/ipc/host/shader_disk_cache.cc
@@ -51,6 +51,10 @@
   ShaderDiskCacheEntry(ShaderDiskCache* cache,
                        const std::string& key,
                        const std::string& shader);
+
+  ShaderDiskCacheEntry(const ShaderDiskCacheEntry&) = delete;
+  ShaderDiskCacheEntry& operator=(const ShaderDiskCacheEntry&) = delete;
+
   ~ShaderDiskCacheEntry();
 
   void Cache();
@@ -75,8 +79,6 @@
   disk_cache::Entry* entry_;
   base::WeakPtr<ShaderDiskCacheEntry> weak_ptr_;
   base::WeakPtrFactory<ShaderDiskCacheEntry> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(ShaderDiskCacheEntry);
 };
 
 // ShaderDiskReadHelper is used to load all of the cached shaders from the
@@ -86,6 +88,10 @@
   using ShaderLoadedCallback = ShaderDiskCache::ShaderLoadedCallback;
   ShaderDiskReadHelper(ShaderDiskCache* cache,
                        const ShaderLoadedCallback& callback);
+
+  ShaderDiskReadHelper(const ShaderDiskReadHelper&) = delete;
+  ShaderDiskReadHelper& operator=(const ShaderDiskReadHelper&) = delete;
+
   ~ShaderDiskReadHelper();
 
   void LoadCache();
@@ -113,8 +119,6 @@
   scoped_refptr<net::IOBufferWithSize> buf_;
   disk_cache::Entry* entry_;
   base::WeakPtrFactory<ShaderDiskReadHelper> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(ShaderDiskReadHelper);
 };
 
 class ShaderClearHelper : public base::ThreadChecker {
@@ -125,6 +129,10 @@
                     const base::Time& delete_begin,
                     const base::Time& delete_end,
                     base::OnceClosure callback);
+
+  ShaderClearHelper(const ShaderClearHelper&) = delete;
+  ShaderClearHelper& operator=(const ShaderClearHelper&) = delete;
+
   ~ShaderClearHelper();
 
   void Clear();
@@ -142,8 +150,6 @@
   base::Time delete_end_;
   base::OnceClosure callback_;
   base::WeakPtrFactory<ShaderClearHelper> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(ShaderClearHelper);
 };
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/gpu/ipc/host/shader_disk_cache.h b/gpu/ipc/host/shader_disk_cache.h
index d723ce29..1057ebf7 100644
--- a/gpu/ipc/host/shader_disk_cache.h
+++ b/gpu/ipc/host/shader_disk_cache.h
@@ -109,6 +109,10 @@
 class ShaderCacheFactory : public base::ThreadChecker {
  public:
   ShaderCacheFactory();
+
+  ShaderCacheFactory(const ShaderCacheFactory&) = delete;
+  ShaderCacheFactory& operator=(const ShaderCacheFactory&) = delete;
+
   ~ShaderCacheFactory();
 
   // Clear the shader disk cache for the given |path|. This supports unbounded
@@ -157,8 +161,6 @@
   using ShaderClearQueue = base::queue<std::unique_ptr<ShaderClearHelper>>;
   using ShaderClearMap = std::map<base::FilePath, ShaderClearQueue>;
   ShaderClearMap shader_clear_map_;
-
-  DISALLOW_COPY_AND_ASSIGN(ShaderCacheFactory);
 };
 
 }  // namespace gpu
diff --git a/gpu/ipc/host/shader_disk_cache_unittest.cc b/gpu/ipc/host/shader_disk_cache_unittest.cc
index e0456b9..056d651 100644
--- a/gpu/ipc/host/shader_disk_cache_unittest.cc
+++ b/gpu/ipc/host/shader_disk_cache_unittest.cc
@@ -26,6 +26,9 @@
  public:
   ShaderDiskCacheTest() = default;
 
+  ShaderDiskCacheTest(const ShaderDiskCacheTest&) = delete;
+  ShaderDiskCacheTest& operator=(const ShaderDiskCacheTest&) = delete;
+
   ~ShaderDiskCacheTest() override = default;
 
   const base::FilePath& cache_path() { return temp_dir_.GetPath(); }
@@ -50,8 +53,6 @@
   base::test::TaskEnvironment task_environment_;
   base::ScopedTempDir temp_dir_;
   ShaderCacheFactory factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(ShaderDiskCacheTest);
 };
 
 TEST_F(ShaderDiskCacheTest, ClearsCache) {
diff --git a/gpu/ipc/in_process_command_buffer.h b/gpu/ipc/in_process_command_buffer.h
index 274d08f..b5d9692 100644
--- a/gpu/ipc/in_process_command_buffer.h
+++ b/gpu/ipc/in_process_command_buffer.h
@@ -106,6 +106,10 @@
  public:
   InProcessCommandBuffer(CommandBufferTaskExecutor* task_executor,
                          const GURL& active_url);
+
+  InProcessCommandBuffer(const InProcessCommandBuffer&) = delete;
+  InProcessCommandBuffer& operator=(const InProcessCommandBuffer&) = delete;
+
   ~InProcessCommandBuffer() override;
 
   // If |surface| is not null, use it directly; in this case, the command
@@ -451,8 +455,6 @@
       this};
   base::WeakPtrFactory<InProcessCommandBuffer> gpu_thread_weak_ptr_factory_{
       this};
-
-  DISALLOW_COPY_AND_ASSIGN(InProcessCommandBuffer);
 };
 
 }  // namespace gpu
diff --git a/gpu/ipc/in_process_gpu_thread_holder.h b/gpu/ipc/in_process_gpu_thread_holder.h
index 1762e54..64dc63f 100644
--- a/gpu/ipc/in_process_gpu_thread_holder.h
+++ b/gpu/ipc/in_process_gpu_thread_holder.h
@@ -32,6 +32,10 @@
       public GpuInProcessThreadServiceDelegate {
  public:
   InProcessGpuThreadHolder();
+
+  InProcessGpuThreadHolder(const InProcessGpuThreadHolder&) = delete;
+  InProcessGpuThreadHolder& operator=(const InProcessGpuThreadHolder&) = delete;
+
   ~InProcessGpuThreadHolder() override;
 
   // Returns GpuPreferences that can be modified before GetTaskExecutor() is
@@ -67,8 +71,6 @@
   std::unique_ptr<MailboxManager> mailbox_manager_;
   std::unique_ptr<SharedImageManager> shared_image_manager_;
   std::unique_ptr<CommandBufferTaskExecutor> task_executor_;
-
-  DISALLOW_COPY_AND_ASSIGN(InProcessGpuThreadHolder);
 };
 
 }  // namespace gpu
diff --git a/gpu/ipc/raster_in_process_context.h b/gpu/ipc/raster_in_process_context.h
index 531c2f8..9f0d848f 100644
--- a/gpu/ipc/raster_in_process_context.h
+++ b/gpu/ipc/raster_in_process_context.h
@@ -32,6 +32,10 @@
 class RasterInProcessContext {
  public:
   RasterInProcessContext();
+
+  RasterInProcessContext(const RasterInProcessContext&) = delete;
+  RasterInProcessContext& operator=(const RasterInProcessContext&) = delete;
+
   ~RasterInProcessContext();
 
   // |attrib_list| must be null or a NONE-terminated list of attribute/value
@@ -72,8 +76,6 @@
   std::unique_ptr<TransferBuffer> transfer_buffer_;
   std::unique_ptr<raster::RasterImplementation> raster_implementation_;
   std::unique_ptr<InProcessCommandBuffer> command_buffer_;
-
-  DISALLOW_COPY_AND_ASSIGN(RasterInProcessContext);
 };
 
 }  // namespace gpu
diff --git a/gpu/ipc/scheduler_sequence.h b/gpu/ipc/scheduler_sequence.h
index effb371e..88ef2f1 100644
--- a/gpu/ipc/scheduler_sequence.h
+++ b/gpu/ipc/scheduler_sequence.h
@@ -32,6 +32,10 @@
 // is used for a thread.
 class GL_IN_PROCESS_CONTEXT_EXPORT ScopedAllowScheduleGpuTask {
  public:
+  ScopedAllowScheduleGpuTask(const ScopedAllowScheduleGpuTask&) = delete;
+  ScopedAllowScheduleGpuTask& operator=(const ScopedAllowScheduleGpuTask&) =
+      delete;
+
   ~ScopedAllowScheduleGpuTask();
 
  private:
@@ -51,7 +55,6 @@
 #if DCHECK_IS_ON()
   const bool original_value_;
 #endif
-  DISALLOW_COPY_AND_ASSIGN(ScopedAllowScheduleGpuTask);
 };
 
 // SingleTaskSequence implementation that uses gpu scheduler sequences.
@@ -66,6 +69,9 @@
   SchedulerSequence(Scheduler* scheduler,
                     scoped_refptr<base::SingleThreadTaskRunner> task_runner);
 
+  SchedulerSequence(const SchedulerSequence&) = delete;
+  SchedulerSequence& operator=(const SchedulerSequence&) = delete;
+
   // Note: this drops tasks not executed yet.
   ~SchedulerSequence() override;
 
@@ -85,8 +91,6 @@
  private:
   Scheduler* const scheduler_;
   const SequenceId sequence_id_;
-
-  DISALLOW_COPY_AND_ASSIGN(SchedulerSequence);
 };
 
 }  // namespace gpu
diff --git a/gpu/ipc/service/command_buffer_stub.cc b/gpu/ipc/service/command_buffer_stub.cc
index a0a6f42..37eb5ffd 100644
--- a/gpu/ipc/service/command_buffer_stub.cc
+++ b/gpu/ipc/service/command_buffer_stub.cc
@@ -78,6 +78,10 @@
  public:
   static std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
   CreateForChannel(GpuChannel* channel);
+
+  DevToolsChannelData(const DevToolsChannelData&) = delete;
+  DevToolsChannelData& operator=(const DevToolsChannelData&) = delete;
+
   ~DevToolsChannelData() override = default;
 
   void AppendAsTraceFormat(std::string* out) const override {
@@ -89,7 +93,6 @@
  private:
   explicit DevToolsChannelData(base::Value* value) : value_(value) {}
   std::unique_ptr<base::Value> value_;
-  DISALLOW_COPY_AND_ASSIGN(DevToolsChannelData);
 };
 
 std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
diff --git a/gpu/ipc/service/gles2_command_buffer_stub.h b/gpu/ipc/service/gles2_command_buffer_stub.h
index e3883af5..887c17f 100644
--- a/gpu/ipc/service/gles2_command_buffer_stub.h
+++ b/gpu/ipc/service/gles2_command_buffer_stub.h
@@ -28,6 +28,9 @@
                          int32_t stream_id,
                          int32_t route_id);
 
+  GLES2CommandBufferStub(const GLES2CommandBufferStub&) = delete;
+  GLES2CommandBufferStub& operator=(const GLES2CommandBufferStub&) = delete;
+
   ~GLES2CommandBufferStub() override;
 
   // This must leave the GL context associated with the newly-created
@@ -86,8 +89,6 @@
   base::circular_deque<SwapBufferParams> pending_swap_completed_params_;
 
   base::WeakPtrFactory<GLES2CommandBufferStub> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(GLES2CommandBufferStub);
 };
 
 }  // namespace gpu
diff --git a/gpu/ipc/service/gpu_channel_manager.h b/gpu/ipc/service/gpu_channel_manager.h
index 5faecb6..dcac9c1 100644
--- a/gpu/ipc/service/gpu_channel_manager.h
+++ b/gpu/ipc/service/gpu_channel_manager.h
@@ -101,6 +101,10 @@
       viz::VulkanContextProvider* vulkan_context_provider = nullptr,
       viz::MetalContextProvider* metal_context_provider = nullptr,
       viz::DawnContextProvider* dawn_context_provider = nullptr);
+
+  GpuChannelManager(const GpuChannelManager&) = delete;
+  GpuChannelManager& operator=(const GpuChannelManager&) = delete;
+
   ~GpuChannelManager() override;
 
   GpuChannelManagerDelegate* delegate() const { return delegate_; }
@@ -228,6 +232,10 @@
     GpuPeakMemoryMonitor(
         GpuChannelManager* channel_manager,
         scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+
+    GpuPeakMemoryMonitor(const GpuPeakMemoryMonitor&) = delete;
+    GpuPeakMemoryMonitor& operator=(const GpuPeakMemoryMonitor&) = delete;
+
     ~GpuPeakMemoryMonitor() override;
 
     base::flat_map<GpuPeakMemoryAllocationSource, uint64_t> GetPeakMemoryUsage(
@@ -277,7 +285,6 @@
 
     std::unique_ptr<GpuMemoryAblationExperiment> ablation_experiment_;
     base::WeakPtrFactory<GpuPeakMemoryMonitor> weak_factory_;
-    DISALLOW_COPY_AND_ASSIGN(GpuPeakMemoryMonitor);
   };
 
   void InternalDestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id, int client_id);
@@ -379,8 +386,6 @@
   // that any WeakPtrs to Controller are invalidated before its members
   // variable's destructors are executed, rendering them invalid.
   base::WeakPtrFactory<GpuChannelManager> weak_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(GpuChannelManager);
 };
 
 }  // namespace gpu
diff --git a/gpu/ipc/service/gpu_channel_test_common.cc b/gpu/ipc/service/gpu_channel_test_common.cc
index 22bba9d..795f429d 100644
--- a/gpu/ipc/service/gpu_channel_test_common.cc
+++ b/gpu/ipc/service/gpu_channel_test_common.cc
@@ -33,6 +33,11 @@
 class TestGpuChannelManagerDelegate : public GpuChannelManagerDelegate {
  public:
   TestGpuChannelManagerDelegate(Scheduler* scheduler) : scheduler_(scheduler) {}
+
+  TestGpuChannelManagerDelegate(const TestGpuChannelManagerDelegate&) = delete;
+  TestGpuChannelManagerDelegate& operator=(
+      const TestGpuChannelManagerDelegate&) = delete;
+
   ~TestGpuChannelManagerDelegate() override = default;
 
   // GpuChannelManagerDelegate implementation:
@@ -64,8 +69,6 @@
  private:
   bool is_exiting_ = false;
   Scheduler* const scheduler_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestGpuChannelManagerDelegate);
 };
 
 GpuChannelTestCommon::GpuChannelTestCommon(bool use_stub_bindings)
diff --git a/gpu/ipc/service/gpu_channel_test_common.h b/gpu/ipc/service/gpu_channel_test_common.h
index f4e1bda..f09406f 100644
--- a/gpu/ipc/service/gpu_channel_test_common.h
+++ b/gpu/ipc/service/gpu_channel_test_common.h
@@ -37,6 +37,10 @@
   // Constructor which allows a custom set of GPU driver bug workarounds.
   GpuChannelTestCommon(std::vector<int32_t> enabled_workarounds,
                        bool use_stub_bindings);
+
+  GpuChannelTestCommon(const GpuChannelTestCommon&) = delete;
+  GpuChannelTestCommon& operator=(const GpuChannelTestCommon&) = delete;
+
   ~GpuChannelTestCommon() override;
 
  protected:
@@ -63,8 +67,6 @@
   std::unique_ptr<Scheduler> scheduler_;
   std::unique_ptr<TestGpuChannelManagerDelegate> channel_manager_delegate_;
   std::unique_ptr<GpuChannelManager> channel_manager_;
-
-  DISALLOW_COPY_AND_ASSIGN(GpuChannelTestCommon);
 };
 
 }  // namespace gpu
diff --git a/gpu/ipc/service/gpu_init.h b/gpu/ipc/service/gpu_init.h
index 764860f..7ae1354 100644
--- a/gpu/ipc/service/gpu_init.h
+++ b/gpu/ipc/service/gpu_init.h
@@ -43,6 +43,10 @@
 class GPU_IPC_SERVICE_EXPORT GpuInit {
  public:
   GpuInit();
+
+  GpuInit(const GpuInit&) = delete;
+  GpuInit& operator=(const GpuInit&) = delete;
+
   ~GpuInit();
 
   void set_sandbox_helper(GpuSandboxHelper* helper) {
@@ -111,8 +115,6 @@
 
   void SaveHardwareGpuInfoAndGpuFeatureInfo();
   void AdjustInfoToSwiftShader();
-
-  DISALLOW_COPY_AND_ASSIGN(GpuInit);
 };
 
 }  // namespace gpu
diff --git a/gpu/ipc/service/gpu_memory_buffer_factory.h b/gpu/ipc/service/gpu_memory_buffer_factory.h
index 9a88a29..a66d26d 100644
--- a/gpu/ipc/service/gpu_memory_buffer_factory.h
+++ b/gpu/ipc/service/gpu_memory_buffer_factory.h
@@ -26,6 +26,9 @@
 
 class GPU_IPC_SERVICE_EXPORT GpuMemoryBufferFactory {
  public:
+  GpuMemoryBufferFactory(const GpuMemoryBufferFactory&) = delete;
+  GpuMemoryBufferFactory& operator=(const GpuMemoryBufferFactory&) = delete;
+
   virtual ~GpuMemoryBufferFactory() = default;
 
   // Creates a new factory instance for native GPU memory buffers. Returns null
@@ -78,9 +81,6 @@
 
  protected:
   GpuMemoryBufferFactory() = default;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferFactory);
 };
 
 }  // namespace gpu
diff --git a/gpu/ipc/service/gpu_memory_buffer_factory_android_hardware_buffer.h b/gpu/ipc/service/gpu_memory_buffer_factory_android_hardware_buffer.h
index 9e3b04e..ca8e4827 100644
--- a/gpu/ipc/service/gpu_memory_buffer_factory_android_hardware_buffer.h
+++ b/gpu/ipc/service/gpu_memory_buffer_factory_android_hardware_buffer.h
@@ -26,6 +26,12 @@
       public ImageFactory {
  public:
   GpuMemoryBufferFactoryAndroidHardwareBuffer();
+
+  GpuMemoryBufferFactoryAndroidHardwareBuffer(
+      const GpuMemoryBufferFactoryAndroidHardwareBuffer&) = delete;
+  GpuMemoryBufferFactoryAndroidHardwareBuffer& operator=(
+      const GpuMemoryBufferFactoryAndroidHardwareBuffer&) = delete;
+
   ~GpuMemoryBufferFactoryAndroidHardwareBuffer() override;
 
   // Overridden from GpuMemoryBufferFactory:
@@ -68,8 +74,6 @@
 
   base::Lock lock_;
   BufferMap buffer_map_ GUARDED_BY(lock_);
-
-  DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferFactoryAndroidHardwareBuffer);
 };
 
 }  // namespace gpu
diff --git a/gpu/ipc/service/gpu_memory_buffer_factory_io_surface.h b/gpu/ipc/service/gpu_memory_buffer_factory_io_surface.h
index 0e6d373..585be46 100644
--- a/gpu/ipc/service/gpu_memory_buffer_factory_io_surface.h
+++ b/gpu/ipc/service/gpu_memory_buffer_factory_io_surface.h
@@ -32,6 +32,12 @@
       public ImageFactory {
  public:
   GpuMemoryBufferFactoryIOSurface();
+
+  GpuMemoryBufferFactoryIOSurface(const GpuMemoryBufferFactoryIOSurface&) =
+      delete;
+  GpuMemoryBufferFactoryIOSurface& operator=(
+      const GpuMemoryBufferFactoryIOSurface&) = delete;
+
   ~GpuMemoryBufferFactoryIOSurface() override;
 
   // Overridden from GpuMemoryBufferFactory:
@@ -76,8 +82,6 @@
   // used with any GPU process by passing a mach_port to CreateImageCHROMIUM.
   IOSurfaceMap io_surfaces_;
   base::Lock io_surfaces_lock_;
-
-  DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferFactoryIOSurface);
 };
 
 }  // namespace gpu
diff --git a/gpu/ipc/service/gpu_memory_buffer_factory_native_pixmap.h b/gpu/ipc/service/gpu_memory_buffer_factory_native_pixmap.h
index 2973e04..db21802 100644
--- a/gpu/ipc/service/gpu_memory_buffer_factory_native_pixmap.h
+++ b/gpu/ipc/service/gpu_memory_buffer_factory_native_pixmap.h
@@ -31,6 +31,12 @@
   GpuMemoryBufferFactoryNativePixmap();
   explicit GpuMemoryBufferFactoryNativePixmap(
       viz::VulkanContextProvider* vulkan_context_provider);
+
+  GpuMemoryBufferFactoryNativePixmap(
+      const GpuMemoryBufferFactoryNativePixmap&) = delete;
+  GpuMemoryBufferFactoryNativePixmap& operator=(
+      const GpuMemoryBufferFactoryNativePixmap&) = delete;
+
   ~GpuMemoryBufferFactoryNativePixmap() override;
 
   // Overridden from GpuMemoryBufferFactory:
@@ -106,8 +112,6 @@
   base::Lock native_pixmaps_lock_;
 
   base::WeakPtrFactory<GpuMemoryBufferFactoryNativePixmap> weak_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferFactoryNativePixmap);
 };
 
 }  // namespace gpu
diff --git a/gpu/ipc/service/gpu_watchdog_thread.h b/gpu/ipc/service/gpu_watchdog_thread.h
index 621da92..b7ce614 100644
--- a/gpu/ipc/service/gpu_watchdog_thread.h
+++ b/gpu/ipc/service/gpu_watchdog_thread.h
@@ -94,6 +94,9 @@
       bool test_mode,
       const std::string& thread_name);
 
+  GpuWatchdogThread(const GpuWatchdogThread&) = delete;
+  GpuWatchdogThread& operator=(const GpuWatchdogThread&) = delete;
+
   ~GpuWatchdogThread() override;
 
   // Notifies the watchdog when Chrome is backgrounded / foregrounded. Should
@@ -313,8 +316,6 @@
 
   base::WeakPtr<GpuWatchdogThread> weak_ptr_;
   base::WeakPtrFactory<GpuWatchdogThread> weak_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(GpuWatchdogThread);
 };
 
 }  // namespace gpu
diff --git a/gpu/ipc/service/image_decode_accelerator_stub_unittest.cc b/gpu/ipc/service/image_decode_accelerator_stub_unittest.cc
index fdf64976..847bdabe 100644
--- a/gpu/ipc/service/image_decode_accelerator_stub_unittest.cc
+++ b/gpu/ipc/service/image_decode_accelerator_stub_unittest.cc
@@ -243,6 +243,12 @@
   ImageDecodeAcceleratorStubTest()
       : GpuChannelTestCommon(false /* use_stub_bindings */),
         image_decode_accelerator_worker_(GetParam()) {}
+
+  ImageDecodeAcceleratorStubTest(const ImageDecodeAcceleratorStubTest&) =
+      delete;
+  ImageDecodeAcceleratorStubTest& operator=(
+      const ImageDecodeAcceleratorStubTest&) = delete;
+
   ~ImageDecodeAcceleratorStubTest() override = default;
 
   SyncPointManager* sync_point_manager() const {
@@ -653,8 +659,6 @@
   TestImageFactory image_factory_;
   base::test::ScopedFeatureList feature_list_;
   base::WeakPtrFactory<ImageDecodeAcceleratorStubTest> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(ImageDecodeAcceleratorStubTest);
 };
 
 // Tests the following flow: two decode requests are sent. One of the decodes is
diff --git a/gpu/ipc/service/raster_command_buffer_stub.h b/gpu/ipc/service/raster_command_buffer_stub.h
index 57b53b5..207bc6a8 100644
--- a/gpu/ipc/service/raster_command_buffer_stub.h
+++ b/gpu/ipc/service/raster_command_buffer_stub.h
@@ -18,6 +18,10 @@
                           SequenceId sequence_id,
                           int32_t stream_id,
                           int32_t route_id);
+
+  RasterCommandBufferStub(const RasterCommandBufferStub&) = delete;
+  RasterCommandBufferStub& operator=(const RasterCommandBufferStub&) = delete;
+
   ~RasterCommandBufferStub() override;
 
   // This must leave the GL context associated with the newly-created
@@ -32,8 +36,6 @@
  private:
   void OnSwapBuffers(uint64_t swap_id, uint32_t flags) override;
   void SetActiveURL(GURL url) override;
-
-  DISALLOW_COPY_AND_ASSIGN(RasterCommandBufferStub);
 };
 
 }  // namespace gpu
diff --git a/gpu/ipc/service/shared_image_stub.cc b/gpu/ipc/service/shared_image_stub.cc
index fc82505..7999ff9 100644
--- a/gpu/ipc/service/shared_image_stub.cc
+++ b/gpu/ipc/service/shared_image_stub.cc
@@ -123,6 +123,12 @@
           std::move(request->get_create_shared_image_video_planes()));
       break;
 
+    case mojom::DeferredSharedImageRequest::Tag::kCopyToGpuMemoryBuffer: {
+      auto& params = *request->get_copy_to_gpu_memory_buffer();
+      OnCopyToGpuMemoryBuffer(params.mailbox, params.release_id);
+      break;
+    }
+
     case mojom::DeferredSharedImageRequest::Tag::kCreateSwapChain:
       OnCreateSwapChain(std::move(request->get_create_swap_chain()));
       break;
@@ -404,6 +410,26 @@
   sync_point_client_state_->ReleaseFenceSync(params->release_id);
 }
 
+void SharedImageStub::OnCopyToGpuMemoryBuffer(const Mailbox& mailbox,
+                                              uint32_t release_id) {
+  if (!mailbox.IsSharedImage()) {
+    DLOG(ERROR) << "SharedImageStub: Trying to access a SharedImage with a "
+                   "non-SharedImage mailbox.";
+    OnError();
+    return;
+  }
+  if (!MakeContextCurrent()) {
+    OnError();
+    return;
+  }
+  if (!factory_->CopyToGpuMemoryBuffer(mailbox)) {
+    DLOG(ERROR) << "SharedImageStub: Unable to update shared GMB";
+    OnError();
+    return;
+  }
+  sync_point_client_state_->ReleaseFenceSync(release_id);
+}
+
 void SharedImageStub::OnCreateSwapChain(
     mojom::CreateSwapChainParamsPtr params) {
   TRACE_EVENT0("gpu", "SharedImageStub::OnCreateSwapChain");
diff --git a/gpu/ipc/service/shared_image_stub.h b/gpu/ipc/service/shared_image_stub.h
index c6f3708..13fe755 100644
--- a/gpu/ipc/service/shared_image_stub.h
+++ b/gpu/ipc/service/shared_image_stub.h
@@ -106,6 +106,7 @@
 #if defined(OS_WIN)
   void OnCreateSharedImageVideoPlanes(
       mojom::CreateSharedImageVideoPlanesParamsPtr params);
+  void OnCopyToGpuMemoryBuffer(const Mailbox& mailbox, uint32_t release_id);
   void OnCreateSwapChain(mojom::CreateSwapChainParamsPtr params);
   void OnPresentSwapChain(const Mailbox& mailbox, uint32_t release_id);
 #endif  // OS_WIN
diff --git a/gpu/ipc/service/webgpu_command_buffer_stub.h b/gpu/ipc/service/webgpu_command_buffer_stub.h
index 023fbf81..7b6bfb9 100644
--- a/gpu/ipc/service/webgpu_command_buffer_stub.h
+++ b/gpu/ipc/service/webgpu_command_buffer_stub.h
@@ -18,6 +18,10 @@
                           SequenceId sequence_id,
                           int32_t stream_id,
                           int32_t route_id);
+
+  WebGPUCommandBufferStub(const WebGPUCommandBufferStub&) = delete;
+  WebGPUCommandBufferStub& operator=(const WebGPUCommandBufferStub&) = delete;
+
   ~WebGPUCommandBufferStub() override;
 
   // This must leave the GL context associated with the newly-created
@@ -31,8 +35,6 @@
 
  private:
   void OnSwapBuffers(uint64_t swap_id, uint32_t flags) override;
-
-  DISALLOW_COPY_AND_ASSIGN(WebGPUCommandBufferStub);
 };
 
 }  // namespace gpu
diff --git a/gpu/ipc/shared_image_interface_in_process.h b/gpu/ipc/shared_image_interface_in_process.h
index 044dd48..ca15044 100644
--- a/gpu/ipc/shared_image_interface_in_process.h
+++ b/gpu/ipc/shared_image_interface_in_process.h
@@ -33,6 +33,11 @@
       SingleTaskSequence* task_sequence,
       DisplayCompositorMemoryAndTaskControllerOnGpu* display_controller,
       std::unique_ptr<CommandBufferHelper> command_buffer_helper);
+
+  SharedImageInterfaceInProcess(const SharedImageInterfaceInProcess&) = delete;
+  SharedImageInterfaceInProcess& operator=(
+      const SharedImageInterfaceInProcess&) = delete;
+
   ~SharedImageInterfaceInProcess() override;
 
   // The |SharedImageInterface| keeps ownership of the image until
@@ -235,8 +240,6 @@
   SyncPointManager* sync_point_manager_;
   scoped_refptr<SyncPointClientState> sync_point_client_state_;
   std::unique_ptr<SharedImageFactory> shared_image_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(SharedImageInterfaceInProcess);
 };
 
 }  // namespace gpu
diff --git a/gpu/ipc/webgpu_in_process_context.h b/gpu/ipc/webgpu_in_process_context.h
index b2097200..70dcabb5 100644
--- a/gpu/ipc/webgpu_in_process_context.h
+++ b/gpu/ipc/webgpu_in_process_context.h
@@ -33,6 +33,10 @@
 class WebGPUInProcessContext {
  public:
   WebGPUInProcessContext();
+
+  WebGPUInProcessContext(const WebGPUInProcessContext&) = delete;
+  WebGPUInProcessContext& operator=(const WebGPUInProcessContext&) = delete;
+
   ~WebGPUInProcessContext();
 
   // |attrib_list| must be null or a NONE-terminated list of attribute/value
@@ -64,8 +68,6 @@
   std::unique_ptr<webgpu::WebGPUImplementation> webgpu_implementation_;
   std::unique_ptr<InProcessCommandBuffer> command_buffer_;
   scoped_refptr<base::TestSimpleTaskRunner> client_task_runner_;
-
-  DISALLOW_COPY_AND_ASSIGN(WebGPUInProcessContext);
 };
 
 }  // namespace gpu
diff --git a/gpu/skia_bindings/grcontext_for_gles2_interface.h b/gpu/skia_bindings/grcontext_for_gles2_interface.h
index 2f5431141..bd6b478 100644
--- a/gpu/skia_bindings/grcontext_for_gles2_interface.h
+++ b/gpu/skia_bindings/grcontext_for_gles2_interface.h
@@ -30,6 +30,10 @@
                                       size_t max_resource_cache_bytes,
                                       size_t max_glyph_cache_texture_bytes);
 
+  GrContextForGLES2Interface(const GrContextForGLES2Interface&) = delete;
+  GrContextForGLES2Interface& operator=(const GrContextForGLES2Interface&) =
+      delete;
+
   ~GrContextForGLES2Interface() override;
 
   // Handles Skia-reported shader compilation errors.
@@ -43,8 +47,6 @@
  private:
   sk_sp<class GrDirectContext> gr_context_;
   gpu::ContextSupport* context_support_;
-
-  DISALLOW_COPY_AND_ASSIGN(GrContextForGLES2Interface);
 };
 
 }  // namespace skia_bindings
diff --git a/gpu/skia_bindings/grcontext_for_webgpu_interface.h b/gpu/skia_bindings/grcontext_for_webgpu_interface.h
index 188ca88..26e15af 100644
--- a/gpu/skia_bindings/grcontext_for_webgpu_interface.h
+++ b/gpu/skia_bindings/grcontext_for_webgpu_interface.h
@@ -32,6 +32,10 @@
                               size_t max_resource_cache_bytes,
                               size_t max_glyph_cache_texture_bytes);
 
+  GrContextForWebGPUInterface(const GrContextForWebGPUInterface&) = delete;
+  GrContextForWebGPUInterface& operator=(const GrContextForWebGPUInterface&) =
+      delete;
+
   ~GrContextForWebGPUInterface() override;
 
   // GrContextOptions::ShaderErrorHandler implementation
@@ -43,8 +47,6 @@
  private:
   sk_sp<class GrDirectContext> gr_context_;
   gpu::ContextSupport* context_support_;
-
-  DISALLOW_COPY_AND_ASSIGN(GrContextForWebGPUInterface);
 };
 
 }  // namespace skia_bindings
diff --git a/gpu/vulkan/android/vulkan_implementation_android.h b/gpu/vulkan/android/vulkan_implementation_android.h
index 6c7568b..52b7c27 100644
--- a/gpu/vulkan/android/vulkan_implementation_android.h
+++ b/gpu/vulkan/android/vulkan_implementation_android.h
@@ -19,6 +19,11 @@
     : public VulkanImplementation {
  public:
   VulkanImplementationAndroid();
+
+  VulkanImplementationAndroid(const VulkanImplementationAndroid&) = delete;
+  VulkanImplementationAndroid& operator=(const VulkanImplementationAndroid&) =
+      delete;
+
   ~VulkanImplementationAndroid() override;
 
   // VulkanImplementation:
@@ -56,8 +61,6 @@
 
  private:
   VulkanInstance vulkan_instance_;
-
-  DISALLOW_COPY_AND_ASSIGN(VulkanImplementationAndroid);
 };
 
 }  // namespace gpu
diff --git a/gpu/vulkan/init/gr_vk_memory_allocator_impl.cc b/gpu/vulkan/init/gr_vk_memory_allocator_impl.cc
index 07d7042..2fe87c1 100644
--- a/gpu/vulkan/init/gr_vk_memory_allocator_impl.cc
+++ b/gpu/vulkan/init/gr_vk_memory_allocator_impl.cc
@@ -47,7 +47,9 @@
     }
 
     if (AllocationPropertyFlags::kLazyAllocation & flags) {
-      info.preferredFlags |= VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT;
+      // If the caller asked for lazy allocation then they already set up the
+      // VkImage for it so we must require the lazy property.
+      info.requiredFlags |= VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT;
     }
 
     if (AllocationPropertyFlags::kProtected & flags) {
@@ -144,6 +146,9 @@
     if (!SkToBool(VK_MEMORY_PROPERTY_HOST_COHERENT_BIT & mem_flags)) {
       flags |= GrVkAlloc::kNoncoherent_Flag;
     }
+    if (VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT & mem_flags) {
+      flags |= GrVkAlloc::kLazilyAllocated_Flag;
+    }
 
     alloc->fMemory = vma_info.deviceMemory;
     alloc->fOffset = vma_info.offset;
diff --git a/gpu/vulkan/semaphore_handle.h b/gpu/vulkan/semaphore_handle.h
index 9927d12..47058d1 100644
--- a/gpu/vulkan/semaphore_handle.h
+++ b/gpu/vulkan/semaphore_handle.h
@@ -45,6 +45,9 @@
                   PlatformHandle handle);
   SemaphoreHandle(SemaphoreHandle&&);
 
+  SemaphoreHandle(const SemaphoreHandle&) = delete;
+  SemaphoreHandle& operator=(const SemaphoreHandle&) = delete;
+
   ~SemaphoreHandle();
 
   SemaphoreHandle& operator=(SemaphoreHandle&&);
@@ -68,8 +71,6 @@
  private:
   VkExternalSemaphoreHandleTypeFlagBits type_;
   PlatformHandle handle_;
-
-  DISALLOW_COPY_AND_ASSIGN(SemaphoreHandle);
 };
 
 }  // namespace gpu
diff --git a/gpu/vulkan/vulkan_command_buffer.h b/gpu/vulkan/vulkan_command_buffer.h
index f6e2b6f..6e1da39 100644
--- a/gpu/vulkan/vulkan_command_buffer.h
+++ b/gpu/vulkan/vulkan_command_buffer.h
@@ -22,6 +22,10 @@
   VulkanCommandBuffer(VulkanDeviceQueue* device_queue,
                       VulkanCommandPool* command_pool,
                       bool primary);
+
+  VulkanCommandBuffer(const VulkanCommandBuffer&) = delete;
+  VulkanCommandBuffer& operator=(const VulkanCommandBuffer&) = delete;
+
   ~VulkanCommandBuffer();
 
   bool Initialize();
@@ -96,8 +100,6 @@
   VulkanCommandPool* command_pool_;
   VkCommandBuffer command_buffer_ = VK_NULL_HANDLE;
   VulkanFenceHelper::FenceHandle submission_fence_;
-
-  DISALLOW_COPY_AND_ASSIGN(VulkanCommandBuffer);
 };
 
 class COMPONENT_EXPORT(VULKAN) CommandBufferRecorderBase {
@@ -135,20 +137,26 @@
     : public CommandBufferRecorderBase {
  public:
   ScopedMultiUseCommandBufferRecorder(VulkanCommandBuffer& command_buffer);
-  ~ScopedMultiUseCommandBufferRecorder() override {}
 
- private:
-  DISALLOW_COPY_AND_ASSIGN(ScopedMultiUseCommandBufferRecorder);
+  ScopedMultiUseCommandBufferRecorder(
+      const ScopedMultiUseCommandBufferRecorder&) = delete;
+  ScopedMultiUseCommandBufferRecorder& operator=(
+      const ScopedMultiUseCommandBufferRecorder&) = delete;
+
+  ~ScopedMultiUseCommandBufferRecorder() override {}
 };
 
 class COMPONENT_EXPORT(VULKAN) ScopedSingleUseCommandBufferRecorder
     : public CommandBufferRecorderBase {
  public:
   ScopedSingleUseCommandBufferRecorder(VulkanCommandBuffer& command_buffer);
-  ~ScopedSingleUseCommandBufferRecorder() override {}
 
- private:
-  DISALLOW_COPY_AND_ASSIGN(ScopedSingleUseCommandBufferRecorder);
+  ScopedSingleUseCommandBufferRecorder(
+      const ScopedSingleUseCommandBufferRecorder&) = delete;
+  ScopedSingleUseCommandBufferRecorder& operator=(
+      const ScopedSingleUseCommandBufferRecorder&) = delete;
+
+  ~ScopedSingleUseCommandBufferRecorder() override {}
 };
 
 }  // namespace gpu
diff --git a/gpu/vulkan/vulkan_command_pool.h b/gpu/vulkan/vulkan_command_pool.h
index ef0ce810..ec2175f 100644
--- a/gpu/vulkan/vulkan_command_pool.h
+++ b/gpu/vulkan/vulkan_command_pool.h
@@ -20,6 +20,10 @@
 class COMPONENT_EXPORT(VULKAN) VulkanCommandPool {
  public:
   explicit VulkanCommandPool(VulkanDeviceQueue* device_queue);
+
+  VulkanCommandPool(const VulkanCommandPool&) = delete;
+  VulkanCommandPool& operator=(const VulkanCommandPool&) = delete;
+
   ~VulkanCommandPool();
 
   bool Initialize();
@@ -41,8 +45,6 @@
   VkCommandPool handle_ = VK_NULL_HANDLE;
   uint32_t command_buffer_count_ = 0;
   bool use_protected_memory_ = false;
-
-  DISALLOW_COPY_AND_ASSIGN(VulkanCommandPool);
 };
 
 }  // namespace gpu
diff --git a/gpu/vulkan/vulkan_device_queue.h b/gpu/vulkan/vulkan_device_queue.h
index 49477790..c7a57ce 100644
--- a/gpu/vulkan/vulkan_device_queue.h
+++ b/gpu/vulkan/vulkan_device_queue.h
@@ -32,6 +32,10 @@
   };
 
   explicit VulkanDeviceQueue(VkInstance vk_instance);
+
+  VulkanDeviceQueue(const VulkanDeviceQueue&) = delete;
+  VulkanDeviceQueue& operator=(const VulkanDeviceQueue&) = delete;
+
   ~VulkanDeviceQueue();
 
   using GetPresentationSupportCallback =
@@ -127,8 +131,6 @@
 #endif  // defined(OS_ANDROID) || defined(OS_FUCHSIA)
 
   VkPhysicalDeviceProtectedMemoryFeatures protected_memory_features_;
-
-  DISALLOW_COPY_AND_ASSIGN(VulkanDeviceQueue);
 };
 
 }  // namespace gpu
diff --git a/gpu/vulkan/vulkan_fence_helper.h b/gpu/vulkan/vulkan_fence_helper.h
index f08e010..0bbc64d 100644
--- a/gpu/vulkan/vulkan_fence_helper.h
+++ b/gpu/vulkan/vulkan_fence_helper.h
@@ -26,6 +26,10 @@
 class COMPONENT_EXPORT(VULKAN) VulkanFenceHelper {
  public:
   explicit VulkanFenceHelper(VulkanDeviceQueue* device_queue);
+
+  VulkanFenceHelper(const VulkanFenceHelper&) = delete;
+  VulkanFenceHelper& operator=(const VulkanFenceHelper&) = delete;
+
   ~VulkanFenceHelper();
 
   // Destroy the fence helper.
@@ -146,8 +150,6 @@
   base::circular_deque<TasksForFence> cleanup_tasks_;
 
   base::WeakPtrFactory<VulkanFenceHelper> weak_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(VulkanFenceHelper);
 };
 
 template <typename T>
diff --git a/gpu/vulkan/vulkan_implementation.h b/gpu/vulkan/vulkan_implementation.h
index 72586d0..c57ee0b3 100644
--- a/gpu/vulkan/vulkan_implementation.h
+++ b/gpu/vulkan/vulkan_implementation.h
@@ -52,6 +52,9 @@
   explicit VulkanImplementation(bool use_swiftshader = false,
                                 bool allow_protected_memory = false);
 
+  VulkanImplementation(const VulkanImplementation&) = delete;
+  VulkanImplementation& operator=(const VulkanImplementation&) = delete;
+
   virtual ~VulkanImplementation();
 
   // Initialize VulkanInstance. If using_surface, VK_KHR_surface instance
@@ -146,7 +149,6 @@
  private:
   const bool use_swiftshader_;
   const bool allow_protected_memory_;
-  DISALLOW_COPY_AND_ASSIGN(VulkanImplementation);
 };
 
 COMPONENT_EXPORT(VULKAN)
diff --git a/gpu/vulkan/vulkan_instance.h b/gpu/vulkan/vulkan_instance.h
index 2b119789..46580452 100644
--- a/gpu/vulkan/vulkan_instance.h
+++ b/gpu/vulkan/vulkan_instance.h
@@ -20,6 +20,9 @@
  public:
   VulkanInstance();
 
+  VulkanInstance(const VulkanInstance&) = delete;
+  VulkanInstance& operator=(const VulkanInstance&) = delete;
+
   ~VulkanInstance();
 
   // Creates the vulkan instance.
@@ -46,8 +49,6 @@
   VkDebugReportCallbackEXT error_callback_ = VK_NULL_HANDLE;
   VkDebugReportCallbackEXT warning_callback_ = VK_NULL_HANDLE;
 #endif
-
-  DISALLOW_COPY_AND_ASSIGN(VulkanInstance);
 };
 
 }  // namespace gpu
diff --git a/gpu/vulkan/vulkan_surface.h b/gpu/vulkan/vulkan_surface.h
index 9d80b9f..597115b 100644
--- a/gpu/vulkan/vulkan_surface.h
+++ b/gpu/vulkan/vulkan_surface.h
@@ -37,6 +37,9 @@
                 VkSurfaceKHR surface,
                 uint64_t acquire_next_image_timeout_ns = UINT64_MAX);
 
+  VulkanSurface(const VulkanSurface&) = delete;
+  VulkanSurface& operator=(const VulkanSurface&) = delete;
+
   virtual ~VulkanSurface();
 
   bool Initialize(VulkanDeviceQueue* device_queue,
@@ -93,8 +96,6 @@
   gfx::OverlayTransform transform_ = gfx::OVERLAY_TRANSFORM_INVALID;
 
   std::unique_ptr<VulkanSwapChain> swap_chain_;
-
-  DISALLOW_COPY_AND_ASSIGN(VulkanSurface);
 };
 
 }  // namespace gpu
diff --git a/gpu/vulkan/vulkan_swap_chain.h b/gpu/vulkan/vulkan_swap_chain.h
index b4c71e1..7cbd79f 100644
--- a/gpu/vulkan/vulkan_swap_chain.h
+++ b/gpu/vulkan/vulkan_swap_chain.h
@@ -31,6 +31,10 @@
   class COMPONENT_EXPORT(VULKAN) ScopedWrite {
    public:
     explicit ScopedWrite(VulkanSwapChain* swap_chain);
+
+    ScopedWrite(const ScopedWrite&) = delete;
+    ScopedWrite& operator=(const ScopedWrite&) = delete;
+
     ~ScopedWrite();
 
     bool success() const { return success_; }
@@ -50,8 +54,6 @@
     VkImageUsageFlags image_usage_ = 0;
     VkSemaphore begin_semaphore_ = VK_NULL_HANDLE;
     VkSemaphore end_semaphore_ = VK_NULL_HANDLE;
-
-    DISALLOW_COPY_AND_ASSIGN(ScopedWrite);
   };
 
   explicit VulkanSwapChain(uint64_t acquire_next_image_timeout_ns);
diff --git a/gpu/vulkan/win32/vulkan_implementation_win32.h b/gpu/vulkan/win32/vulkan_implementation_win32.h
index 8e6b649..1c5e1d8 100644
--- a/gpu/vulkan/win32/vulkan_implementation_win32.h
+++ b/gpu/vulkan/win32/vulkan_implementation_win32.h
@@ -15,6 +15,11 @@
     : public VulkanImplementation {
  public:
   explicit VulkanImplementationWin32(bool use_swiftshader);
+
+  VulkanImplementationWin32(const VulkanImplementationWin32&) = delete;
+  VulkanImplementationWin32& operator=(const VulkanImplementationWin32&) =
+      delete;
+
   ~VulkanImplementationWin32() override;
 
   // VulkanImplementation:
@@ -48,8 +53,6 @@
 
  private:
   VulkanInstance vulkan_instance_;
-
-  DISALLOW_COPY_AND_ASSIGN(VulkanImplementationWin32);
 };
 
 }  // namespace gpu
diff --git a/gpu/vulkan/x/vulkan_implementation_x11.h b/gpu/vulkan/x/vulkan_implementation_x11.h
index 5626066..b294501 100644
--- a/gpu/vulkan/x/vulkan_implementation_x11.h
+++ b/gpu/vulkan/x/vulkan_implementation_x11.h
@@ -17,6 +17,10 @@
     : public VulkanImplementation {
  public:
   explicit VulkanImplementationX11(bool use_swiftshader = false);
+
+  VulkanImplementationX11(const VulkanImplementationX11&) = delete;
+  VulkanImplementationX11& operator=(const VulkanImplementationX11&) = delete;
+
   ~VulkanImplementationX11() override;
 
   // VulkanImplementation:
@@ -51,8 +55,6 @@
  private:
   bool using_surface_ = true;
   VulkanInstance vulkan_instance_;
-
-  DISALLOW_COPY_AND_ASSIGN(VulkanImplementationX11);
 };
 
 }  // namespace gpu
diff --git a/gpu/vulkan/x/vulkan_surface_x11.h b/gpu/vulkan/x/vulkan_surface_x11.h
index d1d4dadb..94bb8ec 100644
--- a/gpu/vulkan/x/vulkan_surface_x11.h
+++ b/gpu/vulkan/x/vulkan_surface_x11.h
@@ -26,6 +26,10 @@
                    VkSurfaceKHR vk_surface,
                    x11::Window parent_window,
                    x11::Window window);
+
+  VulkanSurfaceX11(const VulkanSurfaceX11&) = delete;
+  VulkanSurfaceX11& operator=(const VulkanSurfaceX11&) = delete;
+
   ~VulkanSurfaceX11() override;
 
   // VulkanSurface:
@@ -40,8 +44,6 @@
   const x11::Window parent_window_;
   x11::Window window_;
   std::unique_ptr<x11::XScopedEventSelector> event_selector_;
-
-  DISALLOW_COPY_AND_ASSIGN(VulkanSurfaceX11);
 };
 
 }  // namespace gpu
diff --git a/headless/test/headless_web_contents_browsertest.cc b/headless/test/headless_web_contents_browsertest.cc
index 9092c37..70af060 100644
--- a/headless/test/headless_web_contents_browsertest.cc
+++ b/headless/test/headless_web_contents_browsertest.cc
@@ -483,6 +483,8 @@
 
 HEADLESS_ASYNC_DEVTOOLED_TEST_F(HeadlessWebContentsPDFPageSizeRoundingTest);
 
+#if BUILDFLAG(ENABLE_TAGGED_PDF)
+
 const char kExpectedStructTreeJSON[] = R"({
    "lang": "en",
    "type": "Document",
@@ -636,6 +638,8 @@
 
 HEADLESS_ASYNC_DEVTOOLED_TEST_F(HeadlessWebContentsTaggedPDFTest);
 
+#endif  // BUILDFLAG(ENABLE_TAGGED_PDF)
+
 #endif  // BUILDFLAG(ENABLE_PRINTING)
 
 class HeadlessWebContentsSecurityTest
diff --git a/infra/config/generated/builders/try/linux-rel-orchestrator/properties.textpb b/infra/config/generated/builders/try/linux-rel-orchestrator/properties.textpb
index 3d2d52ed..a9194bf 100644
--- a/infra/config/generated/builders/try/linux-rel-orchestrator/properties.textpb
+++ b/infra/config/generated/builders/try/linux-rel-orchestrator/properties.textpb
@@ -1,4 +1,8 @@
 {
+  "$build/chromium_orchestrator": {
+    "compilator": "linux-rel-compilator",
+    "compilator_watcher_git_revision": "ac4c95a90ea18c8ce70865c667a04ba18dfca1cd"
+  },
   "$build/code_coverage": {
     "coverage_test_types": [
       "unit",
diff --git a/infra/config/generated/builders/try/win10-rel-orchestrator/properties.textpb b/infra/config/generated/builders/try/win10-rel-orchestrator/properties.textpb
index c81ae0a7..65ce93b 100644
--- a/infra/config/generated/builders/try/win10-rel-orchestrator/properties.textpb
+++ b/infra/config/generated/builders/try/win10-rel-orchestrator/properties.textpb
@@ -1,4 +1,8 @@
 {
+  "$build/chromium_orchestrator": {
+    "compilator": "win10-rel-compilator",
+    "compilator_watcher_git_revision": "ac4c95a90ea18c8ce70865c667a04ba18dfca1cd"
+  },
   "$build/code_coverage": {
     "coverage_test_types": [
       "unit",
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg
index 7f15c03..e0390c8 100644
--- a/infra/config/generated/luci/cr-buildbucket.cfg
+++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -72710,6 +72710,10 @@
       }
       properties:
         '{'
+        '  "$build/chromium_orchestrator": {'
+        '    "compilator": "linux-rel-compilator",'
+        '    "compilator_watcher_git_revision": "ac4c95a90ea18c8ce70865c667a04ba18dfca1cd"'
+        '  },'
         '  "$build/code_coverage": {'
         '    "coverage_test_types": ['
         '      "unit",'
@@ -81964,6 +81968,10 @@
       }
       properties:
         '{'
+        '  "$build/chromium_orchestrator": {'
+        '    "compilator": "win10-rel-compilator",'
+        '    "compilator_watcher_git_revision": "ac4c95a90ea18c8ce70865c667a04ba18dfca1cd"'
+        '  },'
         '  "$build/code_coverage": {'
         '    "coverage_test_types": ['
         '      "unit",'
diff --git a/infra/config/subprojects/chromium/try.star b/infra/config/subprojects/chromium/try.star
index d528408d..01b0f6f 100644
--- a/infra/config/subprojects/chromium/try.star
+++ b/infra/config/subprojects/chromium/try.star
@@ -1342,8 +1342,14 @@
     use_clang_coverage = True,
     coverage_test_types = ["unit", "overall"],
     properties = {
+        # TODO (kimstephanie): Remove first two when orchestrator recipe stops
+        # reading these
         "compilator": "linux-rel-compilator",
         "compilator_watcher_git_revision": compilator_watcher_git_revision,
+        "$build/chromium_orchestrator": {
+            "compilator": "linux-rel-compilator",
+            "compilator_watcher_git_revision": compilator_watcher_git_revision,
+        },
     },
     service_account = "chromium-orchestrator@chops-service-accounts.iam.gserviceaccount.com",
     tryjob = try_.job(
@@ -1971,8 +1977,14 @@
     use_clang_coverage = True,
     coverage_test_types = ["unit", "overall"],
     properties = {
+        # TODO (kimstephanie): Remove first two when orchestrator recipe stops
+        # reading these
         "compilator": "win10-rel-compilator",
         "compilator_watcher_git_revision": compilator_watcher_git_revision,
+        "$build/chromium_orchestrator": {
+            "compilator": "win10-rel-compilator",
+            "compilator_watcher_git_revision": compilator_watcher_git_revision,
+        },
     },
     service_account = "chromium-orchestrator@chops-service-accounts.iam.gserviceaccount.com",
     tryjob = try_.job(
diff --git a/ios/chrome/browser/ui/authentication/signin/signin_constants.h b/ios/chrome/browser/ui/authentication/signin/signin_constants.h
index 93325635..531b816 100644
--- a/ios/chrome/browser/ui/authentication/signin/signin_constants.h
+++ b/ios/chrome/browser/ui/authentication/signin/signin_constants.h
@@ -63,9 +63,6 @@
 typedef NS_ENUM(NSUInteger, SigninCompletionAction) {
   // No action needed.
   SigninCompletionActionNone,
-  // The advanced settings sign-in view is needed to finish the sign-in.
-  // This case is only used for the first run sign-in.
-  SigninCompletionActionShowAdvancedSettingsSignin,
   // The user tapped the manager, learn more, link and sign-in was cancelled.
   SigninCompletionActionShowManagedLearnMore,
 };
diff --git a/ios/chrome/browser/ui/authentication/signin/user_signin/user_signin_coordinator.mm b/ios/chrome/browser/ui/authentication/signin/user_signin/user_signin_coordinator.mm
index 40cd2267..f88e8992 100644
--- a/ios/chrome/browser/ui/authentication/signin/user_signin/user_signin_coordinator.mm
+++ b/ios/chrome/browser/ui/authentication/signin/user_signin/user_signin_coordinator.mm
@@ -346,17 +346,13 @@
   if (self.managedLearnMoreLinkWasTapped) {
     completionAction = SigninCompletionActionShowManagedLearnMore;
   } else if (self.unifiedConsentCoordinator.settingsLinkWasTapped) {
-    completionAction = SigninCompletionActionShowAdvancedSettingsSignin;
+    // Sign-in is finished but the advanced settings link was tapped.
+    [self displayAdvancedSettings];
+    return;
   }
   SigninCompletionInfo* completionInfo =
       [[SigninCompletionInfo alloc] initWithIdentity:identity
                               signinCompletionAction:completionAction];
-  // Sign-in is finished but the advanced settings link was tapped.
-  if (completionInfo.signinCompletionAction ==
-      SigninCompletionActionShowAdvancedSettingsSignin) {
-    [self displayAdvancedSettings];
-    return;
-  }
   __weak UserSigninCoordinator* weakSelf = self;
   ProceduralBlock completion = ^void() {
     [weakSelf viewControllerDismissedWithResult:signinResult
@@ -415,9 +411,7 @@
                     object:self];
 }
 
-// Called when |self.viewController| is dismissed. If |completionInfo|'s
-// signinCompletionAction is SigninCompletionActionShowAdvancedSettingsSignin,
-// the advanced settings sign-in is presented. Otherwise, the sign-in is
+// Called when |self.viewController| is dismissed. The sign-in is
 // finished and |runCompletionCallbackWithSigninResult:completionInfo:| is
 // called.
 - (void)viewControllerDismissedWithResult:(SigninCoordinatorResult)signinResult
@@ -428,8 +422,6 @@
   DCHECK(self.unifiedConsentCoordinator);
   DCHECK(self.mediator);
   DCHECK(self.viewController);
-  DCHECK_NE(SigninCompletionActionShowAdvancedSettingsSignin,
-            completionInfo.signinCompletionAction);
 
   [self.unifiedConsentCoordinator stop];
   self.unifiedConsentCoordinator = nil;
diff --git a/ios/chrome/browser/ui/first_run/first_run_egtest.mm b/ios/chrome/browser/ui/first_run/first_run_egtest.mm
index e80f3299..df1949d5 100644
--- a/ios/chrome/browser/ui/first_run/first_run_egtest.mm
+++ b/ios/chrome/browser/ui/first_run/first_run_egtest.mm
@@ -541,6 +541,62 @@
   [SigninEarlGrey verifySyncUIEnabled:NO];
 }
 
+// Checks that Sync is turned off after the user chose not to turn
+// it on, having opened the Advanced Settings in the advanced sync settings
+// screen.
+- (void)testTapLinkSyncOff {
+  FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1];
+  [SigninEarlGrey addFakeIdentity:fakeIdentity];
+
+  [self verifyWelcomeScreenIsDisplayed];
+  [self scrollToElementAndAssertVisibility:GetAcceptButton()];
+  [[EarlGrey selectElementWithMatcher:GetAcceptButton()]
+      performAction:grey_tap()];
+
+  [self verifySignInScreenIsDisplayed];
+  [[EarlGrey
+      selectElementWithMatcher:GetContinueButtonWithIdentity(fakeIdentity)]
+      performAction:grey_tap()];
+
+  [self verifySyncScreenIsDisplayed];
+  [[EarlGrey
+      selectElementWithMatcher:
+          grey_allOf(grey_text(l10n_util::GetNSString(
+                         IDS_IOS_FIRST_RUN_SYNC_SCREEN_ADVANCE_SETTINGS)),
+                     grey_sufficientlyVisible(), nil)]
+      performAction:grey_tap()];
+
+  // Check that Sync hasn't started yet, allowing the user to change some
+  // settings.
+  GREYAssertFalse([FirstRunAppInterface isSyncFirstSetupComplete],
+                  @"Sync shouldn't have finished its original setup yet");
+
+  [[EarlGrey selectElementWithMatcher:AdvancedSyncSettingsDoneButtonMatcher()]
+      performAction:grey_tap()];
+
+  // Check sync did not start.
+  GREYAssertFalse([FirstRunAppInterface isSyncFirstSetupComplete],
+                  @"Sync shouldn't start when discarding advanced settings.");
+  [[EarlGrey
+      selectElementWithMatcher:
+          grey_allOf(grey_text(l10n_util::GetNSString(
+                         IDS_IOS_FIRST_RUN_SYNC_SCREEN_SECONDARY_ACTION)),
+                     grey_sufficientlyVisible(), nil)]
+      performAction:grey_tap()];
+
+  // Verify that the user is signed in.
+  [SigninEarlGrey verifySignedInWithFakeIdentity:fakeIdentity];
+
+  // Dismiss the location prompt.
+  [[EarlGrey selectElementWithMatcher:
+                 grey_text(l10n_util::GetNSString(
+                     IDS_IOS_DEFAULT_BROWSER_SECONDARY_BUTTON_TEXT))]
+      performAction:grey_tap()];
+
+  [ChromeEarlGreyUI openSettingsMenu];
+  [SigninEarlGrey verifySyncUIEnabled:NO];
+}
+
 // Checks that sync is turned on after the user chose to turn on
 // sync in the advanced sync settings screen.
 - (void)testCustomSyncOn {
diff --git a/ios/chrome/browser/ui/first_run/welcome_to_chrome_view_controller.mm b/ios/chrome/browser/ui/first_run/welcome_to_chrome_view_controller.mm
index bb9b81e7..89337ae5 100644
--- a/ios/chrome/browser/ui/first_run/welcome_to_chrome_view_controller.mm
+++ b/ios/chrome/browser/ui/first_run/welcome_to_chrome_view_controller.mm
@@ -296,11 +296,6 @@
                                      (SigninCompletionInfo*)completionInfo {
   FirstRunDismissed();
   switch (completionInfo.signinCompletionAction) {
-    case SigninCompletionActionShowAdvancedSettingsSignin:
-      DCHECK(!self.interruptCompletion);
-      [self.dispatcher showAdvancedSigninSettingsFromViewController:
-                           presentingViewController];
-      break;
     case SigninCompletionActionNone:
     case SigninCompletionActionShowManagedLearnMore:
       if (self.interruptCompletion) {
diff --git a/ios/chrome/browser/ui/main/scene_controller.mm b/ios/chrome/browser/ui/main/scene_controller.mm
index 79e93952..279f41f 100644
--- a/ios/chrome/browser/ui/main/scene_controller.mm
+++ b/ios/chrome/browser/ui/main/scene_controller.mm
@@ -2774,10 +2774,6 @@
         switch (info.signinCompletionAction) {
           case SigninCompletionActionNone:
             break;
-          case SigninCompletionActionShowAdvancedSettingsSignin:
-            // Case only for first run.
-            NOTREACHED();
-            break;
           case SigninCompletionActionShowManagedLearnMore:
             id<ApplicationCommands> dispatcher = HandlerForProtocol(
                 strongSelf.mainInterface.browser->GetCommandDispatcher(),
diff --git a/mojo/core/atomic_flag.h b/mojo/core/atomic_flag.h
index aec7f4e..e5a79033 100644
--- a/mojo/core/atomic_flag.h
+++ b/mojo/core/atomic_flag.h
@@ -33,6 +33,10 @@
 class AtomicFlag {
  public:
   AtomicFlag() : flag_(0) {}
+
+  AtomicFlag(const AtomicFlag&) = delete;
+  AtomicFlag& operator=(const AtomicFlag&) = delete;
+
   ~AtomicFlag() = default;
 
   void Set(bool value) { base::subtle::Release_Store(&flag_, value ? 1 : 0); }
@@ -43,8 +47,6 @@
 
  private:
   base::subtle::Atomic32 flag_;
-
-  DISALLOW_COPY_AND_ASSIGN(AtomicFlag);
 };
 
 }  // namespace core
diff --git a/mojo/core/broker.h b/mojo/core/broker.h
index a22210d4..27e070c 100644
--- a/mojo/core/broker.h
+++ b/mojo/core/broker.h
@@ -26,6 +26,10 @@
   // Otherwise, no initialization message is expected and this will not wait for
   // one.
   Broker(PlatformHandle handle, bool wait_for_channel_handle);
+
+  Broker(const Broker&) = delete;
+  Broker& operator=(const Broker&) = delete;
+
   ~Broker();
 
   // Returns the platform handle that should be used to establish a NodeChannel
@@ -49,8 +53,6 @@
   // with message ordering since we can only have one request at a time
   // in-flight.
   base::Lock lock_;
-
-  DISALLOW_COPY_AND_ASSIGN(Broker);
 };
 
 }  // namespace core
diff --git a/mojo/core/channel.cc b/mojo/core/channel.cc
index 5935ef3..233087de 100644
--- a/mojo/core/channel.cc
+++ b/mojo/core/channel.cc
@@ -699,6 +699,9 @@
     data_ = MakeAlignedBuffer(size_);
   }
 
+  ReadBuffer(const ReadBuffer&) = delete;
+  ReadBuffer& operator=(const ReadBuffer&) = delete;
+
   ~ReadBuffer() { DCHECK(data_); }
 
   const char* occupied_bytes() const {
@@ -782,8 +785,6 @@
 
   // The total number of occupied bytes, including discarded bytes.
   size_t num_occupied_bytes_ = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(ReadBuffer);
 };
 
 Channel::Channel(Delegate* delegate,
diff --git a/mojo/core/channel.h b/mojo/core/channel.h
index 7288dd8..fe9309c 100644
--- a/mojo/core/channel.h
+++ b/mojo/core/channel.h
@@ -62,6 +62,9 @@
 
   // A message to be written to a channel.
   struct MOJO_SYSTEM_IMPL_EXPORT Message {
+    Message(const Message&) = delete;
+    Message& operator=(const Message&) = delete;
+
     virtual ~Message() = default;
 
     enum class MessageType : uint16_t {
@@ -234,8 +237,6 @@
     // be transmitted if the message is written to a channel. Includes all
     // headers and user payload.
     size_t size_ = 0;
-
-    DISALLOW_COPY_AND_ASSIGN(Message);
   };
 
   // Error types which may be reported by a Channel instance to its delegate.
diff --git a/mojo/core/channel_fuchsia.cc b/mojo/core/channel_fuchsia.cc
index 7b112ded..ae4e725c 100644
--- a/mojo/core/channel_fuchsia.cc
+++ b/mojo/core/channel_fuchsia.cc
@@ -104,6 +104,9 @@
 
   MessageView& operator=(MessageView&& other) = default;
 
+  MessageView(const MessageView&) = delete;
+  MessageView& operator=(const MessageView&) = delete;
+
   ~MessageView() = default;
 
   const void* data() const {
@@ -144,8 +147,6 @@
   Channel::MessagePtr message_;
   size_t offset_;
   std::vector<PlatformHandleInTransit> handles_;
-
-  DISALLOW_COPY_AND_ASSIGN(MessageView);
 };
 
 class ChannelFuchsia : public Channel,
diff --git a/mojo/core/channel_linux.cc b/mojo/core/channel_linux.cc
index 20333a7..22c391d2 100644
--- a/mojo/core/channel_linux.cc
+++ b/mojo/core/channel_linux.cc
@@ -181,6 +181,10 @@
                         public base::MessagePumpForIO::FdWatcher {
  public:
   EventFDNotifier(EventFDNotifier&& efd) = default;
+
+  EventFDNotifier(const EventFDNotifier&) = delete;
+  EventFDNotifier& operator=(const EventFDNotifier&) = delete;
+
   ~EventFDNotifier() override { reset(); }
 
   static constexpr int kEfdFlags = EFD_CLOEXEC | EFD_NONBLOCK;
@@ -318,8 +322,6 @@
   base::ScopedFD fd_;
   std::unique_ptr<base::MessagePumpForIO::FdWatchController> watcher_;
   scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
-
-  DISALLOW_COPY_AND_ASSIGN(EventFDNotifier);
 };
 
 }  // namespace
@@ -331,6 +333,10 @@
 class ChannelLinux::SharedBuffer {
  public:
   SharedBuffer(SharedBuffer&& other) = default;
+
+  SharedBuffer(const SharedBuffer&) = delete;
+  SharedBuffer& operator=(const SharedBuffer&) = delete;
+
   ~SharedBuffer() { reset(); }
 
   enum class Error { kSuccess = 0, kGeneralError = 1, kControlCorruption = 2 };
@@ -602,8 +608,6 @@
 
   uint8_t* base_ptr_ = nullptr;
   size_t len_ = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(SharedBuffer);
 };
 
 ChannelLinux::ChannelLinux(
diff --git a/mojo/core/channel_posix.cc b/mojo/core/channel_posix.cc
index e2b3868..f05582c 100644
--- a/mojo/core/channel_posix.cc
+++ b/mojo/core/channel_posix.cc
@@ -65,6 +65,9 @@
 
   MessageView& operator=(MessageView&& other) = default;
 
+  MessageView(const MessageView&) = delete;
+  MessageView& operator=(const MessageView&) = delete;
+
   ~MessageView() {
     if (message_) {
       UMA_HISTOGRAM_TIMES("Mojo.Channel.WriteMessageLatency",
@@ -111,8 +114,6 @@
   size_t num_handles_sent_ = 0;
 
   base::TimeTicks start_time_ = base::TimeTicks::Now();
-
-  DISALLOW_COPY_AND_ASSIGN(MessageView);
 };
 
 ChannelPosix::ChannelPosix(
diff --git a/mojo/core/connection_params.h b/mojo/core/connection_params.h
index c1f41c0..754a128 100644
--- a/mojo/core/connection_params.h
+++ b/mojo/core/connection_params.h
@@ -21,6 +21,10 @@
   explicit ConnectionParams(PlatformChannelEndpoint endpoint);
   explicit ConnectionParams(PlatformChannelServerEndpoint server_endpoint);
   ConnectionParams(ConnectionParams&&);
+
+  ConnectionParams(const ConnectionParams&) = delete;
+  ConnectionParams& operator=(const ConnectionParams&) = delete;
+
   ~ConnectionParams();
 
   ConnectionParams& operator=(ConnectionParams&&);
@@ -47,8 +51,6 @@
   bool leak_endpoint_ = false;
   PlatformChannelEndpoint endpoint_;
   PlatformChannelServerEndpoint server_endpoint_;
-
-  DISALLOW_COPY_AND_ASSIGN(ConnectionParams);
 };
 
 }  // namespace core
diff --git a/mojo/core/core.cc b/mojo/core/core.cc
index 15378b4..69b6178 100644
--- a/mojo/core/core.cc
+++ b/mojo/core/core.cc
@@ -87,6 +87,9 @@
   ProcessDisconnectHandler(MojoProcessErrorHandler handler, uintptr_t context)
       : handler_(handler), context_(context) {}
 
+  ProcessDisconnectHandler(const ProcessDisconnectHandler&) = delete;
+  ProcessDisconnectHandler& operator=(const ProcessDisconnectHandler&) = delete;
+
   ~ProcessDisconnectHandler() {
     InvokeProcessErrorCallback(handler_, context_, std::string(),
                                MOJO_PROCESS_ERROR_FLAG_DISCONNECTED);
@@ -95,8 +98,6 @@
  private:
   const MojoProcessErrorHandler handler_;
   const uintptr_t context_;
-
-  DISALLOW_COPY_AND_ASSIGN(ProcessDisconnectHandler);
 };
 
 void RunMojoProcessErrorHandler(
diff --git a/mojo/core/core.h b/mojo/core/core.h
index 8946d53..f952a1b 100644
--- a/mojo/core/core.h
+++ b/mojo/core/core.h
@@ -39,6 +39,10 @@
 class MOJO_SYSTEM_IMPL_EXPORT Core {
  public:
   Core();
+
+  Core(const Core&) = delete;
+  Core& operator=(const Core&) = delete;
+
   virtual ~Core();
 
   static Core* Get();
@@ -360,8 +364,6 @@
   using MappingTable =
       std::unordered_map<void*, std::unique_ptr<PlatformSharedMemoryMapping>>;
   MappingTable mapping_table_;
-
-  DISALLOW_COPY_AND_ASSIGN(Core);
 };
 
 }  // namespace core
diff --git a/mojo/core/core_test_base.h b/mojo/core/core_test_base.h
index ebc5fe1..908ef9d 100644
--- a/mojo/core/core_test_base.h
+++ b/mojo/core/core_test_base.h
@@ -26,6 +26,10 @@
   using MockHandleInfo = CoreTestBase_MockHandleInfo;
 
   CoreTestBase();
+
+  CoreTestBase(const CoreTestBase&) = delete;
+  CoreTestBase& operator=(const CoreTestBase&) = delete;
+
   ~CoreTestBase() override;
 
  protected:
@@ -33,14 +37,16 @@
   MojoHandle CreateMockHandle(MockHandleInfo* info);
 
   Core* core();
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CoreTestBase);
 };
 
 class CoreTestBase_MockHandleInfo {
  public:
   CoreTestBase_MockHandleInfo();
+
+  CoreTestBase_MockHandleInfo(const CoreTestBase_MockHandleInfo&) = delete;
+  CoreTestBase_MockHandleInfo& operator=(const CoreTestBase_MockHandleInfo&) =
+      delete;
+
   ~CoreTestBase_MockHandleInfo();
 
   unsigned GetCtorCallCount() const;
@@ -81,8 +87,6 @@
   unsigned read_data_call_count_;
   unsigned begin_read_data_call_count_;
   unsigned end_read_data_call_count_;
-
-  DISALLOW_COPY_AND_ASSIGN(CoreTestBase_MockHandleInfo);
 };
 
 }  // namespace test
diff --git a/mojo/core/data_pipe_unittest.cc b/mojo/core/data_pipe_unittest.cc
index 330c957cf1..adbcffe 100644
--- a/mojo/core/data_pipe_unittest.cc
+++ b/mojo/core/data_pipe_unittest.cc
@@ -74,6 +74,9 @@
   DataPipeTest()
       : producer_(MOJO_HANDLE_INVALID), consumer_(MOJO_HANDLE_INVALID) {}
 
+  DataPipeTest(const DataPipeTest&) = delete;
+  DataPipeTest& operator=(const DataPipeTest&) = delete;
+
   ~DataPipeTest() override {
     if (producer_ != MOJO_HANDLE_INVALID)
       CHECK_EQ(MOJO_RESULT_OK, MojoClose(producer_));
@@ -173,9 +176,6 @@
   }
 
   MojoHandle producer_, consumer_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(DataPipeTest);
 };
 
 TEST_F(DataPipeTest, Basic) {
diff --git a/mojo/core/embedder/scoped_ipc_support.h b/mojo/core/embedder/scoped_ipc_support.h
index ff60329..d19337a8 100644
--- a/mojo/core/embedder/scoped_ipc_support.h
+++ b/mojo/core/embedder/scoped_ipc_support.h
@@ -105,12 +105,14 @@
   ScopedIPCSupport(
       scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner,
       ShutdownPolicy shutdown_policy);
+
+  ScopedIPCSupport(const ScopedIPCSupport&) = delete;
+  ScopedIPCSupport& operator=(const ScopedIPCSupport&) = delete;
+
   ~ScopedIPCSupport();
 
  private:
   const ShutdownPolicy shutdown_policy_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedIPCSupport);
 };
 
 }  // namespace core
diff --git a/mojo/core/handle_table.h b/mojo/core/handle_table.h
index fdc9f212..e4234b18 100644
--- a/mojo/core/handle_table.h
+++ b/mojo/core/handle_table.h
@@ -25,6 +25,10 @@
     : public base::trace_event::MemoryDumpProvider {
  public:
   HandleTable();
+
+  HandleTable(const HandleTable&) = delete;
+  HandleTable& operator=(const HandleTable&) = delete;
+
   ~HandleTable() override;
 
   // HandleTable is thread-hostile. All access should be gated by GetLock().
@@ -80,8 +84,6 @@
   base::Lock lock_;
 
   uint32_t next_available_handle_ = 1;
-
-  DISALLOW_COPY_AND_ASSIGN(HandleTable);
 };
 
 }  // namespace core
diff --git a/mojo/core/invitation_unittest.cc b/mojo/core/invitation_unittest.cc
index 2c8eeef..e001bee 100644
--- a/mojo/core/invitation_unittest.cc
+++ b/mojo/core/invitation_unittest.cc
@@ -47,6 +47,10 @@
 class InvitationTest : public test::MojoTestBase {
  public:
   InvitationTest() = default;
+
+  InvitationTest(const InvitationTest&) = delete;
+  InvitationTest& operator=(const InvitationTest&) = delete;
+
   ~InvitationTest() override = default;
 
  protected:
@@ -74,8 +78,6 @@
 
  private:
   base::test::TaskEnvironment task_environment_;
-
-  DISALLOW_COPY_AND_ASSIGN(InvitationTest);
 };
 
 void PrepareToPassRemoteEndpoint(PlatformChannel* channel,
@@ -587,6 +589,10 @@
  public:
   RemoteProcessState()
       : callback_task_runner_(base::SequencedTaskRunnerHandle::Get()) {}
+
+  RemoteProcessState(const RemoteProcessState&) = delete;
+  RemoteProcessState& operator=(const RemoteProcessState&) = delete;
+
   ~RemoteProcessState() = default;
 
   bool disconnected() {
@@ -620,8 +626,6 @@
   bool disconnected_ = false;
   std::string expected_error_message_;
   base::RepeatingClosure error_callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(RemoteProcessState);
 };
 
 void TestProcessErrorHandler(uintptr_t context,
diff --git a/mojo/core/message_pipe_dispatcher.cc b/mojo/core/message_pipe_dispatcher.cc
index 3fb553b..301e1b4 100644
--- a/mojo/core/message_pipe_dispatcher.cc
+++ b/mojo/core/message_pipe_dispatcher.cc
@@ -64,6 +64,10 @@
 class PeekSizeMessageFilter : public ports::MessageFilter {
  public:
   PeekSizeMessageFilter() = default;
+
+  PeekSizeMessageFilter(const PeekSizeMessageFilter&) = delete;
+  PeekSizeMessageFilter& operator=(const PeekSizeMessageFilter&) = delete;
+
   ~PeekSizeMessageFilter() override = default;
 
   // ports::MessageFilter:
@@ -78,8 +82,6 @@
 
  private:
   size_t message_size_ = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(PeekSizeMessageFilter);
 };
 
 #endif  // DCHECK_IS_ON()
diff --git a/mojo/core/message_pipe_unittest.cc b/mojo/core/message_pipe_unittest.cc
index 9aa13f6..5f5bd87 100644
--- a/mojo/core/message_pipe_unittest.cc
+++ b/mojo/core/message_pipe_unittest.cc
@@ -35,6 +35,9 @@
     CHECK_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(nullptr, &pipe0_, &pipe1_));
   }
 
+  MessagePipeTest(const MessagePipeTest&) = delete;
+  MessagePipeTest& operator=(const MessagePipeTest&) = delete;
+
   ~MessagePipeTest() override {
     if (pipe0_ != MOJO_HANDLE_INVALID)
       CHECK_EQ(MOJO_RESULT_OK, MojoClose(pipe0_));
@@ -78,9 +81,6 @@
   }
 
   MojoHandle pipe0_, pipe1_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MessagePipeTest);
 };
 
 using FuseMessagePipeTest = test::MojoTestBase;
diff --git a/mojo/core/message_unittest.cc b/mojo/core/message_unittest.cc
index cb0747c..981e820 100644
--- a/mojo/core/message_unittest.cc
+++ b/mojo/core/message_unittest.cc
@@ -102,6 +102,10 @@
   NeverSerializedMessage(
       base::OnceClosure destruction_callback = base::OnceClosure())
       : destruction_callback_(std::move(destruction_callback)) {}
+
+  NeverSerializedMessage(const NeverSerializedMessage&) = delete;
+  NeverSerializedMessage& operator=(const NeverSerializedMessage&) = delete;
+
   ~NeverSerializedMessage() override {
     if (destruction_callback_)
       std::move(destruction_callback_).Run();
@@ -116,8 +120,6 @@
   void SerializePayload(void* buffer) override { NOTREACHED(); }
 
   base::OnceClosure destruction_callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(NeverSerializedMessage);
 };
 
 class SimpleMessage : public TestMessageBase {
@@ -127,6 +129,9 @@
       : contents_(contents),
         destruction_callback_(std::move(destruction_callback)) {}
 
+  SimpleMessage(const SimpleMessage&) = delete;
+  SimpleMessage& operator=(const SimpleMessage&) = delete;
+
   ~SimpleMessage() override {
     if (destruction_callback_)
       std::move(destruction_callback_).Run();
@@ -159,8 +164,6 @@
   const std::string contents_;
   base::OnceClosure destruction_callback_;
   std::vector<mojo::ScopedMessagePipeHandle> handles_;
-
-  DISALLOW_COPY_AND_ASSIGN(SimpleMessage);
 };
 
 TEST_F(MessageTest, InvalidMessageObjects) {
diff --git a/mojo/core/mojo_core.cc b/mojo/core/mojo_core.cc
index bcbe1210..fc1763f 100644
--- a/mojo/core/mojo_core.cc
+++ b/mojo/core/mojo_core.cc
@@ -35,6 +35,9 @@
     mojo::core::Core::Get()->SetIOTaskRunner(ipc_thread_.task_runner());
   }
 
+  IPCSupport(const IPCSupport&) = delete;
+  IPCSupport& operator=(const IPCSupport&) = delete;
+
   ~IPCSupport() {
     base::WaitableEvent wait(base::WaitableEvent::ResetPolicy::MANUAL,
                              base::WaitableEvent::InitialState::NOT_SIGNALED);
@@ -54,8 +57,6 @@
 #endif  // !defined(COMPONENT_BUILD)
 
   base::Thread ipc_thread_;
-
-  DISALLOW_COPY_AND_ASSIGN(IPCSupport);
 };
 
 std::unique_ptr<IPCSupport>& GetIPCSupport() {
diff --git a/mojo/core/platform_handle_in_transit.h b/mojo/core/platform_handle_in_transit.h
index 3ba2707..21a7d95 100644
--- a/mojo/core/platform_handle_in_transit.h
+++ b/mojo/core/platform_handle_in_transit.h
@@ -28,6 +28,10 @@
   PlatformHandleInTransit();
   explicit PlatformHandleInTransit(PlatformHandle handle);
   PlatformHandleInTransit(PlatformHandleInTransit&&);
+
+  PlatformHandleInTransit(const PlatformHandleInTransit&) = delete;
+  PlatformHandleInTransit& operator=(const PlatformHandleInTransit&) = delete;
+
   ~PlatformHandleInTransit();
 
   PlatformHandleInTransit& operator=(PlatformHandleInTransit&&);
@@ -97,8 +101,6 @@
 
   PlatformHandle handle_;
   base::Process owning_process_;
-
-  DISALLOW_COPY_AND_ASSIGN(PlatformHandleInTransit);
 };
 
 }  // namespace core
diff --git a/mojo/core/platform_shared_memory_mapping.h b/mojo/core/platform_shared_memory_mapping.h
index 305f5e4..dd14df3 100644
--- a/mojo/core/platform_shared_memory_mapping.h
+++ b/mojo/core/platform_shared_memory_mapping.h
@@ -36,6 +36,11 @@
   PlatformSharedMemoryMapping(base::subtle::PlatformSharedMemoryRegion* region,
                               size_t offset,
                               size_t length);
+
+  PlatformSharedMemoryMapping(const PlatformSharedMemoryMapping&) = delete;
+  PlatformSharedMemoryMapping& operator=(const PlatformSharedMemoryMapping&) =
+      delete;
+
   ~PlatformSharedMemoryMapping();
 
   bool IsValid() const;
@@ -49,8 +54,6 @@
   const size_t length_;
   void* base_ = nullptr;
   std::unique_ptr<base::SharedMemoryMapping> mapping_;
-
-  DISALLOW_COPY_AND_ASSIGN(PlatformSharedMemoryMapping);
 };
 
 }  // namespace core
diff --git a/mojo/core/ports/event.h b/mojo/core/ports/event.h
index 55c081e3..a379001 100644
--- a/mojo/core/ports/event.h
+++ b/mojo/core/ports/event.h
@@ -80,6 +80,10 @@
     char padding[7];
   };
 #pragma pack(pop)
+
+  Event(const Event&) = delete;
+  Event& operator=(const Event&) = delete;
+
   virtual ~Event();
 
   static ScopedEvent Deserialize(const void* buffer, size_t num_bytes);
@@ -106,13 +110,15 @@
  private:
   const Type type_;
   PortName port_name_;
-
-  DISALLOW_COPY_AND_ASSIGN(Event);
 };
 
 class COMPONENT_EXPORT(MOJO_CORE_PORTS) UserMessageEvent : public Event {
  public:
   explicit UserMessageEvent(size_t num_ports);
+
+  UserMessageEvent(const UserMessageEvent&) = delete;
+  UserMessageEvent& operator=(const UserMessageEvent&) = delete;
+
   ~UserMessageEvent() override;
 
   bool HasMessage() const { return !!message_; }
@@ -158,13 +164,15 @@
   std::vector<PortDescriptor> port_descriptors_;
   std::vector<PortName> ports_;
   std::unique_ptr<UserMessage> message_;
-
-  DISALLOW_COPY_AND_ASSIGN(UserMessageEvent);
 };
 
 class COMPONENT_EXPORT(MOJO_CORE_PORTS) PortAcceptedEvent : public Event {
  public:
   explicit PortAcceptedEvent(const PortName& port_name);
+
+  PortAcceptedEvent(const PortAcceptedEvent&) = delete;
+  PortAcceptedEvent& operator=(const PortAcceptedEvent&) = delete;
+
   ~PortAcceptedEvent() override;
 
   static ScopedEvent Deserialize(const PortName& port_name,
@@ -174,8 +182,6 @@
  private:
   size_t GetSerializedDataSize() const override;
   void SerializeData(void* buffer) const override;
-
-  DISALLOW_COPY_AND_ASSIGN(PortAcceptedEvent);
 };
 
 class COMPONENT_EXPORT(MOJO_CORE_PORTS) ObserveProxyEvent : public Event {
@@ -185,6 +191,10 @@
                     const PortName& proxy_port_name,
                     const NodeName& proxy_target_node_name,
                     const PortName& proxy_target_port_name);
+
+  ObserveProxyEvent(const ObserveProxyEvent&) = delete;
+  ObserveProxyEvent& operator=(const ObserveProxyEvent&) = delete;
+
   ~ObserveProxyEvent() override;
 
   const NodeName& proxy_node_name() const { return proxy_node_name_; }
@@ -209,13 +219,15 @@
   const PortName proxy_port_name_;
   const NodeName proxy_target_node_name_;
   const PortName proxy_target_port_name_;
-
-  DISALLOW_COPY_AND_ASSIGN(ObserveProxyEvent);
 };
 
 class COMPONENT_EXPORT(MOJO_CORE_PORTS) ObserveProxyAckEvent : public Event {
  public:
   ObserveProxyAckEvent(const PortName& port_name, uint64_t last_sequence_num);
+
+  ObserveProxyAckEvent(const ObserveProxyAckEvent&) = delete;
+  ObserveProxyAckEvent& operator=(const ObserveProxyAckEvent&) = delete;
+
   ~ObserveProxyAckEvent() override;
 
   uint64_t last_sequence_num() const { return last_sequence_num_; }
@@ -230,13 +242,15 @@
   ScopedEvent Clone() const override;
 
   const uint64_t last_sequence_num_;
-
-  DISALLOW_COPY_AND_ASSIGN(ObserveProxyAckEvent);
 };
 
 class COMPONENT_EXPORT(MOJO_CORE_PORTS) ObserveClosureEvent : public Event {
  public:
   ObserveClosureEvent(const PortName& port_name, uint64_t last_sequence_num);
+
+  ObserveClosureEvent(const ObserveClosureEvent&) = delete;
+  ObserveClosureEvent& operator=(const ObserveClosureEvent&) = delete;
+
   ~ObserveClosureEvent() override;
 
   uint64_t last_sequence_num() const { return last_sequence_num_; }
@@ -254,8 +268,6 @@
   ScopedEvent Clone() const override;
 
   uint64_t last_sequence_num_;
-
-  DISALLOW_COPY_AND_ASSIGN(ObserveClosureEvent);
 };
 
 class COMPONENT_EXPORT(MOJO_CORE_PORTS) MergePortEvent : public Event {
@@ -263,6 +275,10 @@
   MergePortEvent(const PortName& port_name,
                  const PortName& new_port_name,
                  const PortDescriptor& new_port_descriptor);
+
+  MergePortEvent(const MergePortEvent&) = delete;
+  MergePortEvent& operator=(const MergePortEvent&) = delete;
+
   ~MergePortEvent() override;
 
   const PortName& new_port_name() const { return new_port_name_; }
@@ -280,8 +296,6 @@
 
   const PortName new_port_name_;
   const PortDescriptor new_port_descriptor_;
-
-  DISALLOW_COPY_AND_ASSIGN(MergePortEvent);
 };
 
 class COMPONENT_EXPORT(MOJO_CORE_PORTS) UserMessageReadAckRequestEvent
diff --git a/mojo/core/ports/message_queue.h b/mojo/core/ports/message_queue.h
index 1d34222..21d6ab0 100644
--- a/mojo/core/ports/message_queue.h
+++ b/mojo/core/ports/message_queue.h
@@ -32,6 +32,10 @@
  public:
   explicit MessageQueue();
   explicit MessageQueue(uint64_t next_sequence_num);
+
+  MessageQueue(const MessageQueue&) = delete;
+  MessageQueue& operator=(const MessageQueue&) = delete;
+
   ~MessageQueue();
 
   void set_signalable(bool value) { signalable_ = value; }
@@ -75,8 +79,6 @@
   uint64_t next_sequence_num_;
   bool signalable_ = true;
   size_t total_queued_bytes_ = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(MessageQueue);
 };
 
 }  // namespace ports
diff --git a/mojo/core/ports/node.cc b/mojo/core/ports/node.cc
index d309b88..ae4c2a2c 100644
--- a/mojo/core/ports/node.cc
+++ b/mojo/core/ports/node.cc
@@ -49,6 +49,10 @@
 class RandomNameGenerator {
  public:
   RandomNameGenerator() = default;
+
+  RandomNameGenerator(const RandomNameGenerator&) = delete;
+  RandomNameGenerator& operator=(const RandomNameGenerator&) = delete;
+
   ~RandomNameGenerator() = default;
 
   PortName GenerateRandomPortName() {
@@ -68,8 +72,6 @@
   base::Lock lock_;
   PortName cache_[kRandomNameCacheSize];
   size_t cache_index_ = kRandomNameCacheSize;
-
-  DISALLOW_COPY_AND_ASSIGN(RandomNameGenerator);
 };
 
 base::LazyInstance<RandomNameGenerator>::Leaky g_name_generator =
diff --git a/mojo/core/ports/node.h b/mojo/core/ports/node.h
index e806e1d..70dea61 100644
--- a/mojo/core/ports/node.h
+++ b/mojo/core/ports/node.h
@@ -75,6 +75,10 @@
 
   // Does not take ownership of the delegate.
   Node(const NodeName& name, NodeDelegate* delegate);
+
+  Node(const Node&) = delete;
+  Node& operator=(const Node&) = delete;
+
   ~Node();
 
   // Returns true iff there are no open ports referring to another node or ports
@@ -185,6 +189,10 @@
   class DelegateHolder {
    public:
     DelegateHolder(Node* node, NodeDelegate* delegate);
+
+    DelegateHolder(const DelegateHolder&) = delete;
+    DelegateHolder& operator=(const DelegateHolder&) = delete;
+
     ~DelegateHolder();
 
     NodeDelegate* operator->() const {
@@ -201,8 +209,6 @@
 
     Node* const node_;
     NodeDelegate* const delegate_;
-
-    DISALLOW_COPY_AND_ASSIGN(DelegateHolder);
   };
 
   int OnUserMessage(std::unique_ptr<UserMessageEvent> message);
@@ -310,8 +316,6 @@
   // port on a peer node. The key to this map is the corresponding peer node
   // name.
   std::unordered_map<NodeName, PeerPortMap> peer_port_maps_;
-
-  DISALLOW_COPY_AND_ASSIGN(Node);
 };
 
 }  // namespace ports
diff --git a/mojo/core/ports/port_locker.h b/mojo/core/ports/port_locker.h
index 0da2654..3ee349d 100644
--- a/mojo/core/ports/port_locker.h
+++ b/mojo/core/ports/port_locker.h
@@ -29,6 +29,10 @@
   // |PortRef*|s. The sequence may be reordered by this constructor, and upon
   // return, all referenced ports' locks are held.
   PortLocker(const PortRef** port_refs, size_t num_ports);
+
+  PortLocker(const PortLocker&) = delete;
+  PortLocker& operator=(const PortLocker&) = delete;
+
   ~PortLocker();
 
   // Provides safe access to a PortRef's Port. Note that in release builds this
@@ -60,14 +64,16 @@
  private:
   const PortRef** const port_refs_;
   const size_t num_ports_;
-
-  DISALLOW_COPY_AND_ASSIGN(PortLocker);
 };
 
 // Convenience wrapper for a PortLocker that locks a single port.
 class SinglePortLocker {
  public:
   explicit SinglePortLocker(const PortRef* port_ref);
+
+  SinglePortLocker(const SinglePortLocker&) = delete;
+  SinglePortLocker& operator=(const SinglePortLocker&) = delete;
+
   ~SinglePortLocker();
 
   Port* port() const { return locker_.GetPort(*port_ref_); }
@@ -75,8 +81,6 @@
  private:
   const PortRef* port_ref_;
   PortLocker locker_;
-
-  DISALLOW_COPY_AND_ASSIGN(SinglePortLocker);
 };
 
 }  // namespace ports
diff --git a/mojo/core/ports/user_message.h b/mojo/core/ports/user_message.h
index e30e316a..9a5e45cf 100644
--- a/mojo/core/ports/user_message.h
+++ b/mojo/core/ports/user_message.h
@@ -29,6 +29,10 @@
   struct TypeInfo {};
 
   explicit UserMessage(const TypeInfo* type_info);
+
+  UserMessage(const UserMessage&) = delete;
+  UserMessage& operator=(const UserMessage&) = delete;
+
   virtual ~UserMessage();
 
   const TypeInfo* type_info() const { return type_info_; }
@@ -47,8 +51,6 @@
 
  private:
   const TypeInfo* const type_info_;
-
-  DISALLOW_COPY_AND_ASSIGN(UserMessage);
 };
 
 }  // namespace ports
diff --git a/mojo/core/request_context.h b/mojo/core/request_context.h
index 89988f2..9bbfc55e 100644
--- a/mojo/core/request_context.h
+++ b/mojo/core/request_context.h
@@ -41,6 +41,10 @@
   RequestContext();
 
   explicit RequestContext(Source source);
+
+  RequestContext(const RequestContext&) = delete;
+  RequestContext& operator=(const RequestContext&) = delete;
+
   ~RequestContext();
 
   // Returns the current thread-local RequestContext.
@@ -98,8 +102,6 @@
   // global LazyInstance, accessing a LazyInstance has a large cost relative to
   // the rest of this class and its usages.
   base::ThreadLocalPointer<RequestContext>* tls_context_;
-
-  DISALLOW_COPY_AND_ASSIGN(RequestContext);
 };
 
 }  // namespace core
diff --git a/mojo/core/shared_buffer_dispatcher_unittest.cc b/mojo/core/shared_buffer_dispatcher_unittest.cc
index 108359a..84bae6bf 100644
--- a/mojo/core/shared_buffer_dispatcher_unittest.cc
+++ b/mojo/core/shared_buffer_dispatcher_unittest.cc
@@ -46,10 +46,12 @@
 class SharedBufferDispatcherTest : public testing::Test {
  public:
   SharedBufferDispatcherTest() = default;
-  ~SharedBufferDispatcherTest() override = default;
 
- private:
-  DISALLOW_COPY_AND_ASSIGN(SharedBufferDispatcherTest);
+  SharedBufferDispatcherTest(const SharedBufferDispatcherTest&) = delete;
+  SharedBufferDispatcherTest& operator=(const SharedBufferDispatcherTest&) =
+      delete;
+
+  ~SharedBufferDispatcherTest() override = default;
 };
 
 // Tests valid inputs to |ValidateCreateOptions()|.
diff --git a/mojo/core/test/mojo_test_base.h b/mojo/core/test/mojo_test_base.h
index 3eb6d9f..8b88404e 100644
--- a/mojo/core/test/mojo_test_base.h
+++ b/mojo/core/test/mojo_test_base.h
@@ -31,6 +31,10 @@
   static constexpr size_t kMaxMessageSizeInTests = 32 * 1024 * 1024;
 
   MojoTestBase();
+
+  MojoTestBase(const MojoTestBase&) = delete;
+  MojoTestBase& operator=(const MojoTestBase&) = delete;
+
   ~MojoTestBase() override;
 
   using LaunchType = MultiprocessTestHelper::LaunchType;
@@ -40,6 +44,10 @@
     ClientController(const std::string& client_name,
                      MojoTestBase* test,
                      LaunchType launch_type);
+
+    ClientController(const ClientController&) = delete;
+    ClientController& operator=(const ClientController&) = delete;
+
     ~ClientController();
 
     MojoHandle pipe() const { return pipe_.get().value(); }
@@ -54,8 +62,6 @@
 #endif
     ScopedMessagePipeHandle pipe_;
     bool was_shutdown_ = false;
-
-    DISALLOW_COPY_AND_ASSIGN(ClientController);
   };
 
   ClientController& StartClient(const std::string& client_name);
@@ -170,8 +176,6 @@
   std::vector<std::unique_ptr<ClientController>> clients_;
 
   LaunchType launch_type_ = LaunchType::CHILD;
-
-  DISALLOW_COPY_AND_ASSIGN(MojoTestBase);
 };
 
 // Use this to declare the child process's "main()" function for tests using
diff --git a/mojo/core/test/multiprocess_test_helper.h b/mojo/core/test/multiprocess_test_helper.h
index b0cc7fe..13bfc318 100644
--- a/mojo/core/test/multiprocess_test_helper.h
+++ b/mojo/core/test/multiprocess_test_helper.h
@@ -50,6 +50,10 @@
   };
 
   MultiprocessTestHelper();
+
+  MultiprocessTestHelper(const MultiprocessTestHelper&) = delete;
+  MultiprocessTestHelper& operator=(const MultiprocessTestHelper&) = delete;
+
   ~MultiprocessTestHelper();
 
   // Start a child process and run the "main" function "named" |test_child_name|
@@ -98,8 +102,6 @@
   base::Process test_child_;
 
   std::unique_ptr<IsolatedConnection> isolated_connection_;
-
-  DISALLOW_COPY_AND_ASSIGN(MultiprocessTestHelper);
 };
 
 }  // namespace test
diff --git a/mojo/core/test/test_support_impl.h b/mojo/core/test/test_support_impl.h
index 1047e912..99c422b 100644
--- a/mojo/core/test/test_support_impl.h
+++ b/mojo/core/test/test_support_impl.h
@@ -17,6 +17,10 @@
 class TestSupportImpl : public mojo::test::TestSupport {
  public:
   TestSupportImpl();
+
+  TestSupportImpl(const TestSupportImpl&) = delete;
+  TestSupportImpl& operator=(const TestSupportImpl&) = delete;
+
   ~TestSupportImpl() override;
 
   void LogPerfResult(const char* test_name,
@@ -26,9 +30,6 @@
   FILE* OpenSourceRootRelativeFile(const char* relative_path) override;
   char** EnumerateSourceRootRelativeDirectory(
       const char* relative_path) override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(TestSupportImpl);
 };
 
 }  // namespace test
diff --git a/mojo/core/trap_unittest.cc b/mojo/core/trap_unittest.cc
index 6559551..a2abcef 100644
--- a/mojo/core/trap_unittest.cc
+++ b/mojo/core/trap_unittest.cc
@@ -35,6 +35,10 @@
   using ContextCallback = base::RepeatingCallback<void(const MojoTrapEvent&)>;
 
   TriggerHelper() = default;
+
+  TriggerHelper(const TriggerHelper&) = delete;
+  TriggerHelper& operator=(const TriggerHelper&) = delete;
+
   ~TriggerHelper() = default;
 
   MojoResult CreateTrap(MojoHandle* handle) {
@@ -65,6 +69,9 @@
     explicit NotificationContext(const ContextCallback& callback)
         : callback_(callback) {}
 
+    NotificationContext(const NotificationContext&) = delete;
+    NotificationContext& operator=(const NotificationContext&) = delete;
+
     ~NotificationContext() = default;
 
     void SetCancelCallback(base::OnceClosure cancel_callback) {
@@ -81,30 +88,28 @@
    private:
     const ContextCallback callback_;
     base::OnceClosure cancel_callback_;
-
-    DISALLOW_COPY_AND_ASSIGN(NotificationContext);
   };
 
   static void Notify(const MojoTrapEvent* event) {
     reinterpret_cast<NotificationContext*>(event->trigger_context)
         ->Notify(*event);
   }
-
-  DISALLOW_COPY_AND_ASSIGN(TriggerHelper);
 };
 
 class ThreadedRunner : public base::SimpleThread {
  public:
   explicit ThreadedRunner(base::OnceClosure callback)
       : SimpleThread("ThreadedRunner"), callback_(std::move(callback)) {}
+
+  ThreadedRunner(const ThreadedRunner&) = delete;
+  ThreadedRunner& operator=(const ThreadedRunner&) = delete;
+
   ~ThreadedRunner() override = default;
 
   void Run() override { std::move(callback_).Run(); }
 
  private:
   base::OnceClosure callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(ThreadedRunner);
 };
 
 void ExpectNoNotification(const MojoTrapEvent* event) {
diff --git a/mojo/core/user_message_impl.cc b/mojo/core/user_message_impl.cc
index ec0686b..33fdbf5 100644
--- a/mojo/core/user_message_impl.cc
+++ b/mojo/core/user_message_impl.cc
@@ -284,6 +284,10 @@
         this, "MojoMessages", nullptr);
   }
 
+  MessageMemoryDumpProvider(const MessageMemoryDumpProvider&) = delete;
+  MessageMemoryDumpProvider& operator=(const MessageMemoryDumpProvider&) =
+      delete;
+
   ~MessageMemoryDumpProvider() override {
     base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
         this);
@@ -299,8 +303,6 @@
                     base::subtle::NoBarrier_Load(&g_message_count));
     return true;
   }
-
-  DISALLOW_COPY_AND_ASSIGN(MessageMemoryDumpProvider);
 };
 
 void EnsureMemoryDumpProviderExists() {
diff --git a/mojo/core/user_message_impl.h b/mojo/core/user_message_impl.h
index 118f3f6..c73b09a4 100644
--- a/mojo/core/user_message_impl.h
+++ b/mojo/core/user_message_impl.h
@@ -45,6 +45,9 @@
     kAbort,
   };
 
+  UserMessageImpl(const UserMessageImpl&) = delete;
+  UserMessageImpl& operator=(const UserMessageImpl&) = delete;
+
   ~UserMessageImpl() override;
 
   // Creates a new ports::UserMessageEvent with an attached UserMessageImpl.
@@ -213,8 +216,6 @@
   // The node name from which this message was received, iff it came from
   // out-of-process and the source is known.
   ports::NodeName source_node_ = ports::kInvalidNodeName;
-
-  DISALLOW_COPY_AND_ASSIGN(UserMessageImpl);
 };
 
 }  // namespace core
diff --git a/mojo/core/watcher_set.h b/mojo/core/watcher_set.h
index d85420ac..ecff3785 100644
--- a/mojo/core/watcher_set.h
+++ b/mojo/core/watcher_set.h
@@ -24,6 +24,10 @@
  public:
   // |owner| is the Dispatcher who owns this WatcherSet.
   explicit WatcherSet(Dispatcher* owner);
+
+  WatcherSet(const WatcherSet&) = delete;
+  WatcherSet& operator=(const WatcherSet&) = delete;
+
   ~WatcherSet();
 
   // Notifies all watchers of the handle's current signals state.
@@ -60,8 +64,6 @@
   Dispatcher* const owner_;
   base::flat_map<WatcherDispatcher*, Entry> watchers_;
   absl::optional<HandleSignalsState> last_known_state_;
-
-  DISALLOW_COPY_AND_ASSIGN(WatcherSet);
 };
 
 }  // namespace core
diff --git a/mojo/public/c/system/tests/core_perftest.cc b/mojo/public/c/system/tests/core_perftest.cc
index 947c32b7..76f1a4a 100644
--- a/mojo/public/c/system/tests/core_perftest.cc
+++ b/mojo/public/c/system/tests/core_perftest.cc
@@ -32,6 +32,10 @@
         handle_(handle),
         num_bytes_(num_bytes),
         num_writes_(0) {}
+
+  MessagePipeWriterThread(const MessagePipeWriterThread&) = delete;
+  MessagePipeWriterThread& operator=(const MessagePipeWriterThread&) = delete;
+
   ~MessagePipeWriterThread() override {}
 
   void Run() override {
@@ -62,8 +66,6 @@
   const MojoHandle handle_;
   const uint32_t num_bytes_;
   int64_t num_writes_;
-
-  DISALLOW_COPY_AND_ASSIGN(MessagePipeWriterThread);
 };
 
 class MessagePipeReaderThread : public base::SimpleThread {
@@ -72,6 +74,10 @@
       : SimpleThread("MessagePipeReaderThread"),
         handle_(handle),
         num_reads_(0) {}
+
+  MessagePipeReaderThread(const MessagePipeReaderThread&) = delete;
+  MessagePipeReaderThread& operator=(const MessagePipeReaderThread&) = delete;
+
   ~MessagePipeReaderThread() override {}
 
   void Run() override {
@@ -107,14 +113,16 @@
  private:
   const MojoHandle handle_;
   int64_t num_reads_;
-
-  DISALLOW_COPY_AND_ASSIGN(MessagePipeReaderThread);
 };
 #endif  // !defined(WIN32)
 
 class CorePerftest : public testing::Test {
  public:
   CorePerftest() {}
+
+  CorePerftest(const CorePerftest&) = delete;
+  CorePerftest& operator=(const CorePerftest&) = delete;
+
   ~CorePerftest() override {}
 
   static void NoOp(void* /*closure*/) {}
@@ -246,8 +254,6 @@
     assert(rv == 0);
   }
 #endif  // !defined(WIN32)
-
-  DISALLOW_COPY_AND_ASSIGN(CorePerftest);
 };
 
 // A no-op test so we can compare performance.
diff --git a/mojo/public/cpp/base/big_buffer.h b/mojo/public/cpp/base/big_buffer.h
index fd3e0cba..2a3a9d5 100644
--- a/mojo/public/cpp/base/big_buffer.h
+++ b/mojo/public/cpp/base/big_buffer.h
@@ -29,6 +29,11 @@
   BigBufferSharedMemoryRegion(mojo::ScopedSharedBufferHandle buffer_handle,
                               size_t size);
   BigBufferSharedMemoryRegion(BigBufferSharedMemoryRegion&& other);
+
+  BigBufferSharedMemoryRegion(const BigBufferSharedMemoryRegion&) = delete;
+  BigBufferSharedMemoryRegion& operator=(const BigBufferSharedMemoryRegion&) =
+      delete;
+
   ~BigBufferSharedMemoryRegion();
 
   BigBufferSharedMemoryRegion& operator=(BigBufferSharedMemoryRegion&& other);
@@ -45,8 +50,6 @@
   size_t size_;
   mojo::ScopedSharedBufferHandle buffer_handle_;
   mojo::ScopedSharedBufferMapping buffer_mapping_;
-
-  DISALLOW_COPY_AND_ASSIGN(BigBufferSharedMemoryRegion);
 };
 
 }  // namespace internal
@@ -93,6 +96,9 @@
   // before transfer to avoid leaking information to less privileged processes.
   explicit BigBuffer(size_t size);
 
+  BigBuffer(const BigBuffer&) = delete;
+  BigBuffer& operator=(const BigBuffer&) = delete;
+
   ~BigBuffer();
 
   BigBuffer& operator=(BigBuffer&& other);
@@ -125,8 +131,6 @@
   std::unique_ptr<uint8_t[]> bytes_;
   size_t bytes_size_;
   absl::optional<internal::BigBufferSharedMemoryRegion> shared_memory_;
-
-  DISALLOW_COPY_AND_ASSIGN(BigBuffer);
 };
 
 // Similar to BigBuffer, but doesn't *necessarily* own the buffer storage.
@@ -143,6 +147,10 @@
   // will retain an unsafe reference to |bytes| and must therefore not outlive
   // |bytes|.
   explicit BigBufferView(base::span<const uint8_t> bytes);
+
+  BigBufferView(const BigBufferView&) = delete;
+  BigBufferView& operator=(const BigBufferView&) = delete;
+
   ~BigBufferView();
 
   BigBufferView& operator=(BigBufferView&& other);
@@ -179,8 +187,6 @@
   BigBuffer::StorageType storage_type_ = BigBuffer::StorageType::kBytes;
   base::span<const uint8_t> bytes_;
   absl::optional<internal::BigBufferSharedMemoryRegion> shared_memory_;
-
-  DISALLOW_COPY_AND_ASSIGN(BigBufferView);
 };
 
 }  // namespace mojo_base
diff --git a/mojo/public/cpp/bindings/associated_interface_ptr_info.h b/mojo/public/cpp/bindings/associated_interface_ptr_info.h
index 7c4b9004..e1550758 100644
--- a/mojo/public/cpp/bindings/associated_interface_ptr_info.h
+++ b/mojo/public/cpp/bindings/associated_interface_ptr_info.h
@@ -37,6 +37,10 @@
                              uint32_t version)
       : handle_(std::move(handle)), version_(version) {}
 
+  AssociatedInterfacePtrInfo(const AssociatedInterfacePtrInfo&) = delete;
+  AssociatedInterfacePtrInfo& operator=(const AssociatedInterfacePtrInfo&) =
+      delete;
+
   ~AssociatedInterfacePtrInfo() {}
 
   AssociatedInterfacePtrInfo& operator=(AssociatedInterfacePtrInfo&& other) {
@@ -76,8 +80,6 @@
  private:
   ScopedInterfaceEndpointHandle handle_;
   uint32_t version_;
-
-  DISALLOW_COPY_AND_ASSIGN(AssociatedInterfacePtrInfo);
 };
 
 }  // namespace mojo
diff --git a/mojo/public/cpp/bindings/associated_remote.h b/mojo/public/cpp/bindings/associated_remote.h
index 988aaef..67c2085 100644
--- a/mojo/public/cpp/bindings/associated_remote.h
+++ b/mojo/public/cpp/bindings/associated_remote.h
@@ -65,6 +65,9 @@
     Bind(std::move(pending_remote), std::move(task_runner));
   }
 
+  AssociatedRemote(const AssociatedRemote&) = delete;
+  AssociatedRemote& operator=(const AssociatedRemote&) = delete;
+
   ~AssociatedRemote() = default;
 
   AssociatedRemote& operator=(AssociatedRemote&& other) noexcept {
@@ -257,8 +260,6 @@
  private:
   using State = internal::AssociatedInterfacePtrState<Interface>;
   mutable State internal_state_;
-
-  DISALLOW_COPY_AND_ASSIGN(AssociatedRemote);
 };
 
 }  // namespace mojo
diff --git a/mojo/public/cpp/bindings/callback_helpers.h b/mojo/public/cpp/bindings/callback_helpers.h
index 94bc98cc..1bcb97d 100644
--- a/mojo/public/cpp/bindings/callback_helpers.h
+++ b/mojo/public/cpp/bindings/callback_helpers.h
@@ -82,6 +82,9 @@
       : callback_(std::move(callback)),
         delete_callback_(std::move(delete_callback)) {}
 
+  CallbackWithDeleteHelper(const CallbackWithDeleteHelper&) = delete;
+  CallbackWithDeleteHelper& operator=(const CallbackWithDeleteHelper&) = delete;
+
   ~CallbackWithDeleteHelper() {
     if (delete_callback_)
       std::move(delete_callback_).Run();
@@ -95,8 +98,6 @@
  private:
   CallbackType callback_;
   base::OnceClosure delete_callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(CallbackWithDeleteHelper);
 };
 
 }  // namespace internal
diff --git a/mojo/public/cpp/bindings/connector.h b/mojo/public/cpp/bindings/connector.h
index 3975d01..c788d5a 100644
--- a/mojo/public/cpp/bindings/connector.h
+++ b/mojo/public/cpp/bindings/connector.h
@@ -96,6 +96,9 @@
             scoped_refptr<base::SequencedTaskRunner> runner,
             const char* interface_name = "unknown interface");
 
+  Connector(const Connector&) = delete;
+  Connector& operator=(const Connector&) = delete;
+
   ~Connector() override;
 
   const char* interface_name() const { return interface_name_; }
@@ -358,8 +361,6 @@
   // transferred (i.e., when |connected_| is set to false).
   base::WeakPtr<Connector> weak_self_;
   base::WeakPtrFactory<Connector> weak_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(Connector);
 };
 
 }  // namespace mojo
diff --git a/mojo/public/cpp/bindings/generic_pending_receiver.h b/mojo/public/cpp/bindings/generic_pending_receiver.h
index a7392438..e190c29 100644
--- a/mojo/public/cpp/bindings/generic_pending_receiver.h
+++ b/mojo/public/cpp/bindings/generic_pending_receiver.h
@@ -38,6 +38,10 @@
       : GenericPendingReceiver(Interface::Name_, request.PassMessagePipe()) {}
 
   GenericPendingReceiver(GenericPendingReceiver&&);
+
+  GenericPendingReceiver(const GenericPendingReceiver&) = delete;
+  GenericPendingReceiver& operator=(const GenericPendingReceiver&) = delete;
+
   ~GenericPendingReceiver();
 
   GenericPendingReceiver& operator=(GenericPendingReceiver&&);
@@ -69,8 +73,6 @@
 
   absl::optional<std::string> interface_name_;
   mojo::ScopedMessagePipeHandle pipe_;
-
-  DISALLOW_COPY_AND_ASSIGN(GenericPendingReceiver);
 };
 
 }  // namespace mojo
diff --git a/mojo/public/cpp/bindings/interface_endpoint_client.h b/mojo/public/cpp/bindings/interface_endpoint_client.h
index 68963ea1..957b709a 100644
--- a/mojo/public/cpp/bindings/interface_endpoint_client.h
+++ b/mojo/public/cpp/bindings/interface_endpoint_client.h
@@ -60,6 +60,10 @@
                           scoped_refptr<base::SequencedTaskRunner> task_runner,
                           uint32_t interface_version,
                           const char* interface_name);
+
+  InterfaceEndpointClient(const InterfaceEndpointClient&) = delete;
+  InterfaceEndpointClient& operator=(const InterfaceEndpointClient&) = delete;
+
   ~InterfaceEndpointClient() override;
 
   // Sets the error handler to receive notifications when an error is
@@ -217,15 +221,16 @@
   struct SyncResponseInfo {
    public:
     explicit SyncResponseInfo(bool* in_response_received);
+
+    SyncResponseInfo(const SyncResponseInfo&) = delete;
+    SyncResponseInfo& operator=(const SyncResponseInfo&) = delete;
+
     ~SyncResponseInfo();
 
     Message response;
 
     // Points to a stack-allocated variable.
     bool* response_received;
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(SyncResponseInfo);
   };
 
   using SyncResponseMap = std::map<uint64_t, std::unique_ptr<SyncResponseInfo>>;
@@ -235,6 +240,11 @@
   class HandleIncomingMessageThunk : public MessageReceiver {
    public:
     explicit HandleIncomingMessageThunk(InterfaceEndpointClient* owner);
+
+    HandleIncomingMessageThunk(const HandleIncomingMessageThunk&) = delete;
+    HandleIncomingMessageThunk& operator=(const HandleIncomingMessageThunk&) =
+        delete;
+
     ~HandleIncomingMessageThunk() override;
 
     // MessageReceiver implementation:
@@ -242,8 +252,6 @@
 
    private:
     InterfaceEndpointClient* const owner_;
-
-    DISALLOW_COPY_AND_ASSIGN(HandleIncomingMessageThunk);
   };
 
   void InitControllerIfNecessary();
@@ -317,8 +325,6 @@
   SEQUENCE_CHECKER(sequence_checker_);
 
   base::WeakPtrFactory<InterfaceEndpointClient> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(InterfaceEndpointClient);
 };
 
 }  // namespace mojo
diff --git a/mojo/public/cpp/bindings/interface_ptr.h b/mojo/public/cpp/bindings/interface_ptr.h
index 6745a32b..311cd58 100644
--- a/mojo/public/cpp/bindings/interface_ptr.h
+++ b/mojo/public/cpp/bindings/interface_ptr.h
@@ -77,6 +77,9 @@
     return *this;
   }
 
+  InterfacePtr(const InterfacePtr&) = delete;
+  InterfacePtr& operator=(const InterfacePtr&) = delete;
+
   // Closes the bound message pipe (if any) on destruction.
   ~InterfacePtr() {}
 
@@ -224,8 +227,6 @@
  private:
   typedef internal::InterfacePtrState<Interface> State;
   mutable State internal_state_;
-
-  DISALLOW_COPY_AND_ASSIGN(InterfacePtr);
 };
 
 // If |info| is valid (containing a valid message pipe handle), returns an
diff --git a/mojo/public/cpp/bindings/interface_ptr_info.h b/mojo/public/cpp/bindings/interface_ptr_info.h
index ab07923..632777c1 100644
--- a/mojo/public/cpp/bindings/interface_ptr_info.h
+++ b/mojo/public/cpp/bindings/interface_ptr_info.h
@@ -33,6 +33,9 @@
 
   InterfacePtrInfo(InterfacePtrInfo&& other) = default;
 
+  InterfacePtrInfo(const InterfacePtrInfo&) = delete;
+  InterfacePtrInfo& operator=(const InterfacePtrInfo&) = delete;
+
   ~InterfacePtrInfo() {}
 
   InterfacePtrInfo& operator=(InterfacePtrInfo&& other) = default;
@@ -55,8 +58,6 @@
 
  private:
   internal::PendingRemoteState state_;
-
-  DISALLOW_COPY_AND_ASSIGN(InterfacePtrInfo);
 };
 
 }  // namespace mojo
diff --git a/mojo/public/cpp/bindings/lib/binder_map_internal.h b/mojo/public/cpp/bindings/lib/binder_map_internal.h
index 4200f30..6b75f5e6 100644
--- a/mojo/public/cpp/bindings/lib/binder_map_internal.h
+++ b/mojo/public/cpp/bindings/lib/binder_map_internal.h
@@ -82,6 +82,11 @@
       scoped_refptr<base::SequencedTaskRunner> task_runner)
       : callback_(std::move(callback)), task_runner_(std::move(task_runner)) {}
 
+  GenericCallbackBinderWithContext(const GenericCallbackBinderWithContext&) =
+      delete;
+  GenericCallbackBinderWithContext& operator=(
+      const GenericCallbackBinderWithContext&) = delete;
+
   ~GenericCallbackBinderWithContext() = default;
 
   void BindInterface(ContextValueType context,
@@ -123,7 +128,6 @@
 
   const GenericBinderType callback_;
   const scoped_refptr<base::SequencedTaskRunner> task_runner_;
-  DISALLOW_COPY_AND_ASSIGN(GenericCallbackBinderWithContext);
 };
 
 }  // namespace internal
diff --git a/mojo/public/cpp/bindings/lib/binding_state.h b/mojo/public/cpp/bindings/lib/binding_state.h
index e111ffa..25e735c 100644
--- a/mojo/public/cpp/bindings/lib/binding_state.h
+++ b/mojo/public/cpp/bindings/lib/binding_state.h
@@ -111,6 +111,9 @@
     stub_.set_sink(std::move(impl));
   }
 
+  BindingState(const BindingState&) = delete;
+  BindingState& operator=(const BindingState&) = delete;
+
   ~BindingState() { Close(); }
 
   void Bind(PendingReceiverState* receiver_state,
@@ -139,8 +142,6 @@
 
  private:
   typename Interface::template Stub_<ImplRefTraits> stub_;
-
-  DISALLOW_COPY_AND_ASSIGN(BindingState);
 };
 
 }  // namespace internal
diff --git a/mojo/public/cpp/bindings/lib/buffer.h b/mojo/public/cpp/bindings/lib/buffer.h
index 9327dbb..3536af9 100644
--- a/mojo/public/cpp/bindings/lib/buffer.h
+++ b/mojo/public/cpp/bindings/lib/buffer.h
@@ -53,6 +53,10 @@
          size_t size);
 
   Buffer(Buffer&& other);
+
+  Buffer(const Buffer&) = delete;
+  Buffer& operator=(const Buffer&) = delete;
+
   ~Buffer();
 
   Buffer& operator=(Buffer&& other);
@@ -122,8 +126,6 @@
   // The current write offset into |data_| if this Buffer is being used for
   // message creation.
   size_t cursor_ = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(Buffer);
 };
 
 }  // namespace internal
diff --git a/mojo/public/cpp/bindings/lib/connector.cc b/mojo/public/cpp/bindings/lib/connector.cc
index 92a9756..c1d111c 100644
--- a/mojo/public/cpp/bindings/lib/connector.cc
+++ b/mojo/public/cpp/bindings/lib/connector.cc
@@ -66,6 +66,10 @@
 class Connector::ActiveDispatchTracker {
  public:
   explicit ActiveDispatchTracker(const base::WeakPtr<Connector>& connector);
+
+  ActiveDispatchTracker(const ActiveDispatchTracker&) = delete;
+  ActiveDispatchTracker& operator=(const ActiveDispatchTracker&) = delete;
+
   ~ActiveDispatchTracker();
 
   void NotifyBeginNesting();
@@ -75,8 +79,6 @@
   RunLoopNestingObserver* const nesting_observer_;
   ActiveDispatchTracker* outer_tracker_ = nullptr;
   ActiveDispatchTracker* inner_tracker_ = nullptr;
-
-  DISALLOW_COPY_AND_ASSIGN(ActiveDispatchTracker);
 };
 
 // Watches the MessageLoop on the current thread. Notifies the current chain of
@@ -88,6 +90,9 @@
     base::RunLoop::AddNestingObserverOnCurrentThread(this);
   }
 
+  RunLoopNestingObserver(const RunLoopNestingObserver&) = delete;
+  RunLoopNestingObserver& operator=(const RunLoopNestingObserver&) = delete;
+
   ~RunLoopNestingObserver() override {
     base::RunLoop::RemoveNestingObserverOnCurrentThread(this);
   }
@@ -113,8 +118,6 @@
   friend class ActiveDispatchTracker;
 
   ActiveDispatchTracker* top_tracker_ = nullptr;
-
-  DISALLOW_COPY_AND_ASSIGN(RunLoopNestingObserver);
 };
 
 Connector::ActiveDispatchTracker::ActiveDispatchTracker(
diff --git a/mojo/public/cpp/bindings/lib/control_message_handler.h b/mojo/public/cpp/bindings/lib/control_message_handler.h
index aee16cb..cc9bf19 100644
--- a/mojo/public/cpp/bindings/lib/control_message_handler.h
+++ b/mojo/public/cpp/bindings/lib/control_message_handler.h
@@ -25,6 +25,10 @@
 
   ControlMessageHandler(InterfaceEndpointClient* owner,
                         uint32_t interface_version);
+
+  ControlMessageHandler(const ControlMessageHandler&) = delete;
+  ControlMessageHandler& operator=(const ControlMessageHandler&) = delete;
+
   ~ControlMessageHandler() override;
 
   // Call the following methods only if IsControlMessage() returned true.
@@ -40,8 +44,6 @@
 
   InterfaceEndpointClient* const owner_;
   uint32_t interface_version_;
-
-  DISALLOW_COPY_AND_ASSIGN(ControlMessageHandler);
 };
 
 }  // namespace internal
diff --git a/mojo/public/cpp/bindings/lib/control_message_proxy.h b/mojo/public/cpp/bindings/lib/control_message_proxy.h
index b6d7cc8..6d766e3 100644
--- a/mojo/public/cpp/bindings/lib/control_message_proxy.h
+++ b/mojo/public/cpp/bindings/lib/control_message_proxy.h
@@ -26,6 +26,10 @@
  public:
   // Doesn't take ownership of |owner|. It must outlive this object.
   explicit ControlMessageProxy(InterfaceEndpointClient* owner);
+
+  ControlMessageProxy(const ControlMessageProxy&) = delete;
+  ControlMessageProxy& operator=(const ControlMessageProxy&) = delete;
+
   ~ControlMessageProxy();
 
   void QueryVersion(base::OnceCallback<void(uint32_t)> callback);
@@ -48,8 +52,6 @@
   bool encountered_error_ = false;
 
   base::OnceClosure pending_flush_callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(ControlMessageProxy);
 };
 
 }  // namespace internal
diff --git a/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc b/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc
index 4e8d1c3..a9dfb63 100644
--- a/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc
+++ b/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc
@@ -233,6 +233,10 @@
       : endpoint_client_(endpoint_client),
         accept_was_invoked_(false),
         task_runner_(std::move(runner)) {}
+
+  ResponderThunk(const ResponderThunk&) = delete;
+  ResponderThunk& operator=(const ResponderThunk&) = delete;
+
   ~ResponderThunk() override {
     if (!accept_was_invoked_) {
       // The Service handled a message that was expecting a response
@@ -301,8 +305,6 @@
   bool accept_was_invoked_;
   scoped_refptr<base::SequencedTaskRunner> task_runner_;
   ConnectionGroup::Ref connection_group_;
-
-  DISALLOW_COPY_AND_ASSIGN(ResponderThunk);
 };
 
 }  // namespace
diff --git a/mojo/public/cpp/bindings/lib/interface_ptr_state.h b/mojo/public/cpp/bindings/lib/interface_ptr_state.h
index f43f651..606a85b 100644
--- a/mojo/public/cpp/bindings/lib/interface_ptr_state.h
+++ b/mojo/public/cpp/bindings/lib/interface_ptr_state.h
@@ -40,6 +40,10 @@
 class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) InterfacePtrStateBase {
  public:
   InterfacePtrStateBase();
+
+  InterfacePtrStateBase(const InterfacePtrStateBase&) = delete;
+  InterfacePtrStateBase& operator=(const InterfacePtrStateBase&) = delete;
+
   ~InterfacePtrStateBase();
 
   MessagePipeHandle handle() const {
@@ -115,8 +119,6 @@
   scoped_refptr<base::SequencedTaskRunner> runner_;
 
   uint32_t version_ = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(InterfacePtrStateBase);
 };
 
 template <typename Interface>
@@ -125,6 +127,10 @@
   using Proxy = typename Interface::Proxy_;
 
   InterfacePtrState() = default;
+
+  InterfacePtrState(const InterfacePtrState&) = delete;
+  InterfacePtrState& operator=(const InterfacePtrState&) = delete;
+
   ~InterfacePtrState() = default;
 
   Proxy* instance() {
@@ -256,8 +262,6 @@
   }
 
   std::unique_ptr<Proxy> proxy_;
-
-  DISALLOW_COPY_AND_ASSIGN(InterfacePtrState);
 };
 
 }  // namespace internal
diff --git a/mojo/public/cpp/bindings/lib/may_auto_lock.h b/mojo/public/cpp/bindings/lib/may_auto_lock.h
index 96fb8d2..bcd913d 100644
--- a/mojo/public/cpp/bindings/lib/may_auto_lock.h
+++ b/mojo/public/cpp/bindings/lib/may_auto_lock.h
@@ -23,6 +23,9 @@
       lock_->Acquire();
   }
 
+  MayAutoLock(const MayAutoLock&) = delete;
+  MayAutoLock& operator=(const MayAutoLock&) = delete;
+
   ~MayAutoLock() {
     if (lock_) {
       lock_->AssertAcquired();
@@ -32,7 +35,6 @@
 
  private:
   base::Lock* lock_;
-  DISALLOW_COPY_AND_ASSIGN(MayAutoLock);
 };
 
 // Similar to base::AutoUnlock, except that it does nothing if |lock| passed
@@ -47,6 +49,9 @@
     }
   }
 
+  MayAutoUnlock(const MayAutoUnlock&) = delete;
+  MayAutoUnlock& operator=(const MayAutoUnlock&) = delete;
+
   ~MayAutoUnlock() {
     if (lock_)
       lock_->Acquire();
@@ -54,7 +59,6 @@
 
  private:
   base::Lock* lock_;
-  DISALLOW_COPY_AND_ASSIGN(MayAutoUnlock);
 };
 
 }  // namespace internal
diff --git a/mojo/public/cpp/bindings/lib/message_internal.h b/mojo/public/cpp/bindings/lib/message_internal.h
index 1703786..f35e95c5 100644
--- a/mojo/public/cpp/bindings/lib/message_internal.h
+++ b/mojo/public/cpp/bindings/lib/message_internal.h
@@ -59,6 +59,10 @@
 class COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) MessageDispatchContext {
  public:
   explicit MessageDispatchContext(Message* message);
+
+  MessageDispatchContext(const MessageDispatchContext&) = delete;
+  MessageDispatchContext& operator=(const MessageDispatchContext&) = delete;
+
   ~MessageDispatchContext();
 
   static MessageDispatchContext* current();
@@ -68,8 +72,6 @@
  private:
   MessageDispatchContext* outer_context_;
   Message* message_;
-
-  DISALLOW_COPY_AND_ASSIGN(MessageDispatchContext);
 };
 
 COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE)
diff --git a/mojo/public/cpp/bindings/lib/multiplex_router.cc b/mojo/public/cpp/bindings/lib/multiplex_router.cc
index 605e513..e7b6788 100644
--- a/mojo/public/cpp/bindings/lib/multiplex_router.cc
+++ b/mojo/public/cpp/bindings/lib/multiplex_router.cc
@@ -264,6 +264,9 @@
   MessageWrapper(MessageWrapper&& other)
       : router_(other.router_), value_(std::move(other.value_)) {}
 
+  MessageWrapper(const MessageWrapper&) = delete;
+  MessageWrapper& operator=(const MessageWrapper&) = delete;
+
   ~MessageWrapper() {
     if (!router_ || value_.IsNull())
       return;
@@ -300,8 +303,6 @@
  private:
   MultiplexRouter* router_ = nullptr;
   Message value_;
-
-  DISALLOW_COPY_AND_ASSIGN(MessageWrapper);
 };
 
 struct MultiplexRouter::Task {
diff --git a/mojo/public/cpp/bindings/lib/sequence_local_sync_event_watcher.cc b/mojo/public/cpp/bindings/lib/sequence_local_sync_event_watcher.cc
index 03ff19e3..f955f57 100644
--- a/mojo/public/cpp/bindings/lib/sequence_local_sync_event_watcher.cc
+++ b/mojo/public/cpp/bindings/lib/sequence_local_sync_event_watcher.cc
@@ -67,6 +67,9 @@
     event_watcher_.AllowWokenUpBySyncWatchOnSameThread();
   }
 
+  SequenceLocalState(const SequenceLocalState&) = delete;
+  SequenceLocalState& operator=(const SequenceLocalState&) = delete;
+
   ~SequenceLocalState() {}
 
   // Initializes a SequenceLocalState instance in sequence-local storage if
@@ -196,8 +199,6 @@
   base::flat_set<const SequenceLocalSyncEventWatcher*> ready_watchers_;
 
   base::WeakPtrFactory<SequenceLocalState> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(SequenceLocalState);
 };
 
 void SequenceLocalSyncEventWatcher::SequenceLocalState::OnEventSignaled() {
@@ -235,6 +236,9 @@
         watcher_state_iterator_(shared_state_->RegisterWatcher(watcher)),
         watcher_state_(watcher_state_iterator_->second) {}
 
+  Registration(const Registration&) = delete;
+  Registration& operator=(const Registration&) = delete;
+
   ~Registration() {
     if (weak_shared_state_) {
       // Because |this| may itself be owned by sequence- or thread-local storage
@@ -257,8 +261,6 @@
   SequenceLocalState* const shared_state_;
   WatcherStateMap::iterator watcher_state_iterator_;
   const scoped_refptr<WatcherState> watcher_state_;
-
-  DISALLOW_COPY_AND_ASSIGN(Registration);
 };
 
 SequenceLocalSyncEventWatcher::SequenceLocalSyncEventWatcher(
diff --git a/mojo/public/cpp/bindings/lib/sync_call_restrictions.cc b/mojo/public/cpp/bindings/lib/sync_call_restrictions.cc
index 45103af..fbc73a50 100644
--- a/mojo/public/cpp/bindings/lib/sync_call_restrictions.cc
+++ b/mojo/public/cpp/bindings/lib/sync_call_restrictions.cc
@@ -22,6 +22,10 @@
 class GlobalSyncCallSettings {
  public:
   GlobalSyncCallSettings() = default;
+
+  GlobalSyncCallSettings(const GlobalSyncCallSettings&) = delete;
+  GlobalSyncCallSettings& operator=(const GlobalSyncCallSettings&) = delete;
+
   ~GlobalSyncCallSettings() = default;
 
   bool sync_call_allowed_by_default() const {
@@ -37,8 +41,6 @@
  private:
   mutable base::Lock lock_;
   bool sync_call_allowed_by_default_ = true;
-
-  DISALLOW_COPY_AND_ASSIGN(GlobalSyncCallSettings);
 };
 
 GlobalSyncCallSettings& GetGlobalSettings() {
diff --git a/mojo/public/cpp/bindings/lib/unserialized_message_context.h b/mojo/public/cpp/bindings/lib/unserialized_message_context.h
index baac620..188baab3 100644
--- a/mojo/public/cpp/bindings/lib/unserialized_message_context.h
+++ b/mojo/public/cpp/bindings/lib/unserialized_message_context.h
@@ -23,6 +23,11 @@
   UnserializedMessageContext(const Tag* tag,
                              uint32_t message_name,
                              uint32_t message_flags);
+
+  UnserializedMessageContext(const UnserializedMessageContext&) = delete;
+  UnserializedMessageContext& operator=(const UnserializedMessageContext&) =
+      delete;
+
   virtual ~UnserializedMessageContext();
 
   template <typename MessageType>
@@ -50,8 +55,6 @@
   // Message implementation which needs to query such metadata for both
   // serialized and unserialized message objects.
   MessageHeaderV1 header_;
-
-  DISALLOW_COPY_AND_ASSIGN(UnserializedMessageContext);
 };
 
 }  // namespace internal
diff --git a/mojo/public/cpp/bindings/lib/validate_params.h b/mojo/public/cpp/bindings/lib/validate_params.h
index c0ee8e02..540cbd9b 100644
--- a/mojo/public/cpp/bindings/lib/validate_params.h
+++ b/mojo/public/cpp/bindings/lib/validate_params.h
@@ -49,6 +49,9 @@
       : expected_num_elements(in_expected_num_elements),
         validate_enum_func(in_validate_enum_func) {}
 
+  ContainerValidateParams(const ContainerValidateParams&) = delete;
+  ContainerValidateParams& operator=(const ContainerValidateParams&) = delete;
+
   ~ContainerValidateParams() {
     if (element_validate_params)
       delete element_validate_params;
@@ -77,9 +80,6 @@
 
   // Validation function for enum elements.
   ValidateEnumFunc validate_enum_func = nullptr;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ContainerValidateParams);
 };
 
 }  // namespace internal
diff --git a/mojo/public/cpp/bindings/lib/validation_context.h b/mojo/public/cpp/bindings/lib/validation_context.h
index a0e8a03..2584c26 100644
--- a/mojo/public/cpp/bindings/lib/validation_context.h
+++ b/mojo/public/cpp/bindings/lib/validation_context.h
@@ -56,6 +56,9 @@
                     const char* description,
                     ValidatorType validator_type);
 
+  ValidationContext(const ValidationContext&) = delete;
+  ValidationContext& operator=(const ValidationContext&) = delete;
+
   ~ValidationContext();
 
   // Claims the specified memory range.
@@ -134,12 +137,13 @@
       ++ctx_->stack_depth_;
     }
 
+    ScopedDepthTracker(const ScopedDepthTracker&) = delete;
+    ScopedDepthTracker& operator=(const ScopedDepthTracker&) = delete;
+
     ~ScopedDepthTracker() { --ctx_->stack_depth_; }
 
    private:
     ValidationContext* ctx_;
-
-    DISALLOW_COPY_AND_ASSIGN(ScopedDepthTracker);
   };
 
   // Returns true if the recursion depth limit has been reached.
@@ -174,8 +178,6 @@
   uint32_t associated_endpoint_handle_end_;
 
   int stack_depth_;
-
-  DISALLOW_COPY_AND_ASSIGN(ValidationContext);
 };
 
 }  // namespace internal
diff --git a/mojo/public/cpp/bindings/lib/validation_errors.h b/mojo/public/cpp/bindings/lib/validation_errors.h
index e7fc871..e451d85 100644
--- a/mojo/public/cpp/bindings/lib/validation_errors.h
+++ b/mojo/public/cpp/bindings/lib/validation_errors.h
@@ -99,12 +99,16 @@
     ScopedSuppressValidationErrorLoggingForTests {
  public:
   ScopedSuppressValidationErrorLoggingForTests();
+
+  ScopedSuppressValidationErrorLoggingForTests(
+      const ScopedSuppressValidationErrorLoggingForTests&) = delete;
+  ScopedSuppressValidationErrorLoggingForTests& operator=(
+      const ScopedSuppressValidationErrorLoggingForTests&) = delete;
+
   ~ScopedSuppressValidationErrorLoggingForTests();
 
  private:
   const bool was_suppressed_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedSuppressValidationErrorLoggingForTests);
 };
 
 // Only used by validation tests and when there is only one thread doing message
@@ -113,6 +117,12 @@
     ValidationErrorObserverForTesting {
  public:
   explicit ValidationErrorObserverForTesting(base::RepeatingClosure callback);
+
+  ValidationErrorObserverForTesting(const ValidationErrorObserverForTesting&) =
+      delete;
+  ValidationErrorObserverForTesting& operator=(
+      const ValidationErrorObserverForTesting&) = delete;
+
   ~ValidationErrorObserverForTesting();
 
   ValidationError last_error() const { return last_error_; }
@@ -124,8 +134,6 @@
  private:
   ValidationError last_error_;
   base::RepeatingClosure callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(ValidationErrorObserverForTesting);
 };
 
 // Used only by MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING. Don't use it directly.
@@ -141,6 +149,12 @@
     SerializationWarningObserverForTesting {
  public:
   SerializationWarningObserverForTesting();
+
+  SerializationWarningObserverForTesting(
+      const SerializationWarningObserverForTesting&) = delete;
+  SerializationWarningObserverForTesting& operator=(
+      const SerializationWarningObserverForTesting&) = delete;
+
   ~SerializationWarningObserverForTesting();
 
   ValidationError last_warning() const { return last_warning_; }
@@ -148,8 +162,6 @@
 
  private:
   ValidationError last_warning_;
-
-  DISALLOW_COPY_AND_ASSIGN(SerializationWarningObserverForTesting);
 };
 
 // Used to record that Deserialize() of a Mojo string failed because it was not
diff --git a/mojo/public/cpp/bindings/message.h b/mojo/public/cpp/bindings/message.h
index 70723f6..52b0d765 100644
--- a/mojo/public/cpp/bindings/message.h
+++ b/mojo/public/cpp/bindings/message.h
@@ -104,6 +104,9 @@
   // calling IsNull() on it will return |true|).
   static Message CreateFromMessageHandle(ScopedMessageHandle* message_handle);
 
+  Message(const Message&) = delete;
+  Message& operator=(const Message&) = delete;
+
   ~Message();
 
   // Moves |other| into a new Message object. The moved-from Message becomes
@@ -297,8 +300,6 @@
   const char* interface_name_ = nullptr;
   const char* method_name_ = nullptr;
 #endif
-
-  DISALLOW_COPY_AND_ASSIGN(Message);
 };
 
 class COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) MessageFilter {
@@ -381,13 +382,14 @@
     : public MessageReceiver {
  public:
   PassThroughFilter();
+
+  PassThroughFilter(const PassThroughFilter&) = delete;
+  PassThroughFilter& operator=(const PassThroughFilter&) = delete;
+
   ~PassThroughFilter() override;
 
   // MessageReceiver:
   bool Accept(Message* message) override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(PassThroughFilter);
 };
 
 // Reports the currently dispatching Message as bad. Note that this is only
diff --git a/mojo/public/cpp/bindings/message_dispatcher.h b/mojo/public/cpp/bindings/message_dispatcher.h
index a279418..7dc8dffc 100644
--- a/mojo/public/cpp/bindings/message_dispatcher.h
+++ b/mojo/public/cpp/bindings/message_dispatcher.h
@@ -26,6 +26,10 @@
 
   MessageDispatcher(MessageDispatcher&& other);
   MessageDispatcher& operator=(MessageDispatcher&& other);
+
+  MessageDispatcher(const MessageDispatcher&) = delete;
+  MessageDispatcher& operator=(const MessageDispatcher&) = delete;
+
   ~MessageDispatcher() override;
 
   void SetValidator(std::unique_ptr<MessageReceiver> validator);
@@ -45,8 +49,6 @@
   MessageReceiver* sink_;
 
   base::WeakPtrFactory<MessageDispatcher> weak_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(MessageDispatcher);
 };
 
 }  // namespace mojo
diff --git a/mojo/public/cpp/bindings/pending_associated_receiver.h b/mojo/public/cpp/bindings/pending_associated_receiver.h
index fb6837c..69fffe9d 100644
--- a/mojo/public/cpp/bindings/pending_associated_receiver.h
+++ b/mojo/public/cpp/bindings/pending_associated_receiver.h
@@ -59,6 +59,10 @@
                 std::move(other))) {}
 #endif  // !defined(OS_NACL)
 
+  PendingAssociatedReceiver(const PendingAssociatedReceiver&) = delete;
+  PendingAssociatedReceiver& operator=(const PendingAssociatedReceiver&) =
+      delete;
+
   ~PendingAssociatedReceiver() = default;
 
   PendingAssociatedReceiver& operator=(PendingAssociatedReceiver&& other) {
@@ -121,8 +125,6 @@
 
  private:
   ScopedInterfaceEndpointHandle handle_;
-
-  DISALLOW_COPY_AND_ASSIGN(PendingAssociatedReceiver);
 };
 
 // Constructs an invalid PendingAssociatedReceiver of any arbitrary interface
diff --git a/mojo/public/cpp/bindings/pending_associated_remote.h b/mojo/public/cpp/bindings/pending_associated_remote.h
index bb68431..72ee1ccc 100644
--- a/mojo/public/cpp/bindings/pending_associated_remote.h
+++ b/mojo/public/cpp/bindings/pending_associated_remote.h
@@ -59,6 +59,9 @@
                 std::move(other))) {}
 #endif  // !defined(OS_NACL)
 
+  PendingAssociatedRemote(const PendingAssociatedRemote&) = delete;
+  PendingAssociatedRemote& operator=(const PendingAssociatedRemote&) = delete;
+
   ~PendingAssociatedRemote() = default;
 
   PendingAssociatedRemote& operator=(PendingAssociatedRemote&& other) {
@@ -118,8 +121,6 @@
  private:
   ScopedInterfaceEndpointHandle handle_;
   uint32_t version_ = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(PendingAssociatedRemote);
 };
 
 // Constructs an invalid PendingAssociatedRemote of any arbitrary interface
diff --git a/mojo/public/cpp/bindings/pending_receiver.h b/mojo/public/cpp/bindings/pending_receiver.h
index 9ca1d24..108bb79 100644
--- a/mojo/public/cpp/bindings/pending_receiver.h
+++ b/mojo/public/cpp/bindings/pending_receiver.h
@@ -80,6 +80,9 @@
             std::forward<T>(other))) {}
 #endif  // !defined(OS_NACL)
 
+  PendingReceiver(const PendingReceiver&) = delete;
+  PendingReceiver& operator=(const PendingReceiver&) = delete;
+
   ~PendingReceiver() = default;
 
   PendingReceiver& operator=(PendingReceiver&&) noexcept = default;
@@ -144,8 +147,6 @@
 
  private:
   internal::PendingReceiverState state_;
-
-  DISALLOW_COPY_AND_ASSIGN(PendingReceiver);
 };
 
 class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) NullReceiver {
diff --git a/mojo/public/cpp/bindings/pending_remote.h b/mojo/public/cpp/bindings/pending_remote.h
index d6448cb..aec4e89 100644
--- a/mojo/public/cpp/bindings/pending_remote.h
+++ b/mojo/public/cpp/bindings/pending_remote.h
@@ -81,6 +81,9 @@
             std::move(other))) {}
 #endif  // !defined(OS_NACL)
 
+  PendingRemote(const PendingRemote&) = delete;
+  PendingRemote& operator=(const PendingRemote&) = delete;
+
   ~PendingRemote() = default;
 
   PendingRemote& operator=(PendingRemote&&) noexcept = default;
@@ -129,8 +132,6 @@
 
  private:
   internal::PendingRemoteState state_;
-
-  DISALLOW_COPY_AND_ASSIGN(PendingRemote);
 };
 
 class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) NullRemote {
diff --git a/mojo/public/cpp/bindings/pipe_control_message_handler.h b/mojo/public/cpp/bindings/pipe_control_message_handler.h
index bf2bd78..7ce1ab3 100644
--- a/mojo/public/cpp/bindings/pipe_control_message_handler.h
+++ b/mojo/public/cpp/bindings/pipe_control_message_handler.h
@@ -22,6 +22,11 @@
  public:
   explicit PipeControlMessageHandler(
       PipeControlMessageHandlerDelegate* delegate);
+
+  PipeControlMessageHandler(const PipeControlMessageHandler&) = delete;
+  PipeControlMessageHandler& operator=(const PipeControlMessageHandler&) =
+      delete;
+
   ~PipeControlMessageHandler() override;
 
   // Sets the description for this handler. Used only when reporting validation
@@ -46,8 +51,6 @@
 
   std::string description_;
   PipeControlMessageHandlerDelegate* const delegate_;
-
-  DISALLOW_COPY_AND_ASSIGN(PipeControlMessageHandler);
 };
 
 }  // namespace mojo
diff --git a/mojo/public/cpp/bindings/receiver.h b/mojo/public/cpp/bindings/receiver.h
index 87818aa..acb9d5c 100644
--- a/mojo/public/cpp/bindings/receiver.h
+++ b/mojo/public/cpp/bindings/receiver.h
@@ -74,6 +74,9 @@
     Bind(std::move(pending_receiver), std::move(task_runner));
   }
 
+  Receiver(const Receiver&) = delete;
+  Receiver& operator=(const Receiver&) = delete;
+
   ~Receiver() = default;
 
   // Indicates whether this Receiver is bound, meaning it may continue to
@@ -301,8 +304,6 @@
 
  private:
   internal::BindingState<Interface, ImplRefTraits> internal_state_;
-
-  DISALLOW_COPY_AND_ASSIGN(Receiver);
 };
 
 }  // namespace mojo
diff --git a/mojo/public/cpp/bindings/remote.h b/mojo/public/cpp/bindings/remote.h
index b7a614f..2691bad 100644
--- a/mojo/public/cpp/bindings/remote.h
+++ b/mojo/public/cpp/bindings/remote.h
@@ -84,6 +84,9 @@
     Bind(std::move(pending_remote), std::move(task_runner));
   }
 
+  Remote(const Remote&) = delete;
+  Remote& operator=(const Remote&) = delete;
+
   ~Remote() = default;
 
   Remote& operator=(Remote&& other) noexcept {
@@ -385,8 +388,6 @@
  private:
   using State = internal::InterfacePtrState<Interface>;
   mutable State internal_state_;
-
-  DISALLOW_COPY_AND_ASSIGN(Remote);
 };
 
 }  // namespace mojo
diff --git a/mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h b/mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h
index 78a6313..a3a8e903 100644
--- a/mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h
+++ b/mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h
@@ -37,6 +37,10 @@
 
   ScopedInterfaceEndpointHandle(ScopedInterfaceEndpointHandle&& other);
 
+  ScopedInterfaceEndpointHandle(const ScopedInterfaceEndpointHandle&) = delete;
+  ScopedInterfaceEndpointHandle& operator=(
+      const ScopedInterfaceEndpointHandle&) = delete;
+
   ~ScopedInterfaceEndpointHandle();
 
   ScopedInterfaceEndpointHandle& operator=(
@@ -113,8 +117,6 @@
   CreateGroupControllerGetter() const;
 
   scoped_refptr<State> state_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedInterfaceEndpointHandle);
 };
 
 }  // namespace mojo
diff --git a/mojo/public/cpp/bindings/sequence_local_sync_event_watcher.h b/mojo/public/cpp/bindings/sequence_local_sync_event_watcher.h
index 5994f8f84..c32a542 100644
--- a/mojo/public/cpp/bindings/sequence_local_sync_event_watcher.h
+++ b/mojo/public/cpp/bindings/sequence_local_sync_event_watcher.h
@@ -31,6 +31,11 @@
  public:
   explicit SequenceLocalSyncEventWatcher(
       const base::RepeatingClosure& callback);
+
+  SequenceLocalSyncEventWatcher(const SequenceLocalSyncEventWatcher&) = delete;
+  SequenceLocalSyncEventWatcher& operator=(
+      const SequenceLocalSyncEventWatcher&) = delete;
+
   ~SequenceLocalSyncEventWatcher();
 
   // Signals the shared event on behalf of this specific watcher. Safe to call
@@ -60,8 +65,6 @@
   const std::unique_ptr<Registration> registration_;
   const base::RepeatingClosure callback_;
   bool can_wake_up_during_any_watch_ = false;
-
-  DISALLOW_COPY_AND_ASSIGN(SequenceLocalSyncEventWatcher);
 };
 
 }  // namespace mojo
diff --git a/mojo/public/cpp/bindings/service_factory.h b/mojo/public/cpp/bindings/service_factory.h
index 5959521..ba3f7a3 100644
--- a/mojo/public/cpp/bindings/service_factory.h
+++ b/mojo/public/cpp/bindings/service_factory.h
@@ -71,6 +71,10 @@
 class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) ServiceFactory {
  public:
   ServiceFactory();
+
+  ServiceFactory(const ServiceFactory&) = delete;
+  ServiceFactory& operator=(const ServiceFactory&) = delete;
+
   ~ServiceFactory();
 
   // Adds a new service to the factory. The argument may be any function that
@@ -105,6 +109,10 @@
   class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) InstanceHolderBase {
    public:
     InstanceHolderBase();
+
+    InstanceHolderBase(const InstanceHolderBase&) = delete;
+    InstanceHolderBase& operator=(const InstanceHolderBase&) = delete;
+
     virtual ~InstanceHolderBase();
 
     void WatchPipe(MessagePipeHandle pipe,
@@ -115,8 +123,6 @@
 
     SimpleWatcher watcher_;
     base::OnceClosure disconnect_callback_;
-
-    DISALLOW_COPY_AND_ASSIGN(InstanceHolderBase);
   };
 
   template <typename Interface>
@@ -124,12 +130,14 @@
    public:
     explicit InstanceHolder(std::unique_ptr<Interface> instance)
         : instance_(std::move(instance)) {}
+
+    InstanceHolder(const InstanceHolder&) = delete;
+    InstanceHolder& operator=(const InstanceHolder&) = delete;
+
     ~InstanceHolder() override = default;
 
    private:
     const std::unique_ptr<Interface> instance_;
-
-    DISALLOW_COPY_AND_ASSIGN(InstanceHolder);
   };
 
   template <typename Func>
@@ -155,8 +163,6 @@
       instances_;
 
   base::WeakPtrFactory<ServiceFactory> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(ServiceFactory);
 };
 
 namespace internal {
diff --git a/mojo/public/cpp/bindings/shared_remote.h b/mojo/public/cpp/bindings/shared_remote.h
index 60bdcc1..226255f 100644
--- a/mojo/public/cpp/bindings/shared_remote.h
+++ b/mojo/public/cpp/bindings/shared_remote.h
@@ -54,14 +54,16 @@
   // method.
   explicit ThreadSafeForwarder(scoped_refptr<ThreadSafeProxy> thread_safe_proxy)
       : ThreadSafeForwarderBase(std::move(thread_safe_proxy)), proxy_(this) {}
+
+  ThreadSafeForwarder(const ThreadSafeForwarder&) = delete;
+  ThreadSafeForwarder& operator=(const ThreadSafeForwarder&) = delete;
+
   ~ThreadSafeForwarder() override = default;
 
   ProxyType& proxy() { return proxy_; }
 
  private:
   ProxyType proxy_;
-
-  DISALLOW_COPY_AND_ASSIGN(ThreadSafeForwarder);
 };
 
 template <typename Interface>
diff --git a/mojo/public/cpp/bindings/struct_ptr.h b/mojo/public/cpp/bindings/struct_ptr.h
index 5d8875c..3f7dc2e2 100644
--- a/mojo/public/cpp/bindings/struct_ptr.h
+++ b/mojo/public/cpp/bindings/struct_ptr.h
@@ -43,6 +43,9 @@
   StructPtr() = default;
   StructPtr(std::nullptr_t) {}
 
+  StructPtr(const StructPtr&) = delete;
+  StructPtr& operator=(const StructPtr&) = delete;
+
   ~StructPtr() = default;
 
   StructPtr& operator=(std::nullptr_t) {
@@ -124,8 +127,6 @@
   }
 
   std::unique_ptr<Struct> ptr_;
-
-  DISALLOW_COPY_AND_ASSIGN(StructPtr);
 };
 
 // Designed to be used when Struct is small and copyable.
@@ -141,6 +142,9 @@
   InlinedStructPtr() = default;
   InlinedStructPtr(std::nullptr_t) {}
 
+  InlinedStructPtr(const InlinedStructPtr&) = delete;
+  InlinedStructPtr& operator=(const InlinedStructPtr&) = delete;
+
   ~InlinedStructPtr() = default;
 
   InlinedStructPtr& operator=(std::nullptr_t) {
@@ -232,8 +236,6 @@
 
   mutable Struct value_;
   State state_ = NIL;
-
-  DISALLOW_COPY_AND_ASSIGN(InlinedStructPtr);
 };
 
 namespace internal {
diff --git a/mojo/public/cpp/bindings/sync_call_restrictions.h b/mojo/public/cpp/bindings/sync_call_restrictions.h
index fc414274..e638cb6 100644
--- a/mojo/public/cpp/bindings/sync_call_restrictions.h
+++ b/mojo/public/cpp/bindings/sync_call_restrictions.h
@@ -134,14 +134,16 @@
   class ScopedAllowSyncCall {
    public:
     ScopedAllowSyncCall() { IncreaseScopedAllowCount(); }
+
+    ScopedAllowSyncCall(const ScopedAllowSyncCall&) = delete;
+    ScopedAllowSyncCall& operator=(const ScopedAllowSyncCall&) = delete;
+
     ~ScopedAllowSyncCall() { DecreaseScopedAllowCount(); }
 
    private:
 #if ENABLE_SYNC_CALL_RESTRICTIONS
     base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope allow_wait_;
 #endif
-
-    DISALLOW_COPY_AND_ASSIGN(ScopedAllowSyncCall);
   };
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(SyncCallRestrictions);
@@ -150,12 +152,15 @@
 class ScopedAllowSyncCallForTesting {
  public:
   ScopedAllowSyncCallForTesting() {}
+
+  ScopedAllowSyncCallForTesting(const ScopedAllowSyncCallForTesting&) = delete;
+  ScopedAllowSyncCallForTesting& operator=(
+      const ScopedAllowSyncCallForTesting&) = delete;
+
   ~ScopedAllowSyncCallForTesting() {}
 
  private:
   SyncCallRestrictions::ScopedAllowSyncCall scoped_allow_sync_call_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedAllowSyncCallForTesting);
 };
 
 }  // namespace mojo
diff --git a/mojo/public/cpp/bindings/sync_event_watcher.h b/mojo/public/cpp/bindings/sync_event_watcher.h
index 3d72204..6f5375c 100644
--- a/mojo/public/cpp/bindings/sync_event_watcher.h
+++ b/mojo/public/cpp/bindings/sync_event_watcher.h
@@ -26,6 +26,9 @@
  public:
   SyncEventWatcher(base::WaitableEvent* event, base::RepeatingClosure callback);
 
+  SyncEventWatcher(const SyncEventWatcher&) = delete;
+  SyncEventWatcher& operator=(const SyncEventWatcher&) = delete;
+
   ~SyncEventWatcher();
 
   // Registers |event_| with SyncHandleRegistry, so that when others perform
@@ -65,8 +68,6 @@
   scoped_refptr<base::RefCountedData<bool>> destroyed_;
 
   SEQUENCE_CHECKER(sequence_checker_);
-
-  DISALLOW_COPY_AND_ASSIGN(SyncEventWatcher);
 };
 
 }  // namespace mojo
diff --git a/mojo/public/cpp/bindings/sync_handle_watcher.h b/mojo/public/cpp/bindings/sync_handle_watcher.h
index 5ed7e7b8..1099aea 100644
--- a/mojo/public/cpp/bindings/sync_handle_watcher.h
+++ b/mojo/public/cpp/bindings/sync_handle_watcher.h
@@ -33,6 +33,9 @@
                     MojoHandleSignals handle_signals,
                     const SyncHandleRegistry::HandleCallback& callback);
 
+  SyncHandleWatcher(const SyncHandleWatcher&) = delete;
+  SyncHandleWatcher& operator=(const SyncHandleWatcher&) = delete;
+
   ~SyncHandleWatcher();
 
   // Registers |handle_| with SyncHandleRegistry, so that when others perform
@@ -66,8 +69,6 @@
   scoped_refptr<base::RefCountedData<bool>> destroyed_;
 
   SEQUENCE_CHECKER(sequence_checker_);
-
-  DISALLOW_COPY_AND_ASSIGN(SyncHandleWatcher);
 };
 
 }  // namespace mojo
diff --git a/mojo/public/cpp/bindings/tests/bindings_perftest.cc b/mojo/public/cpp/bindings/tests/bindings_perftest.cc
index 41f7c26..ffd3659 100644
--- a/mojo/public/cpp/bindings/tests/bindings_perftest.cc
+++ b/mojo/public/cpp/bindings/tests/bindings_perftest.cc
@@ -34,13 +34,14 @@
 class PingServiceImpl : public test::PingService {
  public:
   PingServiceImpl() = default;
+
+  PingServiceImpl(const PingServiceImpl&) = delete;
+  PingServiceImpl& operator=(const PingServiceImpl&) = delete;
+
   ~PingServiceImpl() override = default;
 
   // |PingService| methods:
   void Ping(PingCallback callback) override { std::move(callback).Run(); }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(PingServiceImpl);
 };
 
 class PingPongTest {
diff --git a/mojo/public/cpp/bindings/tests/connection_group_unittest.cc b/mojo/public/cpp/bindings/tests/connection_group_unittest.cc
index bcdb662b..da9f3054 100644
--- a/mojo/public/cpp/bindings/tests/connection_group_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/connection_group_unittest.cc
@@ -38,6 +38,9 @@
         &TestInterfaceImpl::OnDisconnect, base::Unretained(this)));
   }
 
+  TestInterfaceImpl(const TestInterfaceImpl&) = delete;
+  TestInterfaceImpl& operator=(const TestInterfaceImpl&) = delete;
+
   ~TestInterfaceImpl() override = default;
 
   void WaitForDisconnect() {
@@ -60,8 +63,6 @@
 
   ReceiverSet<mojom::TestInterface> receivers_;
   base::OnceClosure wait_for_disconnect_closure_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestInterfaceImpl);
 };
 
 TEST_P(ConnectionGroupBindingsTest, RefCounting) {
diff --git a/mojo/public/cpp/bindings/tests/container_test_util.h b/mojo/public/cpp/bindings/tests/container_test_util.h
index f709c15..61594f8 100644
--- a/mojo/public/cpp/bindings/tests/container_test_util.h
+++ b/mojo/public/cpp/bindings/tests/container_test_util.h
@@ -35,6 +35,10 @@
   MoveOnlyType();
   MoveOnlyType(MoveOnlyType&& other);
   MoveOnlyType& operator=(MoveOnlyType&& other);
+
+  MoveOnlyType(const MoveOnlyType&) = delete;
+  MoveOnlyType& operator=(const MoveOnlyType&) = delete;
+
   ~MoveOnlyType();
 
   bool moved() const { return moved_; }
@@ -46,8 +50,6 @@
   bool moved_;
   static size_t num_instances_;
   MoveOnlyType* ptr_;
-
-  DISALLOW_COPY_AND_ASSIGN(MoveOnlyType);
 };
 
 }  // namespace mojo
diff --git a/mojo/public/cpp/bindings/tests/idle_tracking_unittest.cc b/mojo/public/cpp/bindings/tests/idle_tracking_unittest.cc
index c11b8b8c..823f4624 100644
--- a/mojo/public/cpp/bindings/tests/idle_tracking_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/idle_tracking_unittest.cc
@@ -28,6 +28,9 @@
   explicit TestServiceImpl(PendingReceiver<mojom::TestService> receiver)
       : receiver_(this, std::move(receiver)) {}
 
+  TestServiceImpl(const TestServiceImpl&) = delete;
+  TestServiceImpl& operator=(const TestServiceImpl&) = delete;
+
   ~TestServiceImpl() override = default;
 
   void HoldNextPingPong() { hold_next_ping_pong_ = true; }
@@ -58,8 +61,6 @@
 
   bool hold_next_ping_pong_ = false;
   base::OnceClosure last_ping_pong_reply_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestServiceImpl);
 };
 
 TEST_P(IdleTrackingTest, ControlMessagesDontExpectAck) {
diff --git a/mojo/public/cpp/bindings/tests/lazy_serialization_unittest.cc b/mojo/public/cpp/bindings/tests/lazy_serialization_unittest.cc
index 756f007..c2e51b83 100644
--- a/mojo/public/cpp/bindings/tests/lazy_serialization_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/lazy_serialization_unittest.cc
@@ -19,12 +19,14 @@
 class LazySerializationTest : public testing::Test {
  public:
   LazySerializationTest() = default;
+
+  LazySerializationTest(const LazySerializationTest&) = delete;
+  LazySerializationTest& operator=(const LazySerializationTest&) = delete;
+
   ~LazySerializationTest() override = default;
 
  private:
   base::test::TaskEnvironment task_environment_;
-
-  DISALLOW_COPY_AND_ASSIGN(LazySerializationTest);
 };
 
 class TestUnserializedStructImpl : public test::TestUnserializedStruct {
@@ -32,6 +34,11 @@
   explicit TestUnserializedStructImpl(
       PendingReceiver<test::TestUnserializedStruct> receiver)
       : receiver_(this, std::move(receiver)) {}
+
+  TestUnserializedStructImpl(const TestUnserializedStructImpl&) = delete;
+  TestUnserializedStructImpl& operator=(const TestUnserializedStructImpl&) =
+      delete;
+
   ~TestUnserializedStructImpl() override = default;
 
   // test::TestUnserializedStruct:
@@ -43,14 +50,16 @@
 
  private:
   Receiver<test::TestUnserializedStruct> receiver_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestUnserializedStructImpl);
 };
 
 class ForceSerializeTesterImpl : public test::ForceSerializeTester {
  public:
   ForceSerializeTesterImpl(PendingReceiver<test::ForceSerializeTester> receiver)
       : receiver_(this, std::move(receiver)) {}
+
+  ForceSerializeTesterImpl(const ForceSerializeTesterImpl&) = delete;
+  ForceSerializeTesterImpl& operator=(const ForceSerializeTesterImpl&) = delete;
+
   ~ForceSerializeTesterImpl() override = default;
 
   // test::ForceSerializeTester:
@@ -68,8 +77,6 @@
 
  private:
   Receiver<test::ForceSerializeTester> receiver_;
-
-  DISALLOW_COPY_AND_ASSIGN(ForceSerializeTesterImpl);
 };
 
 TEST_F(LazySerializationTest, NeverSerialize) {
diff --git a/mojo/public/cpp/bindings/tests/message_queue.h b/mojo/public/cpp/bindings/tests/message_queue.h
index 836c60d..4ae5b94 100644
--- a/mojo/public/cpp/bindings/tests/message_queue.h
+++ b/mojo/public/cpp/bindings/tests/message_queue.h
@@ -16,6 +16,10 @@
 class MessageQueue {
  public:
   MessageQueue();
+
+  MessageQueue(const MessageQueue&) = delete;
+  MessageQueue& operator=(const MessageQueue&) = delete;
+
   ~MessageQueue();
 
   bool IsEmpty() const;
@@ -33,8 +37,6 @@
   void Pop();
 
   base::queue<Message> queue_;
-
-  DISALLOW_COPY_AND_ASSIGN(MessageQueue);
 };
 
 }  // namespace test
diff --git a/mojo/public/cpp/bindings/tests/native_struct_unittest.cc b/mojo/public/cpp/bindings/tests/native_struct_unittest.cc
index 3e8a7ed8..1061e6c 100644
--- a/mojo/public/cpp/bindings/tests/native_struct_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/native_struct_unittest.cc
@@ -25,6 +25,10 @@
                          public test::NativeTypeTester {
  public:
   NativeStructTest() : receiver_(this, remote_.BindNewPipeAndPassReceiver()) {}
+
+  NativeStructTest(const NativeStructTest&) = delete;
+  NativeStructTest& operator=(const NativeStructTest&) = delete;
+
   ~NativeStructTest() override = default;
 
   test::NativeTypeTester* remote() { return remote_.get(); }
@@ -44,8 +48,6 @@
 
   Remote<test::NativeTypeTester> remote_;
   Receiver<test::NativeTypeTester> receiver_;
-
-  DISALLOW_COPY_AND_ASSIGN(NativeStructTest);
 };
 
 TEST_P(NativeStructTest, NativeStruct) {
diff --git a/mojo/public/cpp/bindings/tests/new_endpoint_types_unittest.cc b/mojo/public/cpp/bindings/tests/new_endpoint_types_unittest.cc
index bc46b66..b08c361 100644
--- a/mojo/public/cpp/bindings/tests/new_endpoint_types_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/new_endpoint_types_unittest.cc
@@ -36,6 +36,9 @@
     client_->OnInitialized();
   }
 
+  WidgetImpl(const WidgetImpl&) = delete;
+  WidgetImpl& operator=(const WidgetImpl&) = delete;
+
   ~WidgetImpl() override = default;
 
   // mojom::Widget:
@@ -52,14 +55,16 @@
  private:
   mojo::Remote<mojom::WidgetClient> client_;
   std::vector<mojo::Remote<mojom::WidgetObserver>> observers_;
-
-  DISALLOW_COPY_AND_ASSIGN(WidgetImpl);
 };
 
 class FactoryImpl : public mojom::WidgetFactory {
  public:
   explicit FactoryImpl(mojo::PendingReceiver<mojom::WidgetFactory> receiver)
       : receiver_(this, std::move(receiver)) {}
+
+  FactoryImpl(const FactoryImpl&) = delete;
+  FactoryImpl& operator=(const FactoryImpl&) = delete;
+
   ~FactoryImpl() override = default;
 
   // mojom::WidgetFactory:
@@ -72,13 +77,15 @@
  private:
   mojo::Receiver<mojom::WidgetFactory> receiver_;
   mojo::UniqueReceiverSet<mojom::Widget> widgets_;
-
-  DISALLOW_COPY_AND_ASSIGN(FactoryImpl);
 };
 
 class ClientImpl : public mojom::WidgetClient {
  public:
   ClientImpl() = default;
+
+  ClientImpl(const ClientImpl&) = delete;
+  ClientImpl& operator=(const ClientImpl&) = delete;
+
   ~ClientImpl() override = default;
 
   mojo::PendingRemote<mojom::WidgetClient> BindNewPipeAndPassRemote() {
@@ -93,13 +100,15 @@
  private:
   mojo::Receiver<mojom::WidgetClient> receiver_{this};
   base::RunLoop wait_loop_;
-
-  DISALLOW_COPY_AND_ASSIGN(ClientImpl);
 };
 
 class ObserverImpl : public mojom::WidgetObserver {
  public:
   ObserverImpl() = default;
+
+  ObserverImpl(const ObserverImpl&) = delete;
+  ObserverImpl& operator=(const ObserverImpl&) = delete;
+
   ~ObserverImpl() override = default;
 
   mojo::PendingRemote<mojom::WidgetObserver> BindNewPipeAndPassRemote() {
@@ -121,13 +130,15 @@
   mojo::Receiver<mojom::WidgetObserver> receiver_{this};
   base::RunLoop click_loop_;
   base::RunLoop disconnect_loop_;
-
-  DISALLOW_COPY_AND_ASSIGN(ObserverImpl);
 };
 
 class PingerImpl : public mojom::Pinger {
  public:
   PingerImpl() = default;
+
+  PingerImpl(const PingerImpl&) = delete;
+  PingerImpl& operator=(const PingerImpl&) = delete;
+
   ~PingerImpl() override = default;
 
   int ping_count() const { return ping_count_; }
@@ -145,8 +156,6 @@
 
   mojo::AssociatedReceiverSet<mojom::Pinger> receivers_;
   int ping_count_ = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(PingerImpl);
 };
 
 class AssociatedPingerHostImpl : public mojom::AssociatedPingerHost {
@@ -154,6 +163,10 @@
   explicit AssociatedPingerHostImpl(
       mojo::PendingReceiver<mojom::AssociatedPingerHost> receiver)
       : receiver_(this, std::move(receiver)) {}
+
+  AssociatedPingerHostImpl(const AssociatedPingerHostImpl&) = delete;
+  AssociatedPingerHostImpl& operator=(const AssociatedPingerHostImpl&) = delete;
+
   ~AssociatedPingerHostImpl() override = default;
 
   int ping_count() const { return pinger_.ping_count(); }
@@ -170,8 +183,6 @@
 
   mojo::Receiver<mojom::AssociatedPingerHost> receiver_;
   PingerImpl pinger_;
-
-  DISALLOW_COPY_AND_ASSIGN(AssociatedPingerHostImpl);
 };
 
 TEST(NewEndpointTypesTest, BasicUsage) {
diff --git a/mojo/public/cpp/bindings/tests/pickle_unittest.cc b/mojo/public/cpp/bindings/tests/pickle_unittest.cc
index 208d5bd6..a90c36f 100644
--- a/mojo/public/cpp/bindings/tests/pickle_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/pickle_unittest.cc
@@ -184,10 +184,13 @@
   class ScopedForceMessageSerialization {
    public:
     ScopedForceMessageSerialization() { ForceMessageSerialization(true); }
-    ~ScopedForceMessageSerialization() { ForceMessageSerialization(false); }
 
-   private:
-    DISALLOW_COPY_AND_ASSIGN(ScopedForceMessageSerialization);
+    ScopedForceMessageSerialization(const ScopedForceMessageSerialization&) =
+        delete;
+    ScopedForceMessageSerialization& operator=(
+        const ScopedForceMessageSerialization&) = delete;
+
+    ~ScopedForceMessageSerialization() { ForceMessageSerialization(false); }
   };
 
  private:
diff --git a/mojo/public/cpp/bindings/tests/pickled_types_blink.h b/mojo/public/cpp/bindings/tests/pickled_types_blink.h
index a59ca55..ee8da8b 100644
--- a/mojo/public/cpp/bindings/tests/pickled_types_blink.h
+++ b/mojo/public/cpp/bindings/tests/pickled_types_blink.h
@@ -34,6 +34,10 @@
   PickledStructBlink();
   PickledStructBlink(int foo, int bar);
   PickledStructBlink(PickledStructBlink&& other) = default;
+
+  PickledStructBlink(const PickledStructBlink&) = delete;
+  PickledStructBlink& operator=(const PickledStructBlink&) = delete;
+
   ~PickledStructBlink();
 
   PickledStructBlink& operator=(PickledStructBlink&& other) = default;
@@ -58,8 +62,6 @@
   int foo_ = 0;
   int bar_ = 0;
   int baz_ = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(PickledStructBlink);
 };
 
 }  // namespace test
diff --git a/mojo/public/cpp/bindings/tests/pickled_types_chromium.h b/mojo/public/cpp/bindings/tests/pickled_types_chromium.h
index 51649c2..8f4e68d 100644
--- a/mojo/public/cpp/bindings/tests/pickled_types_chromium.h
+++ b/mojo/public/cpp/bindings/tests/pickled_types_chromium.h
@@ -31,6 +31,10 @@
   PickledStructChromium();
   PickledStructChromium(int foo, int bar);
   PickledStructChromium(PickledStructChromium&& other) = default;
+
+  PickledStructChromium(const PickledStructChromium&) = delete;
+  PickledStructChromium& operator=(const PickledStructChromium&) = delete;
+
   ~PickledStructChromium();
 
   PickledStructChromium& operator=(PickledStructChromium&& other) = default;
@@ -49,8 +53,6 @@
   int foo_ = 0;
   int bar_ = 0;
   int baz_ = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(PickledStructChromium);
 };
 
 bool operator==(const PickledStructChromium& a, const PickledStructChromium& b);
diff --git a/mojo/public/cpp/bindings/tests/receiver_unittest.cc b/mojo/public/cpp/bindings/tests/receiver_unittest.cc
index 8453bdc..4e7bcee 100644
--- a/mojo/public/cpp/bindings/tests/receiver_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/receiver_unittest.cc
@@ -44,6 +44,9 @@
   explicit ServiceImpl(base::OnceClosure destruction_callback)
       : destruction_callback_(std::move(destruction_callback)) {}
 
+  ServiceImpl(const ServiceImpl&) = delete;
+  ServiceImpl& operator=(const ServiceImpl&) = delete;
+
   ~ServiceImpl() override {
     if (destruction_callback_)
       std::move(destruction_callback_).Run();
@@ -60,8 +63,6 @@
   void GetPort(PendingReceiver<sample::Port> port) override {}
 
   base::OnceClosure destruction_callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(ServiceImpl);
 };
 
 using ReceiverTest = BindingsTestBase;
@@ -258,6 +259,10 @@
 class IntegerAccessorImpl : public sample::IntegerAccessor {
  public:
   IntegerAccessorImpl() = default;
+
+  IntegerAccessorImpl(const IntegerAccessorImpl&) = delete;
+  IntegerAccessorImpl& operator=(const IntegerAccessorImpl&) = delete;
+
   ~IntegerAccessorImpl() override = default;
 
  private:
@@ -266,8 +271,6 @@
     std::move(callback).Run(1, sample::Enum::VALUE);
   }
   void SetInteger(int64_t data, sample::Enum type) override {}
-
-  DISALLOW_COPY_AND_ASSIGN(IntegerAccessorImpl);
 };
 
 TEST_P(ReceiverTest, PauseResume) {
@@ -323,6 +326,10 @@
 class PingServiceImpl : public test::PingService {
  public:
   PingServiceImpl() = default;
+
+  PingServiceImpl(const PingServiceImpl&) = delete;
+  PingServiceImpl& operator=(const PingServiceImpl&) = delete;
+
   ~PingServiceImpl() override = default;
 
   // test::PingService:
@@ -338,8 +345,6 @@
 
  private:
   base::RepeatingClosure ping_handler_;
-
-  DISALLOW_COPY_AND_ASSIGN(PingServiceImpl);
 };
 
 class CallbackFilter : public MessageFilter {
@@ -671,6 +676,10 @@
     receiver_.set_disconnect_handler(base::BindOnce(
         &TestGenericBinderImpl::OnDisconnect, base::Unretained(this)));
   }
+
+  TestGenericBinderImpl(const TestGenericBinderImpl&) = delete;
+  TestGenericBinderImpl& operator=(const TestGenericBinderImpl&) = delete;
+
   ~TestGenericBinderImpl() override = default;
 
   bool connected() const { return connected_; }
@@ -739,8 +748,6 @@
   absl::optional<base::RunLoop> wait_loop_;
   GenericPendingReceiver* next_receiver_storage_ = nullptr;
   GenericPendingAssociatedReceiver* next_associated_receiver_storage_ = nullptr;
-
-  DISALLOW_COPY_AND_ASSIGN(TestGenericBinderImpl);
 };
 
 using ReceiverSerializationTest = ReceiverTest;
diff --git a/mojo/public/cpp/bindings/tests/report_bad_message_unittest.cc b/mojo/public/cpp/bindings/tests/report_bad_message_unittest.cc
index 33ff065..0b65603e 100644
--- a/mojo/public/cpp/bindings/tests/report_bad_message_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/report_bad_message_unittest.cc
@@ -23,6 +23,10 @@
 class TestBadMessagesImpl : public TestBadMessages {
  public:
   TestBadMessagesImpl() = default;
+
+  TestBadMessagesImpl(const TestBadMessagesImpl&) = delete;
+  TestBadMessagesImpl& operator=(const TestBadMessagesImpl&) = delete;
+
   ~TestBadMessagesImpl() override = default;
 
   void Bind(PendingReceiver<TestBadMessages> receiver) {
@@ -55,8 +59,6 @@
 
   ReportBadMessageCallback bad_message_callback_;
   mojo::Receiver<TestBadMessages> receiver_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(TestBadMessagesImpl);
 };
 
 class ReportBadMessageTest : public BindingsTestBase {
diff --git a/mojo/public/cpp/bindings/tests/service_factory_unittest.cc b/mojo/public/cpp/bindings/tests/service_factory_unittest.cc
index 747b24a..173acbf2f 100644
--- a/mojo/public/cpp/bindings/tests/service_factory_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/service_factory_unittest.cc
@@ -39,6 +39,9 @@
     ++num_instances_;
   }
 
+  TestService1Impl(const TestService1Impl&) = delete;
+  TestService1Impl& operator=(const TestService1Impl&) = delete;
+
   ~TestService1Impl() override {
     --num_instances_;
   }
@@ -55,8 +58,6 @@
 
   Receiver<mojom::TestService1> receiver_;
   static int num_instances_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestService1Impl);
 };
 
 class TestService2Impl : public mojom::TestService2 {
@@ -64,6 +65,9 @@
   explicit TestService2Impl(PendingReceiver<mojom::TestService2> receiver)
       : receiver_(this, std::move(receiver)) {}
 
+  TestService2Impl(const TestService2Impl&) = delete;
+  TestService2Impl& operator=(const TestService2Impl&) = delete;
+
   ~TestService2Impl() override = default;
 
  private:
@@ -73,8 +77,6 @@
   }
 
   Receiver<mojom::TestService2> receiver_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestService2Impl);
 };
 
 int TestService1Impl::num_instances_ = 0;
diff --git a/mojo/public/cpp/bindings/tests/struct_with_traits_impl.h b/mojo/public/cpp/bindings/tests/struct_with_traits_impl.h
index e8d9612..f986746a 100644
--- a/mojo/public/cpp/bindings/tests/struct_with_traits_impl.h
+++ b/mojo/public/cpp/bindings/tests/struct_with_traits_impl.h
@@ -118,6 +118,11 @@
  public:
   MoveOnlyStructWithTraitsImpl();
   MoveOnlyStructWithTraitsImpl(MoveOnlyStructWithTraitsImpl&& other);
+
+  MoveOnlyStructWithTraitsImpl(const MoveOnlyStructWithTraitsImpl&) = delete;
+  MoveOnlyStructWithTraitsImpl& operator=(const MoveOnlyStructWithTraitsImpl&) =
+      delete;
+
   ~MoveOnlyStructWithTraitsImpl();
 
   ScopedHandle& get_mutable_handle() { return handle_; }
@@ -126,7 +131,6 @@
 
  private:
   ScopedHandle handle_;
-  DISALLOW_COPY_AND_ASSIGN(MoveOnlyStructWithTraitsImpl);
 };
 
 class UnionWithTraitsBase {
diff --git a/mojo/public/cpp/bindings/tests/test_helpers_unittest.cc b/mojo/public/cpp/bindings/tests/test_helpers_unittest.cc
index 280b2dc4..b9760ea1 100644
--- a/mojo/public/cpp/bindings/tests/test_helpers_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/test_helpers_unittest.cc
@@ -18,18 +18,24 @@
 class TestHelperTest : public testing::Test {
  public:
   TestHelperTest() = default;
+
+  TestHelperTest(const TestHelperTest&) = delete;
+  TestHelperTest& operator=(const TestHelperTest&) = delete;
+
   ~TestHelperTest() override = default;
 
  private:
   base::test::TaskEnvironment task_environment_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestHelperTest);
 };
 
 class PingImpl : public test::PingService {
  public:
   explicit PingImpl(PendingReceiver<test::PingService> receiver)
       : receiver_(this, std::move(receiver)) {}
+
+  PingImpl(const PingImpl&) = delete;
+  PingImpl& operator=(const PingImpl&) = delete;
+
   ~PingImpl() override = default;
 
   bool pinged() const { return pinged_; }
@@ -43,14 +49,16 @@
  private:
   bool pinged_ = false;
   Receiver<test::PingService> receiver_;
-
-  DISALLOW_COPY_AND_ASSIGN(PingImpl);
 };
 
 class EchoImpl : public test::EchoService {
  public:
   explicit EchoImpl(PendingReceiver<test::EchoService> receiver)
       : receiver_(this, std::move(receiver)) {}
+
+  EchoImpl(const EchoImpl&) = delete;
+  EchoImpl& operator=(const EchoImpl&) = delete;
+
   ~EchoImpl() override = default;
 
   // test::EchoService:
@@ -60,14 +68,16 @@
 
  private:
   Receiver<test::EchoService> receiver_;
-
-  DISALLOW_COPY_AND_ASSIGN(EchoImpl);
 };
 
 class TrampolineImpl : public test::HandleTrampoline {
  public:
   explicit TrampolineImpl(PendingReceiver<test::HandleTrampoline> receiver)
       : receiver_(this, std::move(receiver)) {}
+
+  TrampolineImpl(const TrampolineImpl&) = delete;
+  TrampolineImpl& operator=(const TrampolineImpl&) = delete;
+
   ~TrampolineImpl() override = default;
 
   // test::HandleTrampoline:
@@ -84,8 +94,6 @@
 
  private:
   Receiver<test::HandleTrampoline> receiver_;
-
-  DISALLOW_COPY_AND_ASSIGN(TrampolineImpl);
 };
 
 TEST_F(TestHelperTest, AsyncWaiter) {
diff --git a/mojo/public/cpp/bindings/tests/test_native_types.h b/mojo/public/cpp/bindings/tests/test_native_types.h
index 5ad27ac..7d4f447 100644
--- a/mojo/public/cpp/bindings/tests/test_native_types.h
+++ b/mojo/public/cpp/bindings/tests/test_native_types.h
@@ -41,6 +41,12 @@
   TestNativeStructWithAttachments(TestNativeStructWithAttachments&& other);
   TestNativeStructWithAttachments(const std::string& message,
                                   ScopedMessagePipeHandle pipe);
+
+  TestNativeStructWithAttachments(const TestNativeStructWithAttachments&) =
+      delete;
+  TestNativeStructWithAttachments& operator=(
+      const TestNativeStructWithAttachments&) = delete;
+
   ~TestNativeStructWithAttachments();
 
   TestNativeStructWithAttachments& operator=(
@@ -55,8 +61,6 @@
  private:
   std::string message_;
   mutable mojo::ScopedMessagePipeHandle pipe_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestNativeStructWithAttachments);
 };
 
 }  // namespace test
diff --git a/mojo/public/cpp/platform/named_platform_channel.h b/mojo/public/cpp/platform/named_platform_channel.h
index 6faad4e..f84b98c 100644
--- a/mojo/public/cpp/platform/named_platform_channel.h
+++ b/mojo/public/cpp/platform/named_platform_channel.h
@@ -66,6 +66,10 @@
 
   NamedPlatformChannel(const Options& options);
   NamedPlatformChannel(NamedPlatformChannel&& other);
+
+  NamedPlatformChannel(const NamedPlatformChannel&) = delete;
+  NamedPlatformChannel& operator=(const NamedPlatformChannel&) = delete;
+
   ~NamedPlatformChannel();
 
   NamedPlatformChannel& operator=(NamedPlatformChannel&& other);
@@ -114,8 +118,6 @@
 
   ServerName server_name_;
   PlatformChannelServerEndpoint server_endpoint_;
-
-  DISALLOW_COPY_AND_ASSIGN(NamedPlatformChannel);
 };
 
 }  // namespace mojo
diff --git a/mojo/public/cpp/platform/platform_channel.h b/mojo/public/cpp/platform/platform_channel.h
index bf13b9c5..ee65fdb 100644
--- a/mojo/public/cpp/platform/platform_channel.h
+++ b/mojo/public/cpp/platform/platform_channel.h
@@ -51,6 +51,10 @@
 
   PlatformChannel();
   PlatformChannel(PlatformChannel&& other);
+
+  PlatformChannel(const PlatformChannel&) = delete;
+  PlatformChannel& operator=(const PlatformChannel&) = delete;
+
   ~PlatformChannel();
 
   PlatformChannel& operator=(PlatformChannel&& other);
@@ -114,8 +118,6 @@
  private:
   PlatformChannelEndpoint local_endpoint_;
   PlatformChannelEndpoint remote_endpoint_;
-
-  DISALLOW_COPY_AND_ASSIGN(PlatformChannel);
 };
 
 }  // namespace mojo
diff --git a/mojo/public/cpp/platform/platform_channel_endpoint.h b/mojo/public/cpp/platform/platform_channel_endpoint.h
index 36812be7..b97e896 100644
--- a/mojo/public/cpp/platform/platform_channel_endpoint.h
+++ b/mojo/public/cpp/platform/platform_channel_endpoint.h
@@ -20,6 +20,10 @@
   PlatformChannelEndpoint();
   PlatformChannelEndpoint(PlatformChannelEndpoint&& other);
   explicit PlatformChannelEndpoint(PlatformHandle handle);
+
+  PlatformChannelEndpoint(const PlatformChannelEndpoint&) = delete;
+  PlatformChannelEndpoint& operator=(const PlatformChannelEndpoint&) = delete;
+
   ~PlatformChannelEndpoint();
 
   PlatformChannelEndpoint& operator=(PlatformChannelEndpoint&& other);
@@ -36,8 +40,6 @@
 
  private:
   PlatformHandle handle_;
-
-  DISALLOW_COPY_AND_ASSIGN(PlatformChannelEndpoint);
 };
 
 }  // namespace mojo
diff --git a/mojo/public/cpp/platform/platform_channel_server_endpoint.h b/mojo/public/cpp/platform/platform_channel_server_endpoint.h
index f80d9e3..7fffc60 100644
--- a/mojo/public/cpp/platform/platform_channel_server_endpoint.h
+++ b/mojo/public/cpp/platform/platform_channel_server_endpoint.h
@@ -20,6 +20,11 @@
   PlatformChannelServerEndpoint();
   PlatformChannelServerEndpoint(PlatformChannelServerEndpoint&& other);
   explicit PlatformChannelServerEndpoint(PlatformHandle handle);
+
+  PlatformChannelServerEndpoint(const PlatformChannelServerEndpoint&) = delete;
+  PlatformChannelServerEndpoint& operator=(
+      const PlatformChannelServerEndpoint&) = delete;
+
   ~PlatformChannelServerEndpoint();
 
   PlatformChannelServerEndpoint& operator=(
@@ -37,8 +42,6 @@
 
  private:
   PlatformHandle handle_;
-
-  DISALLOW_COPY_AND_ASSIGN(PlatformChannelServerEndpoint);
 };
 
 }  // namespace mojo
diff --git a/mojo/public/cpp/platform/platform_handle.h b/mojo/public/cpp/platform/platform_handle.h
index 504ffd5..088e75f3 100644
--- a/mojo/public/cpp/platform/platform_handle.h
+++ b/mojo/public/cpp/platform/platform_handle.h
@@ -71,6 +71,9 @@
   explicit PlatformHandle(base::ScopedFD fd);
 #endif
 
+  PlatformHandle(const PlatformHandle&) = delete;
+  PlatformHandle& operator=(const PlatformHandle&) = delete;
+
   ~PlatformHandle();
 
   PlatformHandle& operator=(PlatformHandle&& other);
@@ -228,8 +231,6 @@
 #if defined(OS_POSIX) || defined(OS_FUCHSIA)
   base::ScopedFD fd_;
 #endif
-
-  DISALLOW_COPY_AND_ASSIGN(PlatformHandle);
 };
 
 }  // namespace mojo
diff --git a/mojo/public/cpp/system/data_pipe_producer.h b/mojo/public/cpp/system/data_pipe_producer.h
index 557c116f..4ffa1d8 100644
--- a/mojo/public/cpp/system/data_pipe_producer.h
+++ b/mojo/public/cpp/system/data_pipe_producer.h
@@ -59,6 +59,10 @@
 
   // Constructs a new DataPipeProducer which will write data to |producer|.
   explicit DataPipeProducer(ScopedDataPipeProducerHandle producer);
+
+  DataPipeProducer(const DataPipeProducer&) = delete;
+  DataPipeProducer& operator=(const DataPipeProducer&) = delete;
+
   ~DataPipeProducer();
 
   // Attempts to eventually write all of |data_source|'s contents to the pipe.
@@ -97,8 +101,6 @@
   ScopedDataPipeProducerHandle producer_;
   scoped_refptr<SequenceState> sequence_state_;
   base::WeakPtrFactory<DataPipeProducer> weak_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(DataPipeProducer);
 };
 
 }  // namespace mojo
diff --git a/mojo/public/cpp/system/file_data_source.h b/mojo/public/cpp/system/file_data_source.h
index 02a7bf3..0cd9399 100644
--- a/mojo/public/cpp/system/file_data_source.h
+++ b/mojo/public/cpp/system/file_data_source.h
@@ -21,6 +21,10 @@
   static MojoResult ConvertFileErrorToMojoResult(base::File::Error error);
 
   FileDataSource(base::File file);
+
+  FileDataSource(const FileDataSource&) = delete;
+  FileDataSource& operator=(const FileDataSource&) = delete;
+
   ~FileDataSource() override;
 
   // |end| should be greater than or equal to |start|. Otherwise subsequent
@@ -36,8 +40,6 @@
   MojoResult error_;
   uint64_t start_offset_;
   uint64_t end_offset_;
-
-  DISALLOW_COPY_AND_ASSIGN(FileDataSource);
 };
 
 }  // namespace mojo
diff --git a/mojo/public/cpp/system/filtered_data_source.h b/mojo/public/cpp/system/filtered_data_source.h
index 74c228c2..1dac2d8 100644
--- a/mojo/public/cpp/system/filtered_data_source.h
+++ b/mojo/public/cpp/system/filtered_data_source.h
@@ -44,6 +44,10 @@
 
   FilteredDataSource(std::unique_ptr<DataPipeProducer::DataSource> source,
                      std::unique_ptr<Filter> filter);
+
+  FilteredDataSource(const FilteredDataSource&) = delete;
+  FilteredDataSource& operator=(const FilteredDataSource&) = delete;
+
   ~FilteredDataSource() override;
 
  private:
@@ -54,8 +58,6 @@
 
   std::unique_ptr<DataPipeProducer::DataSource> source_;
   std::unique_ptr<Filter> filter_;
-
-  DISALLOW_COPY_AND_ASSIGN(FilteredDataSource);
 };
 
 }  // namespace mojo
diff --git a/mojo/public/cpp/system/handle.h b/mojo/public/cpp/system/handle.h
index a0bd46ba..bc473ca 100644
--- a/mojo/public/cpp/system/handle.h
+++ b/mojo/public/cpp/system/handle.h
@@ -77,6 +77,10 @@
 
   ScopedHandleBase() {}
   explicit ScopedHandleBase(HandleType handle) : handle_(handle) {}
+
+  ScopedHandleBase(const ScopedHandleBase&) = delete;
+  ScopedHandleBase& operator=(const ScopedHandleBase&) = delete;
+
   ~ScopedHandleBase() { CloseIfNecessary(); }
 
   template <class CompatibleHandleType>
@@ -138,8 +142,6 @@
   }
 
   HandleType handle_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedHandleBase);
 };
 
 template <typename HandleType>
diff --git a/mojo/public/cpp/system/handle_signal_tracker.h b/mojo/public/cpp/system/handle_signal_tracker.h
index 7f4913b0..94e1e51 100644
--- a/mojo/public/cpp/system/handle_signal_tracker.h
+++ b/mojo/public/cpp/system/handle_signal_tracker.h
@@ -37,6 +37,10 @@
                       MojoHandleSignals signals,
                       scoped_refptr<base::SequencedTaskRunner> task_runner =
                           base::SequencedTaskRunnerHandle::Get());
+
+  HandleSignalTracker(const HandleSignalTracker&) = delete;
+  HandleSignalTracker& operator=(const HandleSignalTracker&) = delete;
+
   ~HandleSignalTracker();
 
   const HandleSignalsState& last_known_state() const {
@@ -67,8 +71,6 @@
   // Watches for the signal(s) to be cleared. May only be armed when
   // |high_watcher_| is not.
   SimpleWatcher low_watcher_;
-
-  DISALLOW_COPY_AND_ASSIGN(HandleSignalTracker);
 };
 
 }  // namespace mojo
diff --git a/mojo/public/cpp/system/invitation.h b/mojo/public/cpp/system/invitation.h
index 5191a09..05d657f 100644
--- a/mojo/public/cpp/system/invitation.h
+++ b/mojo/public/cpp/system/invitation.h
@@ -56,6 +56,10 @@
  public:
   OutgoingInvitation();
   OutgoingInvitation(OutgoingInvitation&& other);
+
+  OutgoingInvitation(const OutgoingInvitation&) = delete;
+  OutgoingInvitation& operator=(const OutgoingInvitation&) = delete;
+
   ~OutgoingInvitation();
 
   OutgoingInvitation& operator=(OutgoingInvitation&& other);
@@ -147,8 +151,6 @@
 
  private:
   ScopedInvitationHandle handle_;
-
-  DISALLOW_COPY_AND_ASSIGN(OutgoingInvitation);
 };
 
 // An IncomingInvitation can be accepted by an invited process by calling
@@ -159,6 +161,10 @@
   IncomingInvitation();
   IncomingInvitation(IncomingInvitation&& other);
   explicit IncomingInvitation(ScopedInvitationHandle handle);
+
+  IncomingInvitation(const IncomingInvitation&) = delete;
+  IncomingInvitation& operator=(const IncomingInvitation&) = delete;
+
   ~IncomingInvitation();
 
   IncomingInvitation& operator=(IncomingInvitation&& other);
@@ -197,8 +203,6 @@
 
  private:
   ScopedInvitationHandle handle_;
-
-  DISALLOW_COPY_AND_ASSIGN(IncomingInvitation);
 };
 
 }  // namespace mojo
diff --git a/mojo/public/cpp/system/isolated_connection.h b/mojo/public/cpp/system/isolated_connection.h
index 42c9053..065a8f5 100644
--- a/mojo/public/cpp/system/isolated_connection.h
+++ b/mojo/public/cpp/system/isolated_connection.h
@@ -38,6 +38,10 @@
 class MOJO_CPP_SYSTEM_EXPORT IsolatedConnection {
  public:
   IsolatedConnection();
+
+  IsolatedConnection(const IsolatedConnection&) = delete;
+  IsolatedConnection& operator=(const IsolatedConnection&) = delete;
+
   ~IsolatedConnection();
 
   // Connects to a process at the other end of the channel. Returns a primordial
@@ -51,8 +55,6 @@
 
  private:
   const base::UnguessableToken token_;
-
-  DISALLOW_COPY_AND_ASSIGN(IsolatedConnection);
 };
 
 }  // namespace mojo
diff --git a/mojo/public/cpp/system/scope_to_message_pipe.h b/mojo/public/cpp/system/scope_to_message_pipe.h
index 73282de..7292886 100644
--- a/mojo/public/cpp/system/scope_to_message_pipe.h
+++ b/mojo/public/cpp/system/scope_to_message_pipe.h
@@ -22,6 +22,10 @@
 class MOJO_CPP_SYSTEM_EXPORT MessagePipeScoperBase {
  public:
   explicit MessagePipeScoperBase(ScopedMessagePipeHandle pipe);
+
+  MessagePipeScoperBase(const MessagePipeScoperBase&) = delete;
+  MessagePipeScoperBase& operator=(const MessagePipeScoperBase&) = delete;
+
   virtual ~MessagePipeScoperBase();
 
   static void StartWatchingPipe(std::unique_ptr<MessagePipeScoperBase> scoper);
@@ -29,8 +33,6 @@
  private:
   ScopedMessagePipeHandle pipe_;
   SimpleWatcher pipe_watcher_;
-
-  DISALLOW_COPY_AND_ASSIGN(MessagePipeScoperBase);
 };
 
 template <typename T>
@@ -39,12 +41,14 @@
   explicit MessagePipeScoper(T scoped_object, ScopedMessagePipeHandle pipe)
       : MessagePipeScoperBase(std::move(pipe)),
         scoped_object_(std::move(scoped_object)) {}
+
+  MessagePipeScoper(const MessagePipeScoper&) = delete;
+  MessagePipeScoper& operator=(const MessagePipeScoper&) = delete;
+
   ~MessagePipeScoper() override = default;
 
  private:
   T scoped_object_;
-
-  DISALLOW_COPY_AND_ASSIGN(MessagePipeScoper);
 };
 
 }  // namespace internal
diff --git a/mojo/public/cpp/system/simple_watcher.h b/mojo/public/cpp/system/simple_watcher.h
index 3ccec253..94e45ba 100644
--- a/mojo/public/cpp/system/simple_watcher.h
+++ b/mojo/public/cpp/system/simple_watcher.h
@@ -91,6 +91,10 @@
                 scoped_refptr<base::SequencedTaskRunner> runner =
                     base::SequencedTaskRunnerHandle::Get(),
                 const char* handler_tag = nullptr);
+
+  SimpleWatcher(const SimpleWatcher&) = delete;
+  SimpleWatcher& operator=(const SimpleWatcher&) = delete;
+
   ~SimpleWatcher();
 
   // Indicates if the SimpleWatcher is currently watching a handle.
@@ -229,8 +233,6 @@
   const char* handler_tag_ = nullptr;
 
   base::WeakPtrFactory<SimpleWatcher> weak_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(SimpleWatcher);
 };
 
 }  // namespace mojo
diff --git a/mojo/public/cpp/system/string_data_source.h b/mojo/public/cpp/system/string_data_source.h
index a9e46b41..cd5afd9 100644
--- a/mojo/public/cpp/system/string_data_source.h
+++ b/mojo/public/cpp/system/string_data_source.h
@@ -30,6 +30,10 @@
   };
 
   StringDataSource(base::span<const char> data, AsyncWritingMode mode);
+
+  StringDataSource(const StringDataSource&) = delete;
+  StringDataSource& operator=(const StringDataSource&) = delete;
+
   ~StringDataSource() override;
 
  private:
@@ -39,8 +43,6 @@
 
   std::string data_;
   base::span<const char> data_view_;
-
-  DISALLOW_COPY_AND_ASSIGN(StringDataSource);
 };
 
 }  // namespace mojo
diff --git a/mojo/public/cpp/system/tests/data_pipe_producer_unittest.cc b/mojo/public/cpp/system/tests/data_pipe_producer_unittest.cc
index 729b44a4..98750c6 100644
--- a/mojo/public/cpp/system/tests/data_pipe_producer_unittest.cc
+++ b/mojo/public/cpp/system/tests/data_pipe_producer_unittest.cc
@@ -45,6 +45,10 @@
                    base::BindRepeating(&DataPipeReader::OnDataAvailable,
                                        base::Unretained(this)));
   }
+
+  DataPipeReader(const DataPipeReader&) = delete;
+  DataPipeReader& operator=(const DataPipeReader&) = delete;
+
   ~DataPipeReader() = default;
 
   const std::string& data() const { return data_; }
@@ -79,14 +83,15 @@
   base::OnceClosure on_read_done_;
   SimpleWatcher watcher_;
   std::string data_;
-
-  DISALLOW_COPY_AND_ASSIGN(DataPipeReader);
 };
 
 class DataPipeProducerTest : public testing::Test {
  public:
   DataPipeProducerTest() { CHECK(temp_dir_.CreateUniqueTempDir()); }
 
+  DataPipeProducerTest(const DataPipeProducerTest&) = delete;
+  DataPipeProducerTest& operator=(const DataPipeProducerTest&) = delete;
+
   ~DataPipeProducerTest() override = default;
 
  protected:
@@ -135,8 +140,6 @@
   base::test::TaskEnvironment task_environment_;
   base::ScopedTempDir temp_dir_;
   int tmp_file_id_ = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(DataPipeProducerTest);
 };
 
 struct DataPipeObserverData {
diff --git a/mojo/public/cpp/system/tests/handle_signal_tracker_unittest.cc b/mojo/public/cpp/system/tests/handle_signal_tracker_unittest.cc
index f449956..abef53e 100644
--- a/mojo/public/cpp/system/tests/handle_signal_tracker_unittest.cc
+++ b/mojo/public/cpp/system/tests/handle_signal_tracker_unittest.cc
@@ -18,6 +18,10 @@
 class HandleSignalTrackerTest : public testing::Test {
  public:
   HandleSignalTrackerTest() {}
+
+  HandleSignalTrackerTest(const HandleSignalTrackerTest&) = delete;
+  HandleSignalTrackerTest& operator=(const HandleSignalTrackerTest&) = delete;
+
   ~HandleSignalTrackerTest() override {}
 
   void WaitForNextNotification(HandleSignalTracker* tracker) {
@@ -34,8 +38,6 @@
 
  private:
   base::test::TaskEnvironment task_environment_;
-
-  DISALLOW_COPY_AND_ASSIGN(HandleSignalTrackerTest);
 };
 
 TEST_F(HandleSignalTrackerTest, StartsWithCorrectState) {
diff --git a/mojo/public/cpp/system/tests/invitation_unittest.cc b/mojo/public/cpp/system/tests/invitation_unittest.cc
index 7bc31d99..8d215ddd 100644
--- a/mojo/public/cpp/system/tests/invitation_unittest.cc
+++ b/mojo/public/cpp/system/tests/invitation_unittest.cc
@@ -59,6 +59,10 @@
                           public testing::WithParamInterface<TransportType> {
  public:
   InvitationCppTest() = default;
+
+  InvitationCppTest(const InvitationCppTest&) = delete;
+  InvitationCppTest& operator=(const InvitationCppTest&) = delete;
+
   ~InvitationCppTest() override = default;
 
  protected:
@@ -175,8 +179,6 @@
  private:
   base::test::TaskEnvironment task_environment_;
   base::Process child_process_;
-
-  DISALLOW_COPY_AND_ASSIGN(InvitationCppTest);
 };
 
 class TestClientBase : public InvitationCppTest {
diff --git a/mojo/public/cpp/system/tests/scope_to_message_pipe_unittest.cc b/mojo/public/cpp/system/tests/scope_to_message_pipe_unittest.cc
index 8fa266b..2bc5f384 100644
--- a/mojo/public/cpp/system/tests/scope_to_message_pipe_unittest.cc
+++ b/mojo/public/cpp/system/tests/scope_to_message_pipe_unittest.cc
@@ -21,22 +21,27 @@
  public:
   explicit RunCallbackOnDestruction(base::OnceClosure destruction_callback)
       : destruction_callback_(std::move(destruction_callback)) {}
+
+  RunCallbackOnDestruction(const RunCallbackOnDestruction&) = delete;
+  RunCallbackOnDestruction& operator=(const RunCallbackOnDestruction&) = delete;
+
   ~RunCallbackOnDestruction() { std::move(destruction_callback_).Run(); }
 
  private:
   base::OnceClosure destruction_callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(RunCallbackOnDestruction);
 };
 
 class ScopeToMessagePipeTest : public testing::Test {
  public:
   ScopeToMessagePipeTest() = default;
+
+  ScopeToMessagePipeTest(const ScopeToMessagePipeTest&) = delete;
+  ScopeToMessagePipeTest& operator=(const ScopeToMessagePipeTest&) = delete;
+
   ~ScopeToMessagePipeTest() override = default;
 
  private:
   base::test::TaskEnvironment task_environment_;
-  DISALLOW_COPY_AND_ASSIGN(ScopeToMessagePipeTest);
 };
 
 TEST_F(ScopeToMessagePipeTest, ObjectDestroyedOnPeerClosure) {
diff --git a/mojo/public/cpp/system/tests/simple_watcher_unittest.cc b/mojo/public/cpp/system/tests/simple_watcher_unittest.cc
index 2017576b..de6329f 100644
--- a/mojo/public/cpp/system/tests/simple_watcher_unittest.cc
+++ b/mojo/public/cpp/system/tests/simple_watcher_unittest.cc
@@ -37,12 +37,14 @@
 class SimpleWatcherTest : public testing::Test {
  public:
   SimpleWatcherTest() {}
+
+  SimpleWatcherTest(const SimpleWatcherTest&) = delete;
+  SimpleWatcherTest& operator=(const SimpleWatcherTest&) = delete;
+
   ~SimpleWatcherTest() override {}
 
  private:
   base::test::SingleThreadTaskEnvironment task_environment_;
-
-  DISALLOW_COPY_AND_ASSIGN(SimpleWatcherTest);
 };
 
 TEST_F(SimpleWatcherTest, WatchBasic) {
diff --git a/mojo/public/cpp/system/tests/string_data_source_unittest.cc b/mojo/public/cpp/system/tests/string_data_source_unittest.cc
index 92d74d2..41d3501 100644
--- a/mojo/public/cpp/system/tests/string_data_source_unittest.cc
+++ b/mojo/public/cpp/system/tests/string_data_source_unittest.cc
@@ -39,6 +39,10 @@
                    base::BindRepeating(&DataPipeReader::OnDataAvailable,
                                        base::Unretained(this)));
   }
+
+  DataPipeReader(const DataPipeReader&) = delete;
+  DataPipeReader& operator=(const DataPipeReader&) = delete;
+
   ~DataPipeReader() = default;
 
   const std::string& data() const { return data_; }
@@ -72,13 +76,15 @@
   base::OnceClosure on_read_done_;
   SimpleWatcher watcher_;
   std::string data_;
-
-  DISALLOW_COPY_AND_ASSIGN(DataPipeReader);
 };
 
 class StringDataSourceTest : public testing::Test {
  public:
   StringDataSourceTest() = default;
+
+  StringDataSourceTest(const StringDataSourceTest&) = delete;
+  StringDataSourceTest& operator=(const StringDataSourceTest&) = delete;
+
   ~StringDataSourceTest() override = default;
 
  protected:
@@ -127,8 +133,6 @@
 
  private:
   base::test::TaskEnvironment task_environment_;
-
-  DISALLOW_COPY_AND_ASSIGN(StringDataSourceTest);
 };
 
 TEST_F(StringDataSourceTest, EqualCapacity) {
diff --git a/mojo/public/cpp/system/tests/wait_set_unittest.cc b/mojo/public/cpp/system/tests/wait_set_unittest.cc
index 0fb3707..6d1e487 100644
--- a/mojo/public/cpp/system/tests/wait_set_unittest.cc
+++ b/mojo/public/cpp/system/tests/wait_set_unittest.cc
@@ -42,14 +42,16 @@
  public:
   explicit ThreadedRunner(base::OnceClosure callback)
       : SimpleThread("ThreadedRunner"), callback_(std::move(callback)) {}
+
+  ThreadedRunner(const ThreadedRunner&) = delete;
+  ThreadedRunner& operator=(const ThreadedRunner&) = delete;
+
   ~ThreadedRunner() override { Join(); }
 
   void Run() override { std::move(callback_).Run(); }
 
  private:
   base::OnceClosure callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(ThreadedRunner);
 };
 
 TEST_F(WaitSetTest, Satisfied) {
diff --git a/mojo/public/cpp/system/tests/wait_unittest.cc b/mojo/public/cpp/system/tests/wait_unittest.cc
index e117c8e..8c11846 100644
--- a/mojo/public/cpp/system/tests/wait_unittest.cc
+++ b/mojo/public/cpp/system/tests/wait_unittest.cc
@@ -44,14 +44,16 @@
  public:
   explicit ThreadedRunner(base::OnceClosure callback)
       : SimpleThread("ThreadedRunner"), callback_(std::move(callback)) {}
+
+  ThreadedRunner(const ThreadedRunner&) = delete;
+  ThreadedRunner& operator=(const ThreadedRunner&) = delete;
+
   ~ThreadedRunner() override { Join(); }
 
   void Run() override { std::move(callback_).Run(); }
 
  private:
   base::OnceClosure callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(ThreadedRunner);
 };
 
 TEST_F(WaitTest, InvalidArguments) {
diff --git a/mojo/public/cpp/system/wait_set.h b/mojo/public/cpp/system/wait_set.h
index efb54dea..d57d0367 100644
--- a/mojo/public/cpp/system/wait_set.h
+++ b/mojo/public/cpp/system/wait_set.h
@@ -35,6 +35,10 @@
 class MOJO_CPP_SYSTEM_EXPORT WaitSet {
  public:
   WaitSet();
+
+  WaitSet(const WaitSet&) = delete;
+  WaitSet& operator=(const WaitSet&) = delete;
+
   ~WaitSet();
 
   // Adds |event| to the set of events to wait on. If successful, any future
@@ -116,8 +120,6 @@
   // Thread-safe state associated with this WaitSet. Used to aggregate
   // notifications from watched handles.
   scoped_refptr<State> state_;
-
-  DISALLOW_COPY_AND_ASSIGN(WaitSet);
 };
 
 }  // namespace mojo
diff --git a/mojo/public/cpp/test_support/test_utils.h b/mojo/public/cpp/test_support/test_utils.h
index a62679f..e16a343 100644
--- a/mojo/public/cpp/test_support/test_utils.h
+++ b/mojo/public/cpp/test_support/test_utils.h
@@ -96,6 +96,10 @@
 class BadMessageObserver {
  public:
   BadMessageObserver();
+
+  BadMessageObserver(const BadMessageObserver&) = delete;
+  BadMessageObserver& operator=(const BadMessageObserver&) = delete;
+
   ~BadMessageObserver();
 
   // Waits for the bad message and returns the error string.
@@ -110,8 +114,6 @@
   std::string last_error_for_bad_message_;
   bool got_bad_message_;
   base::RunLoop run_loop_;
-
-  DISALLOW_COPY_AND_ASSIGN(BadMessageObserver);
 };
 
 }  // namespace test
diff --git a/mojo/public/java/system/watcher_impl.cc b/mojo/public/java/system/watcher_impl.cc
index e251d2e6..065677f 100644
--- a/mojo/public/java/system/watcher_impl.cc
+++ b/mojo/public/java/system/watcher_impl.cc
@@ -26,6 +26,9 @@
                  SimpleWatcher::ArmingPolicy::AUTOMATIC,
                  base::SequencedTaskRunnerHandle::Get()) {}
 
+  WatcherImpl(const WatcherImpl&) = delete;
+  WatcherImpl& operator=(const WatcherImpl&) = delete;
+
   ~WatcherImpl() = default;
 
   jint Start(JNIEnv* env,
@@ -67,8 +70,6 @@
 
   SimpleWatcher watcher_;
   base::android::ScopedJavaGlobalRef<jobject> java_watcher_;
-
-  DISALLOW_COPY_AND_ASSIGN(WatcherImpl);
 };
 
 }  // namespace
diff --git a/pdf/ppapi_migration/url_loader.cc b/pdf/ppapi_migration/url_loader.cc
index 6d2d89ec2..59eadb3b 100644
--- a/pdf/ppapi_migration/url_loader.cc
+++ b/pdf/ppapi_migration/url_loader.cc
@@ -345,7 +345,6 @@
   pp::URLRequestInfo pp_request(plugin_instance_);
   pp_request.SetURL(request.url);
   pp_request.SetMethod(request.method);
-  pp_request.SetCustomReferrerURL(request.url);
 
   if (request.ignore_redirects)
     pp_request.SetFollowRedirects(false);
diff --git a/remoting/host/chromoting_messages.h b/remoting/host/chromoting_messages.h
index f5748461..d879a7c 100644
--- a/remoting/host/chromoting_messages.h
+++ b/remoting/host/chromoting_messages.h
@@ -127,19 +127,6 @@
 IPC_MESSAGE_CONTROL(ChromotingNetworkDaemonMsg_HostShutdown)
 
 //-----------------------------------------------------------------------------
-// Chromoting messages sent from the desktop to the daemon process.
-
-// Notifies the daemon that a desktop integration process has been initialized.
-// |desktop_pipe| specifies the client end of the desktop pipe. It is to be
-// forwarded to the desktop environment stub.
-IPC_MESSAGE_CONTROL(ChromotingDesktopDaemonMsg_DesktopAttached,
-                    IPC::ChannelHandle /* desktop_pipe */)
-
-// Asks the daemon to inject Secure Attention Sequence (SAS) in the session
-// where the desktop process is running.
-IPC_MESSAGE_CONTROL(ChromotingDesktopDaemonMsg_InjectSas)
-
-//-----------------------------------------------------------------------------
 // Chromoting messages sent from the desktop to the network process.
 
 // Notifies the network process that a shared buffer has been created.
diff --git a/remoting/host/daemon_process.cc b/remoting/host/daemon_process.cc
index 3cf7c07..64a5e2f 100644
--- a/remoting/host/daemon_process.cc
+++ b/remoting/host/daemon_process.cc
@@ -138,6 +138,15 @@
   stats_sender_.reset();
 }
 
+void DaemonProcess::OnAssociatedInterfaceRequest(
+    const std::string& interface_name,
+    mojo::ScopedInterfaceEndpointHandle handle) {
+  // TODO(b/178114059): Implement this after migrating IPC macros to Mojo.
+  LOG(ERROR) << "Received unexpected associated interface request: "
+             << interface_name;
+  CrashNetworkProcess(FROM_HERE);
+}
+
 void DaemonProcess::CloseDesktopSession(int terminal_id) {
   DCHECK(caller_task_runner()->BelongsToCurrentThread());
 
diff --git a/remoting/host/daemon_process.h b/remoting/host/daemon_process.h
index b048d5bd..11fb16e 100644
--- a/remoting/host/daemon_process.h
+++ b/remoting/host/daemon_process.h
@@ -18,6 +18,7 @@
 #include "base/time/time.h"
 #include "ipc/ipc_channel.h"
 #include "ipc/ipc_channel_handle.h"
+#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
 #include "remoting/host/config_watcher.h"
 #include "remoting/host/current_process_stats_agent.h"
 #include "remoting/host/host_status_monitor.h"
@@ -73,6 +74,9 @@
   bool OnMessageReceived(const IPC::Message& message) override;
   void OnPermanentError(int exit_code) override;
   void OnWorkerProcessStopped() override;
+  void OnAssociatedInterfaceRequest(
+      const std::string& interface_name,
+      mojo::ScopedInterfaceEndpointHandle handle) override;
 
   // Sends an IPC message to the network process. The message will be dropped
   // unless the network process is connected over the IPC channel.
@@ -90,6 +94,9 @@
   // Closes the desktop session identified by |terminal_id|.
   void CloseDesktopSession(int terminal_id);
 
+  // Requests the network process to crash.
+  void CrashNetworkProcess(const base::Location& location);
+
  protected:
   DaemonProcess(scoped_refptr<AutoThreadTaskRunner> caller_task_runner,
                 scoped_refptr<AutoThreadTaskRunner> io_task_runner,
@@ -104,9 +111,6 @@
   // |terminal_id|.
   void SetScreenResolution(int terminal_id, const ScreenResolution& resolution);
 
-  // Requests the network process to crash.
-  void CrashNetworkProcess(const base::Location& location);
-
   // Reads the host configuration and launches the network process.
   void Initialize();
 
diff --git a/remoting/host/desktop_process.cc b/remoting/host/desktop_process.cc
index 88bf1d0..608f44e 100644
--- a/remoting/host/desktop_process.cc
+++ b/remoting/host/desktop_process.cc
@@ -60,10 +60,18 @@
   OnChannelError();
 }
 
+void DesktopProcess::CrashNetworkProcess(const base::Location& location) {
+  DCHECK(caller_task_runner_->BelongsToCurrentThread());
+
+  LOG(ERROR) << "Asking the daemon process to crash the network process. "
+             << "Request originated from: " << location.ToString();
+  desktop_session_request_handler_->CrashNetworkProcess();
+}
+
 void DesktopProcess::InjectSas() {
   DCHECK(caller_task_runner_->BelongsToCurrentThread());
 
-  daemon_channel_->Send(new ChromotingDesktopDaemonMsg_InjectSas());
+  desktop_session_request_handler_->InjectSecureAttentionSequence();
 }
 
 void DesktopProcess::LockWorkstation() {
@@ -108,6 +116,7 @@
     desktop_agent_->Stop();
     desktop_agent_ = nullptr;
   }
+  desktop_session_request_handler_.reset();
 
   caller_task_runner_ = nullptr;
   input_task_runner_ = nullptr;
@@ -150,9 +159,12 @@
       daemon_channel_handle_.release(), IPC::Channel::MODE_CLIENT, this,
       io_task_runner_, base::ThreadTaskRunnerHandle::Get());
 
+  daemon_channel_->GetRemoteAssociatedInterface(
+      &desktop_session_request_handler_);
+
   // Pass |desktop_pipe| to the daemon.
-  daemon_channel_->Send(
-      new ChromotingDesktopDaemonMsg_DesktopAttached(desktop_pipe.release()));
+  desktop_session_request_handler_->ConnectDesktopChannel(
+      std::move(desktop_pipe));
 
   return true;
 }
diff --git a/remoting/host/desktop_process.h b/remoting/host/desktop_process.h
index 8d21701..7d987ed 100644
--- a/remoting/host/desktop_process.h
+++ b/remoting/host/desktop_process.h
@@ -15,8 +15,14 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "ipc/ipc_listener.h"
+#include "mojo/public/cpp/bindings/associated_remote.h"
 #include "mojo/public/cpp/system/message_pipe.h"
 #include "remoting/host/desktop_session_agent.h"
+#include "remoting/host/mojom/desktop_session.mojom.h"
+
+namespace base {
+class Location;
+}
 
 namespace IPC {
 class ChannelProxy;
@@ -44,6 +50,7 @@
   // DesktopSessionAgent::Delegate implementation.
   DesktopEnvironmentFactory& desktop_environment_factory() override;
   void OnNetworkProcessDisconnected() override;
+  void CrashNetworkProcess(const base::Location& location) override;
 
   // IPC::Listener implementation.
   bool OnMessageReceived(const IPC::Message& message) override;
@@ -92,6 +99,9 @@
   // the network process.
   scoped_refptr<DesktopSessionAgent> desktop_agent_;
 
+  mojo::AssociatedRemote<mojom::DesktopSessionRequestHandler>
+      desktop_session_request_handler_;
+
   base::WeakPtrFactory<DesktopProcess> weak_factory_{this};
 };
 
diff --git a/remoting/host/desktop_process_unittest.cc b/remoting/host/desktop_process_unittest.cc
index 2ad94c1..2a134898 100644
--- a/remoting/host/desktop_process_unittest.cc
+++ b/remoting/host/desktop_process_unittest.cc
@@ -31,6 +31,7 @@
 #include "remoting/host/fake_mouse_cursor_monitor.h"
 #include "remoting/host/host_exit_codes.h"
 #include "remoting/host/host_mock_objects.h"
+#include "remoting/host/mojom/desktop_session.mojom.h"
 #include "remoting/host/remote_open_url/fake_url_forwarder_configurator.h"
 #include "remoting/host/screen_resolution.h"
 #include "remoting/protocol/fake_desktop_capturer.h"
@@ -49,7 +50,8 @@
 
 namespace {
 
-class MockDaemonListener : public IPC::Listener {
+class MockDaemonListener : public IPC::Listener,
+                           public mojom::DesktopSessionRequestHandler {
  public:
   MockDaemonListener() = default;
 
@@ -59,10 +61,24 @@
   ~MockDaemonListener() override = default;
 
   bool OnMessageReceived(const IPC::Message& message) override;
+  void OnAssociatedInterfaceRequest(
+      const std::string& interface_name,
+      mojo::ScopedInterfaceEndpointHandle handle) override;
 
-  MOCK_METHOD1(OnDesktopAttached, void(const IPC::ChannelHandle&));
-  MOCK_METHOD1(OnChannelConnected, void(int32_t));
-  MOCK_METHOD0(OnChannelError, void());
+  MOCK_METHOD(void,
+              ConnectDesktopChannel,
+              (mojo::ScopedMessagePipeHandle handle),
+              (override));
+  MOCK_METHOD(void, InjectSecureAttentionSequence, (), (override));
+  MOCK_METHOD(void, CrashNetworkProcess, (), (override));
+  MOCK_METHOD(void, OnChannelConnected, (int32_t), (override));
+  MOCK_METHOD(void, OnChannelError, (), (override));
+
+  void Disconnect();
+
+ private:
+  mojo::AssociatedReceiver<mojom::DesktopSessionRequestHandler>
+      desktop_session_request_handler_{this};
 };
 
 class MockNetworkListener : public IPC::Listener {
@@ -76,22 +92,28 @@
 
   bool OnMessageReceived(const IPC::Message& message) override;
 
-  MOCK_METHOD1(OnChannelConnected, void(int32_t));
-  MOCK_METHOD0(OnChannelError, void());
+  MOCK_METHOD(void, OnChannelConnected, (int32_t), (override));
+  MOCK_METHOD(void, OnChannelError, (), (override));
 
   MOCK_METHOD0(OnDesktopEnvironmentCreated, void());
 };
 
 bool MockDaemonListener::OnMessageReceived(const IPC::Message& message) {
-  bool handled = true;
-  IPC_BEGIN_MESSAGE_MAP(MockDaemonListener, message)
-    IPC_MESSAGE_HANDLER(ChromotingDesktopDaemonMsg_DesktopAttached,
-                        OnDesktopAttached)
-    IPC_MESSAGE_UNHANDLED(handled = false)
-  IPC_END_MESSAGE_MAP()
+  ADD_FAILURE() << "Unexpected call to OnMessageReceived()";
+  return false;
+}
 
-  EXPECT_TRUE(handled);
-  return handled;
+void MockDaemonListener::OnAssociatedInterfaceRequest(
+    const std::string& interface_name,
+    mojo::ScopedInterfaceEndpointHandle handle) {
+  EXPECT_EQ(mojom::DesktopSessionRequestHandler::Name_, interface_name);
+  mojo::PendingAssociatedReceiver<mojom::DesktopSessionRequestHandler>
+      pending_receiver(std::move(handle));
+  desktop_session_request_handler_.Bind(std::move(pending_receiver));
+}
+
+void MockDaemonListener::Disconnect() {
+  desktop_session_request_handler_.reset();
 }
 
 bool MockNetworkListener::OnMessageReceived(const IPC::Message& message) {
@@ -110,9 +132,9 @@
   DesktopProcessTest();
   ~DesktopProcessTest() override;
 
-  // MockDaemonListener mocks
-  void ConnectNetworkChannel(const IPC::ChannelHandle& desktop_process);
-  void OnDesktopAttached(const IPC::ChannelHandle& desktop_process);
+  // Methods invoked when MockDaemonListener::ConnectDesktopChannel is called.
+  void CreateNetworkChannel(mojo::ScopedMessagePipeHandle desktop_pipe);
+  void StoreDesktopHandle(mojo::ScopedMessagePipeHandle desktop_pipe);
 
   // Creates a DesktopEnvironment with a fake webrtc::DesktopCapturer, to mock
   // DesktopEnvironmentFactory::Create().
@@ -161,6 +183,9 @@
   // Delegate that is passed to |daemon_channel_|.
   MockDaemonListener daemon_listener_;
 
+  mojo::AssociatedRemote<mojom::DesktopSessionRequestHandler>
+      desktop_session_request_handler_;
+
   // Runs the daemon's end of the channel.
   base::test::SingleThreadTaskEnvironment task_environment_{
       base::test::SingleThreadTaskEnvironment::MainThreadType::UI};
@@ -173,23 +198,23 @@
   // Delegate that is passed to |network_channel_|.
   MockNetworkListener network_listener_;
 
-  mojo::ScopedMessagePipeHandle desktop_process_channel_;
+  mojo::ScopedMessagePipeHandle desktop_pipe_handle_;
 };
 
 DesktopProcessTest::DesktopProcessTest() = default;
 
 DesktopProcessTest::~DesktopProcessTest() = default;
 
-void DesktopProcessTest::ConnectNetworkChannel(
-    const IPC::ChannelHandle& channel_handle) {
+void DesktopProcessTest::CreateNetworkChannel(
+    mojo::ScopedMessagePipeHandle desktop_pipe) {
   network_channel_ = IPC::ChannelProxy::Create(
-      channel_handle, IPC::Channel::MODE_CLIENT, &network_listener_,
+      desktop_pipe.release(), IPC::Channel::MODE_CLIENT, &network_listener_,
       io_task_runner_.get(), base::ThreadTaskRunnerHandle::Get());
 }
 
-void DesktopProcessTest::OnDesktopAttached(
-    const IPC::ChannelHandle& desktop_process) {
-  desktop_process_channel_.reset(desktop_process.mojo_handle);
+void DesktopProcessTest::StoreDesktopHandle(
+    mojo::ScopedMessagePipeHandle desktop_pipe) {
+  desktop_pipe_handle_ = std::move(desktop_pipe);
 }
 
 DesktopEnvironment* DesktopProcessTest::CreateDesktopEnvironment() {
@@ -199,6 +224,7 @@
   EXPECT_CALL(*desktop_environment, CreateInputInjectorPtr())
       .Times(AtMost(1))
       .WillOnce(Invoke(this, &DesktopProcessTest::CreateInputInjector));
+  EXPECT_CALL(*desktop_environment, CreateActionExecutorPtr()).Times(AtMost(1));
   EXPECT_CALL(*desktop_environment, CreateScreenControlsPtr())
       .Times(AtMost(1));
   EXPECT_CALL(*desktop_environment, CreateVideoCapturerPtr())
@@ -214,6 +240,7 @@
       .Times(AtMost(1))
       .WillOnce(
           Return(ByMove(std::make_unique<FakeUrlForwarderConfigurator>())));
+  EXPECT_CALL(*desktop_environment, CreateFileOperationsPtr()).Times(AtMost(1));
   EXPECT_CALL(*desktop_environment, GetCapabilities())
       .Times(AtMost(1));
   EXPECT_CALL(*desktop_environment, SetCapabilities(_))
@@ -245,6 +272,9 @@
 
 void DesktopProcessTest::DisconnectChannels() {
   daemon_channel_.reset();
+  desktop_pipe_handle_.reset();
+  daemon_listener_.Disconnect();
+
   network_channel_.reset();
   io_task_runner_ = nullptr;
 }
@@ -294,10 +324,11 @@
 void DesktopProcessTest::RunDeathTest() {
   InSequence s;
   EXPECT_CALL(daemon_listener_, OnChannelConnected(_));
-  EXPECT_CALL(daemon_listener_, OnDesktopAttached(_))
-      .WillOnce(DoAll(
-          Invoke(this, &DesktopProcessTest::OnDesktopAttached),
-          InvokeWithoutArgs(this, &DesktopProcessTest::SendCrashRequest)));
+  EXPECT_CALL(daemon_listener_, ConnectDesktopChannel(_))
+      .WillOnce([&](mojo::ScopedMessagePipeHandle desktop_pipe) {
+        StoreDesktopHandle(std::move(desktop_pipe));
+        SendCrashRequest();
+      });
 
   RunDesktopProcess();
 }
@@ -314,24 +345,27 @@
       DesktopEnvironmentOptions()));
 }
 
-// Launches the desktop process and waits when it connects back.
+// Launches the desktop process and then disconnects immediately.
 TEST_F(DesktopProcessTest, Basic) {
   InSequence s;
   EXPECT_CALL(daemon_listener_, OnChannelConnected(_));
-  EXPECT_CALL(daemon_listener_, OnDesktopAttached(_))
-      .WillOnce(DoAll(
-          Invoke(this, &DesktopProcessTest::OnDesktopAttached),
-          InvokeWithoutArgs(this, &DesktopProcessTest::DisconnectChannels)));
+  EXPECT_CALL(daemon_listener_, ConnectDesktopChannel(_))
+      .WillOnce([&](mojo::ScopedMessagePipeHandle desktop_pipe) {
+        StoreDesktopHandle(std::move(desktop_pipe));
+        DisconnectChannels();
+      });
 
   RunDesktopProcess();
 }
 
-// Launches the desktop process and waits when it connects back.
-TEST_F(DesktopProcessTest, ConnectNetworkChannel) {
+// Launches the desktop process and waits until the IPC channel is established.
+TEST_F(DesktopProcessTest, CreateNetworkChannel) {
   InSequence s;
   EXPECT_CALL(daemon_listener_, OnChannelConnected(_));
-  EXPECT_CALL(daemon_listener_, OnDesktopAttached(_))
-      .WillOnce(Invoke(this, &DesktopProcessTest::ConnectNetworkChannel));
+  EXPECT_CALL(daemon_listener_, ConnectDesktopChannel(_))
+      .WillOnce([&](mojo::ScopedMessagePipeHandle desktop_pipe) {
+        CreateNetworkChannel(std::move(desktop_pipe));
+      });
   EXPECT_CALL(network_listener_, OnChannelConnected(_))
       .WillOnce(InvokeWithoutArgs(
           this, &DesktopProcessTest::DisconnectChannels));
@@ -339,14 +373,16 @@
   RunDesktopProcess();
 }
 
-// Launches the desktop process, waits when it connects back and starts
-// the desktop session agent.
+// Launches the desktop process, waits until the IPC channel is established,
+// then starts the desktop session agent.
 TEST_F(DesktopProcessTest, StartSessionAgent) {
   {
     InSequence s;
     EXPECT_CALL(daemon_listener_, OnChannelConnected(_));
-    EXPECT_CALL(daemon_listener_, OnDesktopAttached(_))
-        .WillOnce(Invoke(this, &DesktopProcessTest::ConnectNetworkChannel));
+    EXPECT_CALL(daemon_listener_, ConnectDesktopChannel(_))
+        .WillOnce([&](mojo::ScopedMessagePipeHandle desktop_pipe) {
+          CreateNetworkChannel(std::move(desktop_pipe));
+        });
     EXPECT_CALL(network_listener_, OnChannelConnected(_))
         .WillOnce(InvokeWithoutArgs(
             this, &DesktopProcessTest::SendStartSessionAgent));
diff --git a/remoting/host/desktop_session_agent.cc b/remoting/host/desktop_session_agent.cc
index 3a9fbd6..77171435 100644
--- a/remoting/host/desktop_session_agent.cc
+++ b/remoting/host/desktop_session_agent.cc
@@ -33,7 +33,7 @@
 #include "remoting/host/desktop_environment.h"
 #include "remoting/host/input_injector.h"
 #include "remoting/host/keyboard_layout_monitor.h"
-#include "remoting/host/mojom/url_forwarder_configurator.mojom-shared.h"
+#include "remoting/host/mojom/desktop_session.mojom-shared.h"
 #include "remoting/host/process_stats_sender.h"
 #include "remoting/host/remote_input_filter.h"
 #include "remoting/host/remote_open_url/url_forwarder_configurator.h"
@@ -315,25 +315,20 @@
     mojo::ScopedInterfaceEndpointHandle handle) {
   DCHECK(caller_task_runner_->BelongsToCurrentThread());
 
-  if (interface_name == mojom::ClipboardEventHandler::Name_) {
-    if (clipboard_handler_receiver_.is_bound()) {
+  if (interface_name == mojom::DesktopSessionControl::Name_) {
+    if (desktop_session_control_.is_bound()) {
       LOG(ERROR) << "Receiver already bound for associated interface: "
-                 << mojom::ClipboardEventHandler::Name_;
-      CrashProcess(base::Location::Current());
+                 << mojom::DesktopSessionControl::Name_;
+      delegate_->CrashNetworkProcess(base::Location::Current());
     }
 
-    mojo::PendingAssociatedReceiver<mojom::ClipboardEventHandler>
+    mojo::PendingAssociatedReceiver<mojom::DesktopSessionControl>
         pending_receiver(std::move(handle));
-    clipboard_handler_receiver_.Bind(std::move(pending_receiver));
-  } else if (interface_name == mojom::UrlForwarderConfigurator::Name_) {
-    if (url_forwarder_configurator_receiver_.is_bound()) {
-      LOG(ERROR) << "Receiver already bound for associated interface: "
-                 << mojom::UrlForwarderConfigurator::Name_;
-      CrashProcess(base::Location::Current());
-    }
-    mojo::PendingAssociatedReceiver<mojom::UrlForwarderConfigurator>
-        pending_receiver(std::move(handle));
-    url_forwarder_configurator_receiver_.Bind(std::move(pending_receiver));
+    desktop_session_control_.Bind(std::move(pending_receiver));
+  } else {
+    LOG(ERROR) << "Unknown associated interface requested: " << interface_name
+               << ", crashing the network process";
+    delegate_->CrashNetworkProcess(base::Location::Current());
   }
 }
 
@@ -412,10 +407,9 @@
   started_ = true;
   client_jid_ = authenticated_jid;
 
-  // Hook up the associated interfaces.
-  network_channel_->GetRemoteAssociatedInterface(&clipboard_observer_remote_);
+  // Hook up the associated interface.
   network_channel_->GetRemoteAssociatedInterface(
-      &url_forwarder_state_observer_remote_);
+      &desktop_session_event_handler_);
 
   // Create a desktop environment for the new session.
   desktop_environment_ = delegate_->desktop_environment_factory().Create(
@@ -535,8 +529,8 @@
   DCHECK(caller_task_runner_->BelongsToCurrentThread());
   CHECK(started_) << "OnClipboardEvent called before agent was started.";
 
-  if (clipboard_observer_remote_) {
-    clipboard_observer_remote_->OnClipboardEvent(event);
+  if (desktop_session_event_handler_) {
+    desktop_session_event_handler_->OnClipboardEvent(event);
   }
 }
 
@@ -610,11 +604,9 @@
     weak_factory_.InvalidateWeakPtrs();
     client_jid_.clear();
 
-    clipboard_observer_remote_.reset();
-    clipboard_handler_receiver_.reset();
+    desktop_session_event_handler_.reset();
+    desktop_session_control_.reset();
 
-    url_forwarder_configurator_receiver_.reset();
-    url_forwarder_state_observer_remote_.reset();
     url_forwarder_configurator_.reset();
 
     remote_input_filter_.reset();
@@ -821,7 +813,7 @@
 
 void DesktopSessionAgent::OnCheckUrlForwarderSetUpResult(bool is_set_up) {
   DCHECK(caller_task_runner_->BelongsToCurrentThread());
-  url_forwarder_state_observer_remote_->OnUrlForwarderStateChange(
+  desktop_session_event_handler_->OnUrlForwarderStateChange(
       is_set_up ? mojom::UrlForwarderState::kSetUp
                 : mojom::UrlForwarderState::kNotSetUp);
 }
@@ -844,7 +836,7 @@
       NOTREACHED() << "Unknown state: " << state;
       mojo_state = mojom::UrlForwarderState::kUnknown;
   }
-  url_forwarder_state_observer_remote_->OnUrlForwarderStateChange(mojo_state);
+  desktop_session_event_handler_->OnUrlForwarderStateChange(mojo_state);
 }
 
 }  // namespace remoting
diff --git a/remoting/host/desktop_session_agent.h b/remoting/host/desktop_session_agent.h
index c6cd87a..6b93e4a 100644
--- a/remoting/host/desktop_session_agent.h
+++ b/remoting/host/desktop_session_agent.h
@@ -28,9 +28,8 @@
 #include "remoting/host/desktop_display_info.h"
 #include "remoting/host/desktop_environment_options.h"
 #include "remoting/host/file_transfer/session_file_operations_handler.h"
-#include "remoting/host/mojom/clipboard.mojom.h"
+#include "remoting/host/mojom/desktop_session.mojom.h"
 #include "remoting/host/mojom/remoting_mojom_traits.h"
-#include "remoting/host/mojom/url_forwarder_configurator.mojom.h"
 #include "remoting/proto/url_forwarder_control.pb.h"
 #include "remoting/protocol/clipboard_stub.h"
 #include "remoting/protocol/process_stats_stub.h"
@@ -39,6 +38,10 @@
 #include "third_party/webrtc/modules/desktop_capture/mouse_cursor_monitor.h"
 #include "ui/events/event.h"
 
+namespace base {
+class Location;
+}
+
 namespace IPC {
 class ChannelProxy;
 class Message;
@@ -75,8 +78,7 @@
       public ClientSessionControl,
       public protocol::ProcessStatsStub,
       public IpcFileOperations::ResultHandler,
-      public mojom::ClipboardEventHandler,
-      public mojom::UrlForwarderConfigurator {
+      public mojom::DesktopSessionControl {
  public:
   class Delegate {
    public:
@@ -88,6 +90,12 @@
     // Notifies the delegate that the network-to-desktop channel has been
     // disconnected.
     virtual void OnNetworkProcessDisconnected() = 0;
+
+    // Allows the desktop process to ask the daemon process to crash the network
+    // process. This should be called any time the network process sends an
+    // invalid IPC message to the desktop process (indicating that the network
+    // process might have been compromised).
+    virtual void CrashNetworkProcess(const base::Location& location) = 0;
   };
 
   DesktopSessionAgent(
@@ -125,8 +133,9 @@
   void OnDataResult(std::uint64_t file_id,
                     ResultHandler::DataResult result) override;
 
-  // mojom::ClipboardEventHandler implementation.
+  // mojom::DesktopSessionControl implementation.
   void InjectClipboardEvent(const protocol::ClipboardEvent& event) override;
+  void SetUpUrlForwarder() override;
 
   // Creates desktop integration components and a connected IPC channel to be
   // used to access them. The client end of the channel is returned.
@@ -197,9 +206,6 @@
   void StopProcessStatsReport();
 
  private:
-  // mojom::UrlForwarderConfigurator implementation.
-  void SetUpUrlForwarder() override;
-
   void OnCheckUrlForwarderSetUpResult(bool is_set_up);
   void OnUrlForwarderSetUpStateChanged(
       protocol::UrlForwarderControl::SetUpUrlForwarderResponse::State state);
@@ -269,20 +275,15 @@
 
   CurrentProcessStatsAgent current_process_stats_;
 
-  mojo::AssociatedRemote<mojom::ClipboardEventObserver>
-      clipboard_observer_remote_;
-  mojo::AssociatedReceiver<mojom::ClipboardEventHandler>
-      clipboard_handler_receiver_{this};
+  mojo::AssociatedRemote<mojom::DesktopSessionEventHandler>
+      desktop_session_event_handler_;
+  mojo::AssociatedReceiver<mojom::DesktopSessionControl>
+      desktop_session_control_{this};
 
   // Checks and configures the URL forwarder.
   std::unique_ptr<::remoting::UrlForwarderConfigurator>
       url_forwarder_configurator_;
 
-  mojo::AssociatedReceiver<mojom::UrlForwarderConfigurator>
-      url_forwarder_configurator_receiver_{this};
-  mojo::AssociatedRemote<mojom::UrlForwarderStateObserver>
-      url_forwarder_state_observer_remote_;
-
   // Used to disable callbacks to |this|.
   base::WeakPtrFactory<DesktopSessionAgent> weak_factory_{this};
 
diff --git a/remoting/host/desktop_session_agent_unittest.cc b/remoting/host/desktop_session_agent_unittest.cc
index b12933d4..ed7e79d6 100644
--- a/remoting/host/desktop_session_agent_unittest.cc
+++ b/remoting/host/desktop_session_agent_unittest.cc
@@ -40,6 +40,8 @@
 
   void OnNetworkProcessDisconnected() override {}
 
+  void CrashNetworkProcess(const base::Location& location) override {}
+
   base::WeakPtr<Delegate> GetWeakPtr() { return weak_ptr_.GetWeakPtr(); }
 
  private:
diff --git a/remoting/host/desktop_session_proxy.cc b/remoting/host/desktop_session_proxy.cc
index 2198ab6e..d303e7d 100644
--- a/remoting/host/desktop_session_proxy.cc
+++ b/remoting/host/desktop_session_proxy.cc
@@ -32,6 +32,7 @@
 #include "remoting/host/ipc_keyboard_layout_monitor.h"
 #include "remoting/host/ipc_mouse_cursor_monitor.h"
 #include "remoting/host/ipc_screen_controls.h"
+#include "remoting/host/ipc_url_forwarder_configurator.h"
 #include "remoting/host/ipc_video_frame_capturer.h"
 #include "remoting/host/remote_open_url/remote_open_url_util.h"
 #include "remoting/proto/audio.pb.h"
@@ -271,27 +272,20 @@
     mojo::ScopedInterfaceEndpointHandle handle) {
   DCHECK(caller_task_runner_->BelongsToCurrentThread());
 
-  if (interface_name == mojom::ClipboardEventObserver::Name_) {
-    if (clipboard_observer_receiver_.is_bound()) {
+  if (interface_name == mojom::DesktopSessionEventHandler::Name_) {
+    if (desktop_session_event_handler_.is_bound()) {
       LOG(ERROR) << "Receiver already bound for associated interface: "
-                 << mojom::ClipboardEventObserver::Name_;
+                 << mojom::DesktopSessionEventHandler::Name_;
       CrashProcess(base::Location::Current());
     }
 
-    mojo::PendingAssociatedReceiver<mojom::ClipboardEventObserver>
+    mojo::PendingAssociatedReceiver<mojom::DesktopSessionEventHandler>
         pending_receiver(std::move(handle));
-    clipboard_observer_receiver_.Bind(std::move(pending_receiver));
-  } else if (interface_name == mojom::UrlForwarderStateObserver::Name_) {
-    if (url_forwarder_state_observer_receiver_.is_bound()) {
-      LOG(ERROR) << "Receiver already bound for associated interface: "
-                 << mojom::UrlForwarderStateObserver::Name_;
-      CrashProcess(base::Location::Current());
-      return;
-    }
-
-    mojo::PendingAssociatedReceiver<mojom::UrlForwarderStateObserver>
-        pending_receiver(std::move(handle));
-    url_forwarder_state_observer_receiver_.Bind(std::move(pending_receiver));
+    desktop_session_event_handler_.Bind(std::move(pending_receiver));
+  } else {
+    LOG(ERROR) << "Unknown associated interface requested: " << interface_name
+               << ", crashing this process";
+    CrashProcess(base::Location::Current());
   }
 }
 
@@ -316,9 +310,7 @@
   SendToDesktop(new ChromotingNetworkDesktopMsg_StartSessionAgent(
       client_session_control_->client_jid(), screen_resolution_, options_));
 
-  desktop_channel_->GetRemoteAssociatedInterface(&clipboard_handler_remote_);
-  desktop_channel_->GetRemoteAssociatedInterface(
-      &url_forwarder_configurator_remote_);
+  desktop_channel_->GetRemoteAssociatedInterface(&desktop_session_control_);
 
   desktop_session_id_ = session_id;
 
@@ -329,14 +321,13 @@
   DCHECK(caller_task_runner_->BelongsToCurrentThread());
 
   desktop_channel_.reset();
-  clipboard_handler_remote_.reset();
-  clipboard_observer_receiver_.reset();
-  url_forwarder_configurator_remote_.reset();
-  url_forwarder_state_observer_receiver_.reset();
+  desktop_session_control_.reset();
+  desktop_session_event_handler_.reset();
+  desktop_session_id_ = UINT32_MAX;
+
   current_url_forwarder_state_ = mojom::UrlForwarderState::kUnknown;
   // We don't reset |is_url_forwarder_set_up_callback_| here since the request
   // can come in before the DetachFromDesktop-AttachToDesktop sequence.
-  desktop_session_id_ = UINT32_MAX;
 
   shared_buffers_.clear();
 
@@ -413,8 +404,8 @@
     const protocol::ClipboardEvent& event) {
   DCHECK(caller_task_runner_->BelongsToCurrentThread());
 
-  if (clipboard_handler_remote_) {
-    clipboard_handler_remote_->InjectClipboardEvent(event);
+  if (desktop_session_control_) {
+    desktop_session_control_->InjectClipboardEvent(event);
   }
 }
 
@@ -578,14 +569,14 @@
   DCHECK(caller_task_runner_->BelongsToCurrentThread());
   DCHECK(!set_up_url_forwarder_callback_);
 
-  if (!url_forwarder_configurator_remote_.is_connected()) {
+  if (!desktop_session_control_.is_connected()) {
     LOG(ERROR) << "The UrlForwarderConfigurator remote is not connected. Setup "
                << "request ignored.";
     callback.Run(SetUpUrlForwarderResponse::FAILED);
     return;
   }
   set_up_url_forwarder_callback_ = callback;
-  url_forwarder_configurator_remote_->SetUpUrlForwarder();
+  desktop_session_control_->SetUpUrlForwarder();
 }
 
 void DesktopSessionProxy::OnUrlForwarderStateChange(
diff --git a/remoting/host/desktop_session_proxy.h b/remoting/host/desktop_session_proxy.h
index 03ed66d3..849bc6b5 100644
--- a/remoting/host/desktop_session_proxy.h
+++ b/remoting/host/desktop_session_proxy.h
@@ -25,10 +25,8 @@
 #include "remoting/host/audio_capturer.h"
 #include "remoting/host/desktop_environment.h"
 #include "remoting/host/file_transfer/ipc_file_operations.h"
-#include "remoting/host/ipc_url_forwarder_configurator.h"
-#include "remoting/host/mojom/clipboard.mojom.h"
+#include "remoting/host/mojom/desktop_session.mojom.h"
 #include "remoting/host/mojom/remoting_mojom_traits.h"
-#include "remoting/host/mojom/url_forwarder_configurator.mojom.h"
 #include "remoting/host/remote_open_url/url_forwarder_configurator.h"
 #include "remoting/host/screen_resolution.h"
 #include "remoting/proto/control.pb.h"
@@ -85,8 +83,7 @@
                                         DesktopSessionProxyTraits>,
       public IPC::Listener,
       public IpcFileOperations::RequestHandler,
-      public mojom::ClipboardEventObserver,
-      public mojom::UrlForwarderStateObserver {
+      public mojom::DesktopSessionEventHandler {
  public:
   DesktopSessionProxy(
       scoped_refptr<base::SingleThreadTaskRunner> audio_capture_task_runner,
@@ -179,8 +176,9 @@
   void Close(std::uint64_t file_id) override;
   void Cancel(std::uint64_t file_id) override;
 
-  // mojom::ClipboardEventObserver implementation.
+  // mojom::DesktopSessionEventHandler implementation.
   void OnClipboardEvent(const protocol::ClipboardEvent& event) override;
+  void OnUrlForwarderStateChange(mojom::UrlForwarderState state) override;
 
   // API used to implement the UrlForwarderConfigurator interface.
   void IsUrlForwarderSetUp(
@@ -188,9 +186,6 @@
   void SetUpUrlForwarder(
       const UrlForwarderConfigurator::SetUpUrlForwarderCallback& callback);
 
-  // mojom::UrlForwarderStateObserver implementation.
-  void OnUrlForwarderStateChange(mojom::UrlForwarderState state) override;
-
   uint32_t desktop_session_id() const { return desktop_session_id_; }
 
  private:
@@ -294,20 +289,15 @@
   // is called on IpcKeyboardLayoutMonitor.
   absl::optional<protocol::KeyboardLayout> keyboard_layout_;
 
-  // |clipboard_handler_remote_| is only valid when |desktop_channel_| is
+  // |desktop_session_control_| is only valid when |desktop_channel_| is
   // connected. The desktop process can be detached and reattached several times
   // during a session (e.g. transitioning between the login screen and user
   // desktop) so the validity of this remote must be checked before calling a
   // method on it.
-  mojo::AssociatedRemote<mojom::ClipboardEventHandler>
-      clipboard_handler_remote_;
-  mojo::AssociatedReceiver<mojom::ClipboardEventObserver>
-      clipboard_observer_receiver_{this};
+  mojo::AssociatedRemote<mojom::DesktopSessionControl> desktop_session_control_;
+  mojo::AssociatedReceiver<mojom::DesktopSessionEventHandler>
+      desktop_session_event_handler_{this};
 
-  mojo::AssociatedRemote<mojom::UrlForwarderConfigurator>
-      url_forwarder_configurator_remote_;
-  mojo::AssociatedReceiver<mojom::UrlForwarderStateObserver>
-      url_forwarder_state_observer_receiver_{this};
   UrlForwarderConfigurator::IsUrlForwarderSetUpCallback
       is_url_forwarder_set_up_callback_;
   UrlForwarderConfigurator::SetUpUrlForwarderCallback
diff --git a/remoting/host/desktop_session_win.cc b/remoting/host/desktop_session_win.cc
index b99450d..0d6af364 100644
--- a/remoting/host/desktop_session_win.cc
+++ b/remoting/host/desktop_session_win.cc
@@ -719,21 +719,10 @@
 bool DesktopSessionWin::OnMessageReceived(const IPC::Message& message) {
   DCHECK(caller_task_runner_->BelongsToCurrentThread());
 
-  bool handled = true;
-  IPC_BEGIN_MESSAGE_MAP(DesktopSessionWin, message)
-    IPC_MESSAGE_HANDLER(ChromotingDesktopDaemonMsg_DesktopAttached,
-                        OnDesktopSessionAgentAttached)
-    IPC_MESSAGE_HANDLER(ChromotingDesktopDaemonMsg_InjectSas,
-                        InjectSas)
-    IPC_MESSAGE_UNHANDLED(handled = false)
-  IPC_END_MESSAGE_MAP()
+  LOG(ERROR) << "Received unexpected IPC type: " << message.type();
+  CrashDesktopProcess(FROM_HERE);
 
-  if (!handled) {
-    LOG(ERROR) << "Received unexpected IPC type: " << message.type();
-    CrashDesktopProcess(FROM_HERE);
-  }
-
-  return handled;
+  return false;
 }
 
 void DesktopSessionWin::OnPermanentError(int exit_code) {
@@ -744,6 +733,26 @@
 
 void DesktopSessionWin::OnWorkerProcessStopped() {}
 
+void DesktopSessionWin::OnAssociatedInterfaceRequest(
+    const std::string& interface_name,
+    mojo::ScopedInterfaceEndpointHandle handle) {
+  if (interface_name == mojom::DesktopSessionRequestHandler::Name_) {
+    if (desktop_session_request_handler_.is_bound()) {
+      LOG(ERROR) << "Receiver already bound for associated interface: "
+                 << mojom::DesktopSessionRequestHandler::Name_;
+      CrashDesktopProcess(FROM_HERE);
+    }
+
+    mojo::PendingAssociatedReceiver<mojom::DesktopSessionRequestHandler>
+        pending_receiver(std::move(handle));
+    desktop_session_request_handler_.Bind(std::move(pending_receiver));
+  } else {
+    LOG(ERROR) << "Unknown associated interface requested: " << interface_name
+               << ", crashing the desktop process";
+    CrashDesktopProcess(FROM_HERE);
+  }
+}
+
 void DesktopSessionWin::OnSessionAttached(uint32_t session_id) {
   DCHECK(caller_task_runner_->BelongsToCurrentThread());
   DCHECK(!launcher_);
@@ -800,6 +809,7 @@
   DCHECK(caller_task_runner_->BelongsToCurrentThread());
 
   launcher_.reset();
+  desktop_session_request_handler_.reset();
   session_id_ = UINT32_MAX;
 
   if (monitoring_notifications_) {
@@ -811,14 +821,24 @@
   }
 }
 
-void DesktopSessionWin::OnDesktopSessionAgentAttached(
-      const IPC::ChannelHandle& desktop_pipe) {
-  if (!daemon_process()->OnDesktopSessionAgentAttached(id(), session_id_,
-                                                       desktop_pipe)) {
+void DesktopSessionWin::ConnectDesktopChannel(
+    mojo::ScopedMessagePipeHandle desktop_pipe) {
+  DCHECK(caller_task_runner_->BelongsToCurrentThread());
+
+  if (!daemon_process()->OnDesktopSessionAgentAttached(
+          id(), session_id_, desktop_pipe.release())) {
     CrashDesktopProcess(FROM_HERE);
   }
 }
 
+void DesktopSessionWin::InjectSecureAttentionSequence() {
+  InjectSas();
+}
+
+void DesktopSessionWin::CrashNetworkProcess() {
+  daemon_process()->CrashNetworkProcess(FROM_HERE);
+}
+
 void DesktopSessionWin::CrashDesktopProcess(const base::Location& location) {
   DCHECK(caller_task_runner_->BelongsToCurrentThread());
 
diff --git a/remoting/host/desktop_session_win.h b/remoting/host/desktop_session_win.h
index 40592cf..bb667c5 100644
--- a/remoting/host/desktop_session_win.h
+++ b/remoting/host/desktop_session_win.h
@@ -15,7 +15,10 @@
 #include "base/timer/timer.h"
 #include "base/win/scoped_handle.h"
 #include "ipc/ipc_channel_handle.h"
+#include "mojo/public/cpp/bindings/associated_receiver.h"
+#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
 #include "remoting/host/desktop_session.h"
+#include "remoting/host/mojom/desktop_session.mojom.h"
 #include "remoting/host/win/wts_terminal_observer.h"
 #include "remoting/host/worker_process_ipc_delegate.h"
 
@@ -36,10 +39,10 @@
 // (RDP) console. Receives IPC messages from the desktop process, running in
 // the target session, via |WorkerProcessIpcDelegate|, and monitors session
 // attach/detach events via |WtsTerminalObserer|.
-class DesktopSessionWin
-    : public DesktopSession,
-      public WorkerProcessIpcDelegate,
-      public WtsTerminalObserver {
+class DesktopSessionWin : public DesktopSession,
+                          public WorkerProcessIpcDelegate,
+                          public WtsTerminalObserver,
+                          public mojom::DesktopSessionRequestHandler {
  public:
   // Creates a desktop session instance that attaches to the physical console.
   static std::unique_ptr<DesktopSession> CreateForConsole(
@@ -93,14 +96,20 @@
   bool OnMessageReceived(const IPC::Message& message) override;
   void OnPermanentError(int exit_code) override;
   void OnWorkerProcessStopped() override;
+  void OnAssociatedInterfaceRequest(
+      const std::string& interface_name,
+      mojo::ScopedInterfaceEndpointHandle handle) override;
 
   // WtsTerminalObserver implementation.
   void OnSessionAttached(uint32_t session_id) override;
   void OnSessionDetached() override;
 
  private:
-  // ChromotingDesktopDaemonMsg_DesktopAttached handler.
-  void OnDesktopSessionAgentAttached(const IPC::ChannelHandle& desktop_pipe);
+  // mojom::DesktopSessionRequestHandler implementation.
+  void ConnectDesktopChannel(
+      mojo::ScopedMessagePipeHandle desktop_pipe) override;
+  void InjectSecureAttentionSequence() override;
+  void CrashNetworkProcess() override;
 
   // Requests the desktop process to crash.
   void CrashDesktopProcess(const base::Location& location);
@@ -123,15 +132,17 @@
   // Used to unsubscribe from session attach and detach events.
   WtsTerminalMonitor* monitor_;
 
-  // True if |this| is subsribed to receive session attach/detach notifications.
+  // Indicates whether session attach/detach notifications are subscribed to.
   bool monitoring_notifications_;
 
-  // Used to report an error if the session attach notification does not arrives
-  // for too long.
+  // Reports an error if the session attach notification does not arrive.
   base::OneShotTimer session_attach_timer_;
 
   base::Time last_timestamp_;
 
+  mojo::AssociatedReceiver<mojom::DesktopSessionRequestHandler>
+      desktop_session_request_handler_{this};
+
   // The id of the current desktop session being remoted or UINT32_MAX if no
   // session exists.
   int session_id_ = UINT32_MAX;
diff --git a/remoting/host/ipc_desktop_environment_unittest.cc b/remoting/host/ipc_desktop_environment_unittest.cc
index 3a821cf..fd5f2ed 100644
--- a/remoting/host/ipc_desktop_environment_unittest.cc
+++ b/remoting/host/ipc_desktop_environment_unittest.cc
@@ -40,7 +40,7 @@
 #include "remoting/host/fake_keyboard_layout_monitor.h"
 #include "remoting/host/fake_mouse_cursor_monitor.h"
 #include "remoting/host/host_mock_objects.h"
-#include "remoting/proto/url_forwarder_control.pb.h"
+#include "remoting/host/mojom/desktop_session.mojom.h"
 #include "remoting/protocol/fake_desktop_capturer.h"
 #include "remoting/protocol/protocol_mock_objects.h"
 #include "remoting/protocol/test_event_matchers.h"
@@ -115,7 +115,8 @@
 };
 
 // Receives messages sent from the desktop process to the daemon.
-class MockDaemonListener : public IPC::Listener {
+class MockDaemonListener : public IPC::Listener,
+                           public mojom::DesktopSessionRequestHandler {
  public:
   MockDaemonListener() = default;
 
@@ -125,10 +126,24 @@
   ~MockDaemonListener() override = default;
 
   bool OnMessageReceived(const IPC::Message& message) override;
+  void OnAssociatedInterfaceRequest(
+      const std::string& interface_name,
+      mojo::ScopedInterfaceEndpointHandle handle) override;
 
-  MOCK_METHOD1(OnDesktopAttached, void(const IPC::ChannelHandle&));
-  MOCK_METHOD1(OnChannelConnected, void(int32_t));
-  MOCK_METHOD0(OnChannelError, void());
+  MOCK_METHOD(void,
+              ConnectDesktopChannel,
+              (mojo::ScopedMessagePipeHandle handle),
+              (override));
+  MOCK_METHOD(void, InjectSecureAttentionSequence, (), (override));
+  MOCK_METHOD(void, CrashNetworkProcess, (), (override));
+  MOCK_METHOD(void, OnChannelConnected, (int32_t), (override));
+  MOCK_METHOD(void, OnChannelError, (), (override));
+
+  void Disconnect();
+
+ private:
+  mojo::AssociatedReceiver<mojom::DesktopSessionRequestHandler>
+      desktop_session_request_handler_{this};
 };
 
 bool FakeDaemonSender::Send(IPC::Message* message) {
@@ -153,15 +168,21 @@
 }
 
 bool MockDaemonListener::OnMessageReceived(const IPC::Message& message) {
-  bool handled = true;
-  IPC_BEGIN_MESSAGE_MAP(MockDaemonListener, message)
-    IPC_MESSAGE_HANDLER(ChromotingDesktopDaemonMsg_DesktopAttached,
-                        OnDesktopAttached)
-    IPC_MESSAGE_UNHANDLED(handled = false)
-  IPC_END_MESSAGE_MAP()
+  ADD_FAILURE() << "Unexpected call to OnMessageReceived()";
+  return false;
+}
 
-  EXPECT_TRUE(handled);
-  return handled;
+void MockDaemonListener::OnAssociatedInterfaceRequest(
+    const std::string& interface_name,
+    mojo::ScopedInterfaceEndpointHandle handle) {
+  EXPECT_EQ(mojom::DesktopSessionRequestHandler::Name_, interface_name);
+  mojo::PendingAssociatedReceiver<mojom::DesktopSessionRequestHandler>
+      pending_receiver(std::move(handle));
+  desktop_session_request_handler_.Bind(std::move(pending_receiver));
+}
+
+void MockDaemonListener::Disconnect() {
+  desktop_session_request_handler_.reset();
 }
 
 }  // namespace
@@ -217,9 +238,8 @@
 
   void OnDisconnectCallback();
 
-  // Invoked when ChromotingDesktopDaemonMsg_DesktopAttached message is
-  // received.
-  void OnDesktopAttached(const IPC::ChannelHandle& desktop_pipe);
+  // Invoked when ConnectDesktopChannel() is called over IPC.
+  void ConnectDesktopChannel(mojo::ScopedMessagePipeHandle desktop_pipe);
 
   // Runs until there are no references to |task_runner_|. Calls after the main
   // loop has been run are no-op.
@@ -313,10 +333,11 @@
   // once it is ready.
   EXPECT_CALL(desktop_listener_, OnChannelConnected(_))
       .Times(AnyNumber());
-  EXPECT_CALL(desktop_listener_, OnDesktopAttached(_))
+  EXPECT_CALL(desktop_listener_, ConnectDesktopChannel(_))
       .Times(AnyNumber())
-      .WillRepeatedly(Invoke(this,
-                             &IpcDesktopEnvironmentTest::OnDesktopAttached));
+      .WillRepeatedly([&](mojo::ScopedMessagePipeHandle desktop_pipe) {
+        ConnectDesktopChannel(std::move(desktop_pipe));
+      });
   EXPECT_CALL(desktop_listener_, OnChannelError())
       .Times(AnyNumber())
       .WillOnce(Invoke(this,
@@ -497,6 +518,7 @@
     desktop_process_->OnChannelError();
     desktop_process_.reset();
   }
+  desktop_listener_.Disconnect();
   remote_input_injector_ = nullptr;
 }
 
@@ -513,11 +535,11 @@
   DeleteDesktopEnvironment();
 }
 
-void IpcDesktopEnvironmentTest::OnDesktopAttached(
-    const IPC::ChannelHandle& desktop_pipe) {
+void IpcDesktopEnvironmentTest::ConnectDesktopChannel(
+    mojo::ScopedMessagePipeHandle desktop_pipe) {
   // Instruct DesktopSessionProxy to connect to the network-to-desktop pipe.
   desktop_environment_factory_->OnDesktopSessionAgentAttached(
-      terminal_id_, /*session_id=*/0, desktop_pipe);
+      terminal_id_, /*session_id=*/0, desktop_pipe.release());
 }
 
 void IpcDesktopEnvironmentTest::RunMainLoopUntilDone() {
diff --git a/remoting/host/mojom/BUILD.gn b/remoting/host/mojom/BUILD.gn
index af15a538..5eb4f6f 100644
--- a/remoting/host/mojom/BUILD.gn
+++ b/remoting/host/mojom/BUILD.gn
@@ -6,11 +6,10 @@
 
 mojom("mojom") {
   sources = [
-    "clipboard.mojom",
+    "desktop_session.mojom",
     "remote_support.mojom",
     "remote_url_opener.mojom",
     "testing.mojom",
-    "url_forwarder_configurator.mojom",
   ]
 
   deps = [
diff --git a/remoting/host/mojom/clipboard.mojom b/remoting/host/mojom/clipboard.mojom
deleted file mode 100644
index b998763e..0000000
--- a/remoting/host/mojom/clipboard.mojom
+++ /dev/null
@@ -1,35 +0,0 @@
-// 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.
-
-module remoting.mojom;
-
-import "mojo/public/mojom/base/byte_string.mojom";
-
-// Contains clipboard event data.
-// This struct mirrors the remoting::protocol::ClipboardEvents protobuf struct.
-struct ClipboardEvent {
-  // The MIME type of |data|.
-  string mime_type;
-
-  // The clipboard data. The original protobuf type is string but we use a
-  // ByteString because that is the preferred mojom type.
-  mojo_base.mojom.ByteString data;
-};
-
-// Allows injecting clipboard events received from the client.
-// The remote for this interface is owned in the low-privilege network process
-// and the receiver is bound in the high-privilege desktop integration process.
-interface ClipboardEventHandler {
-  // Used to inject clipboard events received from the client.
-  InjectClipboardEvent(ClipboardEvent event);
-};
-
-// Forwards local clipboard events from the host to the client.
-// The remote for this interface is owned in the high-privilege desktop
-// integration process and the receiver is bound in the low-privilege network
-// process.
-interface ClipboardEventObserver {
-  // Used to forward clipboard events from the host to the client.
-  OnClipboardEvent(ClipboardEvent event);
-};
diff --git a/remoting/host/mojom/desktop_session.mojom b/remoting/host/mojom/desktop_session.mojom
new file mode 100644
index 0000000..29c4cd4c
--- /dev/null
+++ b/remoting/host/mojom/desktop_session.mojom
@@ -0,0 +1,91 @@
+// 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.
+
+module remoting.mojom;
+
+import "mojo/public/mojom/base/byte_string.mojom";
+
+// Contains clipboard event data.
+// This struct mirrors the remoting::protocol::ClipboardEvents protobuf struct.
+struct ClipboardEvent {
+  // The MIME type of |data|.
+  string mime_type;
+
+  // The clipboard data. The original protobuf type is string but we use a
+  // ByteString because that is the preferred mojom type.
+  mojo_base.mojom.ByteString data;
+};
+
+// The state of the URL forwarder setup.
+enum UrlForwarderState {
+  kUnknown = 0,
+
+  // The URL forwarder has been set up properly.
+  kSetUp = 1,
+
+  // The URL forwarder has not been set up.
+  kNotSetUp = 2,
+
+  // We have attempted to set up the URL forwarder but it failed.
+  kFailed = 3,
+
+  // The URL forwarder is being set up but it requires user intervention.
+  kSetupPendingUserIntervention = 4,
+};
+
+// Allows the desktop process to request that the daemon process perform an
+// action on its behalf. Though both processes are high-privilege, the daemon
+// process brokers the IPC channel between the desktop and network processes and
+// owns the lifetime of the network process. It also has the ability to execute
+// actions from session 0 (whereas the desktop process runs in a user session)
+// on Windows.
+// The remote for this interface is owned in the high-privilege desktop
+// integration process and the receiver is bound in the high-privilege daemon
+// process.
+interface DesktopSessionRequestHandler {
+  // Ask the daemon process to forward the |desktop_pipe| handle to the network
+  // process in order to establish an IPC connection between the desktop and
+  // network processes.
+  ConnectDesktopChannel(handle<message_pipe> desktop_pipe);
+
+  // Ask the daemon process to inject the secure attention sequence for the
+  // remoted session.
+  InjectSecureAttentionSequence();
+
+  // Ask the daemon process to crash the network process. The desktop process
+  // will request this when it receives invalid IPC requests or messages from
+  // the network process.
+  CrashNetworkProcess();
+};
+
+// Allows the network process to inject input events and control A/V capture in
+// the desktop session.
+// The remote for this interface is owned in the low-privilege network process
+// and the receiver is bound in the high-privilege desktop integration process.
+interface DesktopSessionControl {
+  // Used to inject clipboard events received from the client.
+  InjectClipboardEvent(ClipboardEvent event);
+
+  // Used to set up the URL forwarder as the default browser.  State changes
+  // will be reported via the
+  // DesktopSessionEventHandler::OnUrlForwarderStateChange() method.
+  SetUpUrlForwarder();
+};
+
+// Allows the desktop process to forward events and data to the network process
+// which may process it (e.g. encode a video frame) or forward it to the client
+// (in the case of updated clipboard contents).
+// Forwards local clipboard events from the host to the client.
+// The remote for this interface is owned in the high-privilege desktop
+// integration process and the receiver is bound in the low-privilege network
+// process.
+interface DesktopSessionEventHandler {
+  // Used to forward clipboard events from the host to the client.
+  OnClipboardEvent(ClipboardEvent event);
+
+  // OnUrlForwarderStateChange is immediately called once the desktop agent
+  // starts to provide the initial state, then it will be called to report state
+  // changes caused by calling DesktopSessionControl::SetUpUrlForwarder().
+  OnUrlForwarderStateChange(UrlForwarderState state);
+};
diff --git a/remoting/host/mojom/remoting_mojom_traits.h b/remoting/host/mojom/remoting_mojom_traits.h
index 837c413..d6d41cf 100644
--- a/remoting/host/mojom/remoting_mojom_traits.h
+++ b/remoting/host/mojom/remoting_mojom_traits.h
@@ -11,7 +11,7 @@
 
 #include "mojo/public/cpp/base/byte_string_mojom_traits.h"
 #include "mojo/public/cpp/bindings/struct_traits.h"
-#include "remoting/host/mojom/clipboard.mojom-shared.h"
+#include "remoting/host/mojom/desktop_session.mojom-shared.h"
 #include "remoting/proto/event.pb.h"
 
 namespace mojo {
diff --git a/remoting/host/mojom/url_forwarder_configurator.mojom b/remoting/host/mojom/url_forwarder_configurator.mojom
deleted file mode 100644
index 152cc46..0000000
--- a/remoting/host/mojom/url_forwarder_configurator.mojom
+++ /dev/null
@@ -1,45 +0,0 @@
-// 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.
-
-module remoting.mojom;
-
-// The state of the URL forwarder setup.
-enum UrlForwarderState {
-  kUnknown = 0,
-
-  // The URL forwarder has been set up properly.
-  kSetUp = 1,
-
-  // The URL forwarder has not been set up.
-  kNotSetUp = 2,
-
-  // We have attempted to set up the URL forwarder but it failed.
-  kFailed = 3,
-
-  // The URL forwarder is being set up but it requires user intervention.
-  kSetupPendingUserIntervention = 4,
-};
-
-// Interface to report the state of the URL forwarder setup.
-// NOTE that it does not watch for external changes, e.g. user changing the
-// default browser to the URL forwarder using the Settings app.
-// The remote for this interface is owned in the high-privilege desktop
-// integration process, and the receiver is bound in the low-privilege network
-// process.
-interface UrlForwarderStateObserver {
-  // OnUrlForwarderStateChange is immediately called once the desktop agent
-  // starts to provide the initial state, then it will be called to report state
-  // changes caused by calling UrlForwarderConfigurator::SetUpUrlForwarder().
-  OnUrlForwarderStateChange(UrlForwarderState state);
-};
-
-// Interface to configure the URL forwarder or query the configuration state.
-// The remote for this interface is owned in the low-privilege network process
-// and the receiver is bound in the high-privilege desktop integration process.
-interface UrlForwarderConfigurator {
-  // Requests the desktop process to set up the URL forwarder.
-  // The state changes will be reported via the UrlForwarderStateObserver
-  // interface.
-  SetUpUrlForwarder();
-};
diff --git a/remoting/host/win/unprivileged_process_delegate.cc b/remoting/host/win/unprivileged_process_delegate.cc
index 8ec5eb2..341e6eb 100644
--- a/remoting/host/win/unprivileged_process_delegate.cc
+++ b/remoting/host/win/unprivileged_process_delegate.cc
@@ -376,6 +376,15 @@
   event_handler_->OnChannelError();
 }
 
+void UnprivilegedProcessDelegate::OnAssociatedInterfaceRequest(
+    const std::string& interface_name,
+    mojo::ScopedInterfaceEndpointHandle handle) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  event_handler_->OnAssociatedInterfaceRequest(interface_name,
+                                               std::move(handle));
+}
+
 void UnprivilegedProcessDelegate::ReportFatalError() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
diff --git a/remoting/host/win/unprivileged_process_delegate.h b/remoting/host/win/unprivileged_process_delegate.h
index cb26513a..c39e79e 100644
--- a/remoting/host/win/unprivileged_process_delegate.h
+++ b/remoting/host/win/unprivileged_process_delegate.h
@@ -15,6 +15,7 @@
 #include "base/sequence_checker.h"
 #include "base/win/scoped_handle.h"
 #include "ipc/ipc_listener.h"
+#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
 #include "remoting/host/win/worker_process_launcher.h"
 
 namespace base {
@@ -55,6 +56,9 @@
   bool OnMessageReceived(const IPC::Message& message) override;
   void OnChannelConnected(int32_t peer_pid) override;
   void OnChannelError() override;
+  void OnAssociatedInterfaceRequest(
+      const std::string& interface_name,
+      mojo::ScopedInterfaceEndpointHandle handle) override;
 
   void ReportFatalError();
   void ReportProcessLaunched(base::win::ScopedHandle worker_process);
diff --git a/remoting/host/win/worker_process_launcher.cc b/remoting/host/win/worker_process_launcher.cc
index f83f88a..dc1234ba 100644
--- a/remoting/host/win/worker_process_launcher.cc
+++ b/remoting/host/win/worker_process_launcher.cc
@@ -13,6 +13,7 @@
 #include "base/single_thread_task_runner.h"
 #include "base/time/time.h"
 #include "ipc/ipc_message.h"
+#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
 #include "remoting/host/chromoting_messages.h"
 #include "remoting/host/host_exit_codes.h"
 #include "remoting/host/worker_process_ipc_delegate.h"
@@ -164,6 +165,17 @@
   }
 }
 
+void WorkerProcessLauncher::OnAssociatedInterfaceRequest(
+    const std::string& interface_name,
+    mojo::ScopedInterfaceEndpointHandle handle) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  if (!ipc_enabled_)
+    return;
+
+  ipc_handler_->OnAssociatedInterfaceRequest(interface_name, std::move(handle));
+}
+
 void WorkerProcessLauncher::OnObjectSignaled(HANDLE object) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!process_watcher_.GetWatchedObject());
diff --git a/remoting/host/win/worker_process_launcher.h b/remoting/host/win/worker_process_launcher.h
index 439d332..6bfbd11 100644
--- a/remoting/host/win/worker_process_launcher.h
+++ b/remoting/host/win/worker_process_launcher.h
@@ -24,6 +24,10 @@
 class TimeDelta;
 } // namespace base
 
+namespace mojo {
+class ScopedInterfaceEndpointHandle;
+}
+
 namespace IPC {
 class Message;
 } // namespace IPC
@@ -97,6 +101,8 @@
   bool OnMessageReceived(const IPC::Message& message);
   void OnChannelConnected(int32_t peer_pid);
   void OnChannelError();
+  void OnAssociatedInterfaceRequest(const std::string& interface_name,
+                                    mojo::ScopedInterfaceEndpointHandle handle);
 
  private:
   friend class WorkerProcessLauncherTest;
@@ -135,7 +141,8 @@
   // code is used to determine whether the process has to be restarted.
   DWORD exit_code_;
 
-  // True if IPC messages should be passed to |ipc_handler_|.
+  // Indicates whether the worker process has been launched, after which IPC
+  // messages and events should be passed to the |ipc_handler_| delegate.
   bool ipc_enabled_;
 
   // The timer used to delay termination of the worker process when an IPC error
diff --git a/remoting/host/win/worker_process_launcher_unittest.cc b/remoting/host/win/worker_process_launcher_unittest.cc
index cfe4b2a6..566263e 100644
--- a/remoting/host/win/worker_process_launcher_unittest.cc
+++ b/remoting/host/win/worker_process_launcher_unittest.cc
@@ -21,6 +21,7 @@
 #include "ipc/ipc_channel_proxy.h"
 #include "ipc/ipc_listener.h"
 #include "ipc/ipc_message.h"
+#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
 #include "mojo/public/cpp/system/message_pipe.h"
 #include "remoting/base/auto_thread_task_runner.h"
 #include "remoting/host/chromoting_messages.h"
@@ -52,10 +53,10 @@
   ~MockProcessLauncherDelegate() override {}
 
   // WorkerProcessLauncher::Delegate interface.
-  MOCK_METHOD1(LaunchProcess, void(WorkerProcessLauncher*));
-  MOCK_METHOD1(Send, void(IPC::Message*));
-  MOCK_METHOD0(CloseChannel, void());
-  MOCK_METHOD0(KillProcess, void());
+  MOCK_METHOD(void, LaunchProcess, (WorkerProcessLauncher*), (override));
+  MOCK_METHOD(void, Send, (IPC::Message*), (override));
+  MOCK_METHOD(void, CloseChannel, (), (override));
+  MOCK_METHOD(void, KillProcess, (), (override));
 };
 
 class MockIpcDelegate : public WorkerProcessIpcDelegate {
@@ -68,10 +69,16 @@
   ~MockIpcDelegate() override {}
 
   // WorkerProcessIpcDelegate interface.
-  MOCK_METHOD1(OnChannelConnected, void(int32_t));
-  MOCK_METHOD1(OnMessageReceived, bool(const IPC::Message&));
-  MOCK_METHOD1(OnPermanentError, void(int));
-  MOCK_METHOD0(OnWorkerProcessStopped, void());
+  MOCK_METHOD(void, OnChannelConnected, (int32_t), (override));
+  MOCK_METHOD(bool, OnMessageReceived, (const IPC::Message&), (override));
+  MOCK_METHOD(void, OnPermanentError, (int), (override));
+  MOCK_METHOD(void, OnWorkerProcessStopped, (), (override));
+  MOCK_METHOD(void,
+              OnAssociatedInterfaceRequest,
+              (const std::string& interface_name,
+               mojo::ScopedInterfaceEndpointHandle handle),
+              (override));
+
 };
 
 class MockWorkerListener : public IPC::Listener {
@@ -83,7 +90,7 @@
 
   ~MockWorkerListener() override {}
 
-  MOCK_METHOD3(OnCrash, void(const std::string&, const std::string&, int));
+  MOCK_METHOD(void, OnCrash, (const std::string&, const std::string&, int));
 
   // IPC::Listener implementation
   bool OnMessageReceived(const IPC::Message& message) override;
diff --git a/remoting/host/win/wts_session_process_delegate.cc b/remoting/host/win/wts_session_process_delegate.cc
index 58c6ec5c..2dfac41 100644
--- a/remoting/host/win/wts_session_process_delegate.cc
+++ b/remoting/host/win/wts_session_process_delegate.cc
@@ -27,6 +27,7 @@
 #include "ipc/ipc_channel_proxy.h"
 #include "ipc/ipc_listener.h"
 #include "ipc/ipc_message.h"
+#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
 #include "mojo/public/cpp/platform/named_platform_channel.h"
 #include "mojo/public/cpp/platform/platform_channel.h"
 #include "mojo/public/cpp/platform/platform_channel_server_endpoint.h"
@@ -86,6 +87,9 @@
   bool OnMessageReceived(const IPC::Message& message) override;
   void OnChannelConnected(int32_t peer_pid) override;
   void OnChannelError() override;
+  void OnAssociatedInterfaceRequest(
+      const std::string& interface_name,
+      mojo::ScopedInterfaceEndpointHandle handle) override;
 
   // The actual implementation of LaunchProcess()
   void DoLaunchProcess();
@@ -361,6 +365,15 @@
   event_handler_->OnChannelError();
 }
 
+void WtsSessionProcessDelegate::Core::OnAssociatedInterfaceRequest(
+    const std::string& interface_name,
+    mojo::ScopedInterfaceEndpointHandle handle) {
+  DCHECK(caller_task_runner_->BelongsToCurrentThread());
+
+  event_handler_->OnAssociatedInterfaceRequest(interface_name,
+                                               std::move(handle));
+}
+
 void WtsSessionProcessDelegate::Core::DoLaunchProcess() {
   DCHECK(caller_task_runner_->BelongsToCurrentThread());
   DCHECK(!channel_);
diff --git a/remoting/host/worker_process_ipc_delegate.h b/remoting/host/worker_process_ipc_delegate.h
index fe82504..fe15ffa0 100644
--- a/remoting/host/worker_process_ipc_delegate.h
+++ b/remoting/host/worker_process_ipc_delegate.h
@@ -5,10 +5,16 @@
 #ifndef REMOTING_HOST_WORKER_PROCESS_IPC_DELEGATE_H_
 #define REMOTING_HOST_WORKER_PROCESS_IPC_DELEGATE_H_
 
+#include <string>
+
 #include <stdint.h>
 
 #include "base/compiler_specific.h"
 
+namespace mojo {
+class ScopedInterfaceEndpointHandle;
+}  // namespace mojo
+
 namespace IPC {
 class Message;
 } // namespace IPC
@@ -32,6 +38,11 @@
 
   // Notifies that the worker process stops for any reason.
   virtual void OnWorkerProcessStopped() = 0;
+
+  // Handles associated interface requests sent by the client.
+  virtual void OnAssociatedInterfaceRequest(
+      const std::string& interface_name,
+      mojo::ScopedInterfaceEndpointHandle handle) = 0;
 };
 
 }  // namespace remoting
diff --git a/sandbox/policy/features.cc b/sandbox/policy/features.cc
index 9ce3f75..0154acf 100644
--- a/sandbox/policy/features.cc
+++ b/sandbox/policy/features.cc
@@ -59,27 +59,21 @@
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 #if defined(OS_WIN)
-bool IsNetworkServiceSandboxLPACSupported() {
+bool IsWinNetworkServiceSandboxSupported() {
   // Since some APIs used for LPAC are unsupported below Windows 10, place a
   // check here in a central place.
-  if (base::win::GetVersion() < base::win::Version::WIN10)
+  if (base::win::GetVersion() < base::win::Version::WIN10_RS1)
     return false;
   return true;
 }
 
-bool IsNetworkServiceSandboxLPACEnabled() {
-  // Use LPAC for network sandbox instead of restricted token. Relies on
-  // NetworkServiceSandbox being also enabled.
-  const base::Feature kNetworkServiceSandboxLPAC{
-      "NetworkServiceSandboxLPAC", base::FEATURE_DISABLED_BY_DEFAULT};
-
+bool IsWinNetworkServiceSandboxEnabled() {
   // Check platform support.
-  if (!IsNetworkServiceSandboxLPACSupported())
+  if (!IsWinNetworkServiceSandboxSupported())
     return false;
 
   // Check feature status.
-  return base::FeatureList::IsEnabled(kNetworkServiceSandbox) &&
-         base::FeatureList::IsEnabled(kNetworkServiceSandboxLPAC);
+  return base::FeatureList::IsEnabled(kNetworkServiceSandbox);
 }
 #endif  // defined(OS_WIN)
 
diff --git a/sandbox/policy/features.h b/sandbox/policy/features.h
index 7ecf6c4d..c75361e8 100644
--- a/sandbox/policy/features.h
+++ b/sandbox/policy/features.h
@@ -39,11 +39,12 @@
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 #if defined(OS_WIN)
-// Returns whether the Network Service LPAC Sandbox is supported by the current
-// Windows platform.
-SANDBOX_POLICY_EXPORT bool IsNetworkServiceSandboxLPACSupported();
-// Returns whether Network Service Sandbox is enabled in LPAC mode.
-SANDBOX_POLICY_EXPORT bool IsNetworkServiceSandboxLPACEnabled();
+// Returns whether the Network Service Sandbox is supported by the current
+// Windows platform. Call this function rather than checking the
+// kNetworkServiceSandbox feature directly.
+SANDBOX_POLICY_EXPORT bool IsWinNetworkServiceSandboxSupported();
+// Returns whether Windows Network Service Sandbox is enabled.
+SANDBOX_POLICY_EXPORT bool IsWinNetworkServiceSandboxEnabled();
 #endif
 }  // namespace features
 }  // namespace policy
diff --git a/sandbox/policy/win/sandbox_win.cc b/sandbox/policy/win/sandbox_win.cc
index 8f2e07d..0cd5567 100644
--- a/sandbox/policy/win/sandbox_win.cc
+++ b/sandbox/policy/win/sandbox_win.cc
@@ -660,9 +660,6 @@
       sandbox_type != SandboxType::kNetwork)
     return SBOX_ERROR_UNSUPPORTED;
 
-  DCHECK(sandbox_type != SandboxType::kNetwork ||
-         sandbox::policy::features::IsNetworkServiceSandboxLPACEnabled());
-
   if (sandbox_type == SandboxType::kGpu &&
       !container->AddImpersonationCapability(L"chromeInstallFiles")) {
     DLOG(ERROR) << "AppContainer::AddImpersonationCapability("
@@ -926,8 +923,10 @@
   if (sandbox_type == SandboxType::kGpu)
     return base::FeatureList::IsEnabled(features::kGpuAppContainer);
 
-  if (sandbox_type == SandboxType::kNetwork)
-    return sandbox::policy::features::IsNetworkServiceSandboxLPACEnabled();
+  if (sandbox_type == SandboxType::kNetwork) {
+    DCHECK(sandbox::policy::features::IsWinNetworkServiceSandboxEnabled());
+    return true;
+  }
 
   return false;
 }
diff --git a/services/network/first_party_sets/first_party_sets.cc b/services/network/first_party_sets/first_party_sets.cc
index f7e732e..1650c28d 100644
--- a/services/network/first_party_sets/first_party_sets.cc
+++ b/services/network/first_party_sets/first_party_sets.cc
@@ -13,6 +13,7 @@
 #include "base/logging.h"
 #include "base/ranges/algorithm.h"
 #include "base/strings/string_split.h"
+#include "base/task/post_task.h"
 #include "net/base/schemeful_site.h"
 #include "net/cookies/cookie_constants.h"
 #include "net/cookies/same_party_context.h"
@@ -72,12 +73,16 @@
       flag_value, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY));
 
   ApplyManuallySpecifiedSet();
+  manual_sets_ready_ = true;
+  ClearSiteDataOnChangedSetsIfReady();
 }
 
 base::flat_map<net::SchemefulSite, net::SchemefulSite>*
 FirstPartySets::ParseAndSet(base::StringPiece raw_sets) {
   sets_ = FirstPartySetParser::ParseSetsFromComponentUpdater(raw_sets);
   ApplyManuallySpecifiedSet();
+  component_sets_ready_ = true;
+  ClearSiteDataOnChangedSetsIfReady();
   return &sets_;
 }
 
@@ -218,4 +223,48 @@
   sets_.emplace(manual_owner, manual_owner);
 }
 
+void FirstPartySets::SetPersistedSets(base::StringPiece raw_sets) {
+  raw_persisted_sets_ = std::string(raw_sets);
+  persisted_sets_ready_ = true;
+  ClearSiteDataOnChangedSetsIfReady();
+}
+
+void FirstPartySets::SetOnSiteDataCleared(
+    base::OnceCallback<void(const std::string&)> callback) {
+  on_site_data_cleared_ = std::move(callback);
+  ClearSiteDataOnChangedSetsIfReady();
+}
+
+base::flat_set<net::SchemefulSite> FirstPartySets::ComputeSetsDiff(
+    const base::flat_map<net::SchemefulSite, net::SchemefulSite>& old_sets) {
+  if (old_sets.empty())
+    return {};
+
+  base::flat_set<net::SchemefulSite> result;
+  for (const auto& old_pair : old_sets) {
+    const net::SchemefulSite& old_member = old_pair.first;
+    const net::SchemefulSite& old_owner = old_pair.second;
+    const net::SchemefulSite* current_owner = FindOwner(old_member, false);
+    // Look for the removed sites and the ones have owner changed.
+    if (!current_owner || *current_owner != old_owner) {
+      result.emplace(old_member);
+    }
+  }
+  return result;
+}
+
+void FirstPartySets::ClearSiteDataOnChangedSetsIfReady() {
+  if (!persisted_sets_ready_ || !component_sets_ready_ || !manual_sets_ready_ ||
+      on_site_data_cleared_.is_null())
+    return;
+
+  base::flat_set<net::SchemefulSite> diff = ComputeSetsDiff(
+      FirstPartySetParser::DeserializeFirstPartySets(raw_persisted_sets_));
+
+  // TODO(shuuran@chromium.org): Implement site state clearing.
+
+  std::move(on_site_data_cleared_)
+      .Run(FirstPartySetParser::SerializeFirstPartySets(sets_));
+}
+
 }  // namespace network
diff --git a/services/network/first_party_sets/first_party_sets.h b/services/network/first_party_sets/first_party_sets.h
index 81e0e10..8158b55 100644
--- a/services/network/first_party_sets/first_party_sets.h
+++ b/services/network/first_party_sets/first_party_sets.h
@@ -9,6 +9,7 @@
 #include <memory>
 #include <set>
 
+#include "base/callback.h"
 #include "base/containers/flat_map.h"
 #include "base/containers/flat_set.h"
 #include "net/base/schemeful_site.h"
@@ -87,6 +88,14 @@
   // the members of the set includes the owner.
   base::flat_map<net::SchemefulSite, std::set<net::SchemefulSite>> Sets() const;
 
+  // Sets the `raw_persisted_sets_`, which is a JSON-encoded
+  // string representation of a map of site -> site.
+  void SetPersistedSets(base::StringPiece persisted_sets);
+  // Sets the `on_site_data_cleared_` callback, which takes input of a
+  // JSON-encoded string representation of a map of site -> site.
+  void SetOnSiteDataCleared(
+      base::OnceCallback<void(const std::string&)> callback);
+
  private:
   // Returns a pointer to `site`'s owner (optionally inferring a singleton set
   // if necessary), or `nullptr` if `site` has no owner. Must not return
@@ -101,6 +110,19 @@
   // `manually_specified_set_`.
   void ApplyManuallySpecifiedSet();
 
+  // Compares the map `old_sets` to `sets_` and returns the set of sites that:
+  // 1) were in `old_sets` but are no longer in `sets_`, i.e. leave the FPSs;
+  // or, 2) mapped to a different owner site.
+  base::flat_set<net::SchemefulSite> ComputeSetsDiff(
+      const base::flat_map<net::SchemefulSite, net::SchemefulSite>& old_sets);
+
+  // Checks the required inputs have been received, and if so, computes the diff
+  // between the `sets_` and the parsed `raw_persisted_sets_`, and clears the
+  // site data of the set of sites based on the diff.
+  //
+  // TODO(shuuran@chromium.org): Implement the code to clear site state.
+  void ClearSiteDataOnChangedSetsIfReady();
+
   // Represents the mapping of site -> site, where keys are members of sets, and
   // values are owners of the sets. Owners are explicitly represented as members
   // of the set.
@@ -108,6 +130,22 @@
   absl::optional<
       std::pair<net::SchemefulSite, base::flat_set<net::SchemefulSite>>>
       manually_specified_set_;
+
+  std::string raw_persisted_sets_;
+
+  bool persisted_sets_ready_ = false;
+  bool component_sets_ready_ = false;
+  bool manual_sets_ready_ = false;
+
+  // The callback runs after the site state clearing is completed.
+  base::OnceCallback<void(const std::string&)> on_site_data_cleared_;
+
+  FRIEND_TEST_ALL_PREFIXES(FirstPartySets, ComputeSetsDiff_SitesJoined);
+  FRIEND_TEST_ALL_PREFIXES(FirstPartySets, ComputeSetsDiff_SitesLeft);
+  FRIEND_TEST_ALL_PREFIXES(FirstPartySets, ComputeSetsDiff_OwnerChanged);
+  FRIEND_TEST_ALL_PREFIXES(FirstPartySets, ComputeSetsDiff_OwnerLeft);
+  FRIEND_TEST_ALL_PREFIXES(FirstPartySets, ComputeSetsDiff_OwnerMemberRotate);
+  FRIEND_TEST_ALL_PREFIXES(FirstPartySets, ComputeSetsDiff_EmptySets);
 };
 
 }  // namespace network
diff --git a/services/network/first_party_sets/first_party_sets_unittest.cc b/services/network/first_party_sets/first_party_sets_unittest.cc
index b929315d..2055619 100644
--- a/services/network/first_party_sets/first_party_sets_unittest.cc
+++ b/services/network/first_party_sets/first_party_sets_unittest.cc
@@ -7,6 +7,7 @@
 #include <initializer_list>
 
 #include "base/json/json_reader.h"
+#include "base/test/bind.h"
 #include "net/base/schemeful_site.h"
 #include "net/cookies/cookie_constants.h"
 #include "net/cookies/same_party_context.h"
@@ -204,6 +205,30 @@
   EXPECT_THAT(sets.ParseAndSet("[]"), Pointee(IsEmpty()));
 }
 
+TEST(FirstPartySets, SetsManuallySpecified_Valid_EmptyValue) {
+  FirstPartySets sets;
+  sets.SetManuallySpecifiedSet("");
+
+  // Set non-empty existing sets to distinguish the failure case from the no-op
+  // case when processing the manually-specified sets.
+  const std::string existing_sets = R"(
+  [
+    {
+      "owner": "https://example.test",
+      "members": ["https://member.test"]
+    }
+  ]
+  )";
+  ASSERT_TRUE(base::JSONReader::Read(existing_sets));
+
+  EXPECT_THAT(sets.ParseAndSet(existing_sets),
+              Pointee(UnorderedElementsAre(
+                  Pair(SerializesTo("https://example.test"),
+                       SerializesTo("https://example.test")),
+                  Pair(SerializesTo("https://member.test"),
+                       SerializesTo("https://example.test")))));
+}
+
 TEST(FirstPartySets, SetsManuallySpecified_Valid_SingleMember) {
   FirstPartySets sets;
   sets.SetManuallySpecifiedSet("https://example.test,https://member.test");
@@ -469,6 +494,311 @@
                        SerializesTo("https://example.test")))));
 }
 
+TEST(FirstPartySets, ComputeSetsDiff_SitesJoined) {
+  auto old_sets = base::flat_map<net::SchemefulSite, net::SchemefulSite>{
+      {net::SchemefulSite(GURL("https://example.test")),
+       net::SchemefulSite(GURL("https://example.test"))},
+      {net::SchemefulSite(GURL("https://member1.test")),
+       net::SchemefulSite(GURL("https://example.test"))},
+      {net::SchemefulSite(GURL("https://member3.test")),
+       net::SchemefulSite(GURL("https://example.test"))}};
+
+  // Consistency check the reviewer-friendly JSON format matches the input.
+  ASSERT_THAT(FirstPartySets().ParseAndSet(R"(
+    [
+      {
+        "owner": "https://example.test",
+        "members": ["https://member1.test", "https://member3.test"]
+      }
+    ]
+  )"),
+              Pointee(old_sets));
+
+  FirstPartySets sets;
+  sets.ParseAndSet(R"(
+    [
+      {
+        "owner": "https://example.test",
+        "members": ["https://member1.test", "https://member3.test"]
+      },
+      {
+        "owner": "https://foo.test",
+        "members": ["https://member2.test"]
+      }
+    ]
+  )");
+  // "https://foo.test" and "https://member2.test" joined FPSs. We don't clear
+  // site data upon joining, so the computed diff should be empty set.
+  EXPECT_THAT(sets.ComputeSetsDiff(old_sets), IsEmpty());
+}
+
+TEST(FirstPartySets, ComputeSetsDiff_SitesLeft) {
+  auto old_sets = base::flat_map<net::SchemefulSite, net::SchemefulSite>{
+      {net::SchemefulSite(GURL("https://example.test")),
+       net::SchemefulSite(GURL("https://example.test"))},
+      {net::SchemefulSite(GURL("https://member1.test")),
+       net::SchemefulSite(GURL("https://example.test"))},
+      {net::SchemefulSite(GURL("https://member3.test")),
+       net::SchemefulSite(GURL("https://example.test"))},
+      {net::SchemefulSite(GURL("https://foo.test")),
+       net::SchemefulSite(GURL("https://foo.test"))},
+      {net::SchemefulSite(GURL("https://member2.test")),
+       net::SchemefulSite(GURL("https://foo.test"))}};
+
+  // Consistency check the reviewer-friendly JSON format matches the input.
+  ASSERT_THAT(FirstPartySets().ParseAndSet(R"(
+    [
+      {
+        "owner": "https://example.test",
+        "members": ["https://member1.test", "https://member3.test"]
+      },
+      {
+        "owner": "https://foo.test",
+        "members": ["https://member2.test"]
+      },
+    ]
+  )"),
+              Pointee(old_sets));
+
+  FirstPartySets sets;
+  sets.ParseAndSet(R"(
+    [
+      {
+        "owner": "https://example.test",
+        "members": ["https://member1.test"]
+      },
+    ]
+  )");
+  // Expected diff: "https://foo.test", "https://member2.test" and
+  // "https://member3.test" left FPSs.
+  EXPECT_THAT(sets.ComputeSetsDiff(old_sets),
+              UnorderedElementsAre(SerializesTo("https://foo.test"),
+                                   SerializesTo("https://member2.test"),
+                                   SerializesTo("https://member3.test")));
+}
+
+TEST(FirstPartySets, ComputeSetsDiff_OwnerChanged) {
+  auto old_sets = base::flat_map<net::SchemefulSite, net::SchemefulSite>{
+      {net::SchemefulSite(GURL("https://example.test")),
+       net::SchemefulSite(GURL("https://example.test"))},
+      {net::SchemefulSite(GURL("https://member1.test")),
+       net::SchemefulSite(GURL("https://example.test"))},
+      {net::SchemefulSite(GURL("https://foo.test")),
+       net::SchemefulSite(GURL("https://foo.test"))},
+      {net::SchemefulSite(GURL("https://member2.test")),
+       net::SchemefulSite(GURL("https://foo.test"))},
+      {net::SchemefulSite(GURL("https://member3.test")),
+       net::SchemefulSite(GURL("https://foo.test"))}};
+
+  // Consistency check the reviewer-friendly JSON format matches the input.
+  ASSERT_THAT(FirstPartySets().ParseAndSet(R"(
+    [
+      {
+        "owner": "https://example.test",
+        "members": ["https://member1.test"]
+      },
+      {
+        "owner": "https://foo.test",
+        "members": ["https://member2.test", "https://member3.test"]
+      },
+    ]
+  )"),
+              Pointee(old_sets));
+
+  FirstPartySets sets;
+  sets.ParseAndSet(R"(
+    [
+      {
+        "owner": "https://example.test",
+        "members": ["https://member1.test", "https://member3.test"]
+      },
+      {
+        "owner": "https://foo.test",
+        "members": ["https://member2.test"]
+      }
+    ]
+  )");
+  // Expected diff: "https://member3.test" changed owner.
+  EXPECT_THAT(sets.ComputeSetsDiff(old_sets),
+              UnorderedElementsAre(SerializesTo("https://member3.test")));
+}
+
+TEST(FirstPartySets, ComputeSetsDiff_OwnerLeft) {
+  auto old_sets = base::flat_map<net::SchemefulSite, net::SchemefulSite>{
+      {net::SchemefulSite(GURL("https://example.test")),
+       net::SchemefulSite(GURL("https://example.test"))},
+      {net::SchemefulSite(GURL("https://foo.test")),
+       net::SchemefulSite(GURL("https://example.test"))},
+      {net::SchemefulSite(GURL("https://bar.test")),
+       net::SchemefulSite(GURL("https://example.test"))}};
+
+  // Consistency check the reviewer-friendly JSON format matches the input.
+  ASSERT_THAT(FirstPartySets().ParseAndSet(R"(
+    [
+      {
+        "owner": "https://example.test",
+        "members": ["https://foo.test", "https://bar.test"]
+      }
+    ]
+  )"),
+              Pointee(old_sets));
+
+  FirstPartySets sets;
+  sets.ParseAndSet(R"(
+    [
+      {
+        "owner": "https://foo.test",
+        "members": ["https://bar.test"]
+      }
+    ]
+  )");
+  // Expected diff: "https://example.test" left FPSs, "https://foo.test" and
+  // "https://bar.test" changed owner.
+  // It would be valid to only have example.test in the diff, but our logic
+  // isn't sophisticated enough yet to know that foo.test and bar.test don't
+  // need to be included in the result.
+  EXPECT_THAT(sets.ComputeSetsDiff(old_sets),
+              UnorderedElementsAre(SerializesTo("https://example.test"),
+                                   SerializesTo("https://foo.test"),
+                                   SerializesTo("https://bar.test")));
+}
+
+TEST(FirstPartySets, ComputeSetsDiff_OwnerMemberRotate) {
+  auto old_sets = base::flat_map<net::SchemefulSite, net::SchemefulSite>{
+      {net::SchemefulSite(GURL("https://example.test")),
+       net::SchemefulSite(GURL("https://example.test"))},
+      {net::SchemefulSite(GURL("https://foo.test")),
+       net::SchemefulSite(GURL("https://example.test"))}};
+
+  // Consistency check the reviewer-friendly JSON format matches the input.
+  ASSERT_THAT(FirstPartySets().ParseAndSet(R"(
+    [
+      {
+        "owner": "https://example.test",
+        "members": ["https://foo.test"]
+      }
+    ]
+  )"),
+              Pointee(old_sets));
+
+  FirstPartySets sets;
+  sets.ParseAndSet(R"(
+    [
+      {
+        "owner": "https://foo.test",
+        "members": ["https://example.test"]
+      }
+    ]
+  )");
+  // Expected diff: "https://example.test" and "https://foo.test" changed owner.
+  // It would be valid to not include example.test and foo.test in the result,
+  // but our logic isn't sophisticated enough yet to know that.ß
+  EXPECT_THAT(sets.ComputeSetsDiff(old_sets),
+              UnorderedElementsAre(SerializesTo("https://example.test"),
+                                   SerializesTo("https://foo.test")));
+}
+
+TEST(FirstPartySets, ComputeSetsDiff_EmptySets) {
+  // Empty old_sets.
+  FirstPartySets sets;
+  sets.ParseAndSet(R"(
+    [
+      {
+        "owner": "https://example.test",
+        "members": ["https://member1.test"]
+      },
+    ]
+  )");
+  EXPECT_THAT(sets.ComputeSetsDiff({}), IsEmpty());
+
+  // Empty current sets.
+  auto old_sets = base::flat_map<net::SchemefulSite, net::SchemefulSite>{
+      {net::SchemefulSite(GURL("https://example.test")),
+       net::SchemefulSite(GURL("https://example.test"))},
+      {net::SchemefulSite(GURL("https://member1.test")),
+       net::SchemefulSite(GURL("https://example.test"))}};
+  // Consistency check the reviewer-friendly JSON format matches the input.
+  ASSERT_THAT(FirstPartySets().ParseAndSet(R"(
+    [
+      {
+        "owner": "https://example.test",
+        "members": ["https://member1.test"]
+      }
+    ]
+  )"),
+              Pointee(old_sets));
+  EXPECT_THAT(FirstPartySets().ComputeSetsDiff(old_sets),
+              UnorderedElementsAre(SerializesTo("https://example.test"),
+                                   SerializesTo("https://member1.test")));
+}
+
+TEST(FirstPartySets, ClearSiteDataOnChangedSetsIfReady_NotReady) {
+  int callback_calls = 0;
+  auto callback = base::BindLambdaForTesting(
+      [&](const std::string& got) { callback_calls++; });
+  // component sets not ready.
+  {
+    FirstPartySets sets;
+    callback_calls = 0;
+    sets.SetPersistedSets("{}");
+    sets.SetManuallySpecifiedSet("");
+    sets.SetOnSiteDataCleared(callback);
+    EXPECT_EQ(callback_calls, 0);
+  }
+  // manual sets not ready.
+  {
+    FirstPartySets sets;
+    callback_calls = 0;
+    sets.ParseAndSet("[]");
+    sets.SetPersistedSets("{}");
+    sets.SetOnSiteDataCleared(callback);
+    EXPECT_EQ(callback_calls, 0);
+  }
+  // persisted sets not ready.
+  {
+    FirstPartySets sets;
+    callback_calls = 0;
+    sets.ParseAndSet("[]");
+    sets.SetManuallySpecifiedSet("");
+    sets.SetOnSiteDataCleared(callback);
+    EXPECT_EQ(callback_calls, 0);
+  }
+  // callback not set.
+  {
+    FirstPartySets sets;
+    callback_calls = 0;
+    sets.ParseAndSet("[]");
+    sets.SetManuallySpecifiedSet("");
+    sets.SetPersistedSets("{}");
+    EXPECT_EQ(callback_calls, 0);
+  }
+}
+
+// The callback only runs when `old_sets` is generated and `sets` has merged the
+// inputs from Component Updater and command line flag.
+TEST(FirstPartySets, ClearSiteDataOnChangedSetsIfReady_Ready) {
+  FirstPartySets sets;
+  int callback_calls = 0;
+  sets.ParseAndSet(R"([
+       {
+         "owner": "https://example.test",
+         "members": ["https://member1.test"]
+       }
+     ])");
+  sets.SetManuallySpecifiedSet("https://example2.test,https://member2.test");
+  sets.SetPersistedSets(
+      R"({"https://example.test":"https://example.test",
+            "https://member1.test":"https://example.test"})");
+  sets.SetOnSiteDataCleared(base::BindLambdaForTesting([&](const std::string&
+                                                               got) {
+    EXPECT_EQ(
+        got,
+        R"({"https://member1.test":"https://example.test","https://member2.test":"https://example2.test"})");
+    callback_calls++;
+  }));
+  EXPECT_EQ(callback_calls, 1);
+}
+
 class FirstPartySetsTest : public ::testing::Test {
  public:
   FirstPartySetsTest() {
diff --git a/services/network/network_service.cc b/services/network/network_service.cc
index 5d598ff6..c850d695 100644
--- a/services/network/network_service.cc
+++ b/services/network/network_service.cc
@@ -343,8 +343,7 @@
   }
 
   first_party_sets_ = std::make_unique<FirstPartySets>();
-  if (net::cookie_util::IsFirstPartySetsEnabled() &&
-      command_line->HasSwitch(switches::kUseFirstPartySet)) {
+  if (net::cookie_util::IsFirstPartySetsEnabled()) {
     first_party_sets_->SetManuallySpecifiedSet(
         command_line->GetSwitchValueASCII(switches::kUseFirstPartySet));
   }
@@ -785,6 +784,14 @@
   first_party_sets_->ParseAndSet(raw_sets);
 }
 
+void NetworkService::SetPersistedFirstPartySetsAndGetCurrentSets(
+    const std::string& persisted_sets,
+    mojom::NetworkService::SetPersistedFirstPartySetsAndGetCurrentSetsCallback
+        callback) {
+  first_party_sets_->SetPersistedSets(persisted_sets);
+  first_party_sets_->SetOnSiteDataCleared(std::move(callback));
+}
+
 void NetworkService::SetExplicitlyAllowedPorts(
     const std::vector<uint16_t>& ports) {
   net::SetExplicitlyAllowedPorts(ports);
diff --git a/services/network/network_service.h b/services/network/network_service.h
index e8c984a..a848746 100644
--- a/services/network/network_service.h
+++ b/services/network/network_service.h
@@ -207,6 +207,10 @@
   void BindTestInterface(
       mojo::PendingReceiver<mojom::NetworkServiceTest> receiver) override;
   void SetFirstPartySets(const std::string& raw_sets) override;
+  void SetPersistedFirstPartySetsAndGetCurrentSets(
+      const std::string& persisted_sets,
+      mojom::NetworkService::SetPersistedFirstPartySetsAndGetCurrentSetsCallback
+          callback) override;
   void SetExplicitlyAllowedPorts(const std::vector<uint16_t>& ports) override;
 
   // Returns an HttpAuthHandlerFactory for the given NetworkContext.
diff --git a/services/network/network_service_unittest.cc b/services/network/network_service_unittest.cc
index 5f23863..369509a 100644
--- a/services/network/network_service_unittest.cc
+++ b/services/network/network_service_unittest.cc
@@ -930,6 +930,7 @@
   void SetUp() override {
     test_server_.AddDefaultHandlers(base::FilePath(kServicesTestData));
     ASSERT_TRUE(test_server_.Start());
+    scoped_features_.InitAndEnableFeature(net::features::kFirstPartySets);
     service_ = NetworkService::CreateForTesting();
     service_->Bind(network_service_.BindNewPipeAndPassReceiver());
   }
@@ -993,6 +994,8 @@
   mojo::Remote<mojom::NetworkService> network_service_;
   mojo::Remote<mojom::NetworkContext> network_context_;
   mojo::Remote<mojom::URLLoader> loader_;
+
+  base::test::ScopedFeatureList scoped_features_;
 };
 
 // Verifies that loading a URL through the network service's mojo interface
@@ -1172,6 +1175,18 @@
   run_loop.Run();
 }
 
+TEST_F(NetworkServiceTestWithService,
+       SetPersistedFirstPartySetsAndGetCurrentSets) {
+  base::RunLoop run_loop;
+  network_service_->SetPersistedFirstPartySetsAndGetCurrentSets(
+      "", base::BindLambdaForTesting([&](const std::string& got) {
+        EXPECT_EQ(got, "{}");
+        run_loop.Quit();
+      }));
+  network_service_->SetFirstPartySets("");
+  run_loop.Run();
+}
+
 class TestNetworkChangeManagerClient
     : public mojom::NetworkChangeManagerClient {
  public:
diff --git a/services/network/public/mojom/network_service.mojom b/services/network/public/mojom/network_service.mojom
index fe5450b2..59fbbde6 100644
--- a/services/network/public/mojom/network_service.mojom
+++ b/services/network/public/mojom/network_service.mojom
@@ -373,6 +373,14 @@
   // cleared (except for the manually-specified set, if one exists).
   SetFirstPartySets(string raw_sets);
 
+  // Sets the First-Party Sets data that was persisted to compare it with the
+  // current First-Party Sets data set by `SetFirstPartySets()`, which is
+  // considered more up-to-date, and returns a serialized version of the current
+  // one. Both input and output are in format of the JSON-encoded string
+  // representation of a map of site -> site.
+  SetPersistedFirstPartySetsAndGetCurrentSets(string persisted_sets)
+      => (string up_to_date_sets);
+
   // Sets the list of ports which will be permitted even if they normally would
   // be restricted.
   SetExplicitlyAllowedPorts(array<uint16> ports);
diff --git a/sql/README.md b/sql/README.md
index 49289d2e..92f1487 100644
--- a/sql/README.md
+++ b/sql/README.md
@@ -31,10 +31,41 @@
 [PostgreSQL](https://www.postgresql.org/) and [MySQL](https://www.mysql.com/).
 
 
-### Data types
+### Data storage model {#storage-model}
 
-SQLite stores data using [5 major types](https://www.sqlite.org/datatype3.html),
-which are summarized below.
+The main bottleneck in SQLite database performance is usually disk I/O. So,
+designing schemas that perform well requires understanding how SQLite stores
+data on disk.
+
+At a very high level, a SQLite database is a forest of
+[B-trees](https://en.wikipedia.org/wiki/B-tree), some of which are
+[B+-trees](https://en.wikipedia.org/wiki/B%2B_tree). The database file is an
+array of fixed-size pages, where each page stores a B-tree node. The page size
+can only be set when a database file is created, and impacts both SQL statement
+execution speed, and memory consumption.
+
+The data in each table (usually called *rows*, *records*, or *tuples*) is stored
+in a separate B-tree. The data in each index (called *entries*, *records* or
+*tuples*) is also stored in a separate B-tree. So, each B-tree is associated
+with exactly one table. The [*Indexing* section](#indexing-model) goes into
+further details.
+
+Each B-tree node stores multiple tuples of values. The values and their
+encodings are described in the [*Value types* section](#data-types).
+
+Tying everything together: The performance of a SQL statement is roughly the
+number of database pages touched (read / written) by the statement. These pages
+are nodes belonging to the B-trees associated with the tables mentioned in the
+statement. The number of pages touched when accessing a B-tree depends on the
+B-tree's depth. Each B-tree's depth depends on its record count (number of
+records stored in it), and on its node width (how many records fit in a node).
+
+
+#### Value types {#data-types}
+
+SQLite stores values using
+[5 major types](https://www.sqlite.org/datatype3.html), which are summarized
+below.
 
 1. NULL is a special type for the `NULL` value.
 
@@ -77,7 +108,7 @@
 information ignored by SQLite.
 
 
-### Indexing
+#### Indexing {#indexing-model}
 
 SQLite [uses B-trees](https://www.sqlite.org/fileformat2.html#pages) to store
 both table and index data.
@@ -123,22 +154,97 @@
 B-tree nodes.
 
 
-### Query processing
+### Statement execution model {#query-model}
 
-[At a high level](https://www.sqlite.org/arch.html), SQLite compiles SQL queries
-into bytecode executed by a virtual machine called the VDBE, or
-[the bytecode engine](https://www.sqlite.org/opcode.html). A compiled query can
-be executed multiple times, amortizing the costs of query parsing and planning.
-Chrome's SQLite abstraction layer makes it easy to use compiled queries.
+At [a very high level](https://www.sqlite.org/arch.html), SQLite compiles SQL
+statements (often called *queries*) into bytecode executed by a virtual machine
+called the VDBE, or [the bytecode engine](https://www.sqlite.org/opcode.html).
+A compiled statement can be executed multiple times, amortizing the costs of
+query parsing and planning. Chrome's SQLite abstraction layer makes it easy to
+use compiled queries.
 
-The following SQLite documentation pages cover the query planner and
-optimizer.
+Assuming effective use of cached statements, the performance of a SQL statement
+comes down to the *query plan* that SQLite generates for the statement. The
+query plan is the sequence of B-tree accesses used to execute the statement,
+which determines the number of B-tree pages touched.
+
+The rest of this section summarizes the following SQLite documentation pages.
 
 1. [query planner overview](https://www.sqlite.org/queryplanner.html)
 2. [query optimizer overview](https://www.sqlite.org/optoverview.html)
 3. [`EXPLAIN QUERY PLAN` output description](https://www.sqlite.org/eqp.html)
 
-TODO: Present a simplified model that's sufficient for most database design.
+At a high level, a SQLite query plan is a sequence of **nested** loops, where
+each loop iterates over the data in a B-tree. Each loop can use the current
+record of the outer loops.
+
+TODO: Complete this section. Cover joins, sorting, etc.
+
+#### Getting SQLite's query plans
+
+Ideally, the SQL schemas and statements used by Chrome features would be simple
+enough that the query plans would be obvious to the reader.
+
+When this isn't the case, the fastest way to get the query plan is to load the
+schema in [the SQLite shell](https://sqlite.org/cli.html), and use
+[`EXPLAIN QUERY PLAN`](https://www.sqlite.org/eqp.html).
+
+The following command builds a SQLite shell that uses Chrome's build of SQLite,
+and supports the `EXPLAIN QUERY PLAN` command.
+
+```sh
+autoninja -C out/Default sqlite_dev_shell
+```
+
+Inside the SQLite shell, the `.eqp on` directive automatically shows the results
+of `EXPLAIN QUERY PLAN` for every SQL statement executed in the shell.
+
+
+#### Query steps {#query-step-types}
+
+Query steps are the building blocks of SQLite query plans. Each query step is
+essentially a loop that iterates over the records in a B-tree. These loops
+differ in terms of how many B-tree pages they touch, and how many records they
+produce. This sub-section lists the types of steps implemented by SQLite.
+
+##### Scans
+
+Scans visit an entire (table or index) B-tree. For this reason, scans are almost
+never acceptable in Chrome. Most of our features don't have limits on the amount
+of stored data, so scans can result in an unbounded amount of I/O.
+
+A *table scan* visits the entire table's B-tree.
+
+A *covering index scan* visits an entire index B-tree, but doesn't access the
+associated table B-tree.
+
+SQLite doesn't have any special optimization for `COUNT(*)` queries. In other
+words, SQLite does not track subtree sizes in its B-tree nodes.
+
+Reviewers sometimes emphasize performance issues by calling the scans *full*
+table scans and *full* index scans, where "full" references the fact that the
+number of B-tree pages accessed is proportional to the entire data set stored on
+disk.
+
+TODO: Complete this section. Add examples in a way that doesn't make the section
+overly long.
+
+##### Searches
+
+Searches access a subset of a (table or index) B-tree nodes. Searches limit the
+amount of nodes they need to access based on query restrictions, such as terms
+in the `WHERE` clause. Seeing a `SEARCH` in a query plan is not a guarantee of
+performance. Searches can vary wildly in the amount of B-tree pages they need to
+access.
+
+One of the fastest possible searches is a *table search* that performs exactly
+one B-tree lookup, and produces at most one record.
+
+The other fastest possible search is a *covering index search* that also
+performs one lookup, and produces at most one record.
+
+TODO: Complete this section. Add examples in a way that doesn't make the section
+overly long.
 
 
 ## General advice
diff --git a/testing/buildbot/chrome.json b/testing/buildbot/chrome.json
index 9055fe7..00a58e8f 100644
--- a/testing/buildbot/chrome.json
+++ b/testing/buildbot/chrome.json
@@ -1592,7 +1592,7 @@
       {
         "args": [],
         "cros_board": "atlas",
-        "cros_img": "atlas-release/R96-14233.0.0",
+        "cros_img": "atlas-release/R96-14236.0.0",
         "name": "lacros_all_tast_tests_ATLAS_LKGM",
         "resultdb": {
           "enable": true,
@@ -1652,7 +1652,7 @@
       {
         "args": [],
         "cros_board": "eve",
-        "cros_img": "eve-release/R96-14233.0.0",
+        "cros_img": "eve-release/R96-14236.0.0",
         "name": "lacros_all_tast_tests_EVE_LKGM",
         "resultdb": {
           "enable": true,
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json
index e099e05..03f86e5 100644
--- a/testing/buildbot/chromium.android.fyi.json
+++ b/testing/buildbot/chromium.android.fyi.json
@@ -5693,7 +5693,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M94",
-              "revision": "version:94.0.4606.61"
+              "revision": "version:94.0.4606.63"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -5780,7 +5780,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M95",
-              "revision": "version:95.0.4638.23"
+              "revision": "version:95.0.4638.24"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -5954,7 +5954,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M94",
-              "revision": "version:94.0.4606.61"
+              "revision": "version:94.0.4606.63"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -6041,7 +6041,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M95",
-              "revision": "version:95.0.4638.23"
+              "revision": "version:95.0.4638.24"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index a960872..4b952b5 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -56581,7 +56581,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M94",
-              "revision": "version:94.0.4606.61"
+              "revision": "version:94.0.4606.63"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -56669,7 +56669,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M95",
-              "revision": "version:95.0.4638.23"
+              "revision": "version:95.0.4638.24"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -56845,7 +56845,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M94",
-              "revision": "version:94.0.4606.61"
+              "revision": "version:94.0.4606.63"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -56933,7 +56933,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M95",
-              "revision": "version:95.0.4638.23"
+              "revision": "version:95.0.4638.24"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -57182,7 +57182,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M94",
-              "revision": "version:94.0.4606.61"
+              "revision": "version:94.0.4606.63"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -57269,7 +57269,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M95",
-              "revision": "version:95.0.4638.23"
+              "revision": "version:95.0.4638.24"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -57443,7 +57443,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M94",
-              "revision": "version:94.0.4606.61"
+              "revision": "version:94.0.4606.63"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -57530,7 +57530,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M95",
-              "revision": "version:95.0.4638.23"
+              "revision": "version:95.0.4638.24"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -57779,7 +57779,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M94",
-              "revision": "version:94.0.4606.61"
+              "revision": "version:94.0.4606.63"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -57866,7 +57866,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M95",
-              "revision": "version:95.0.4638.23"
+              "revision": "version:95.0.4638.24"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -58040,7 +58040,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M94",
-              "revision": "version:94.0.4606.61"
+              "revision": "version:94.0.4606.63"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -58127,7 +58127,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M95",
-              "revision": "version:95.0.4638.23"
+              "revision": "version:95.0.4638.24"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json
index 7706fee..a03a1d7 100644
--- a/testing/buildbot/chromium.perf.json
+++ b/testing/buildbot/chromium.perf.json
@@ -224,6 +224,9 @@
         "override_compile_targets": [
           "resource_sizes_chrome_modern_minimal_apks"
         ],
+        "resultdb": {
+          "has_native_resultdb_integration": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -250,6 +253,9 @@
         "override_compile_targets": [
           "resource_sizes_chrome_modern_public_minimal_apks"
         ],
+        "resultdb": {
+          "has_native_resultdb_integration": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -276,6 +282,9 @@
         "override_compile_targets": [
           "resource_sizes_monochrome_minimal_apks"
         ],
+        "resultdb": {
+          "has_native_resultdb_integration": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -302,6 +311,9 @@
         "override_compile_targets": [
           "resource_sizes_monochrome_public_minimal_apks"
         ],
+        "resultdb": {
+          "has_native_resultdb_integration": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -328,6 +340,9 @@
         "override_compile_targets": [
           "resource_sizes_system_webview_bundle"
         ],
+        "resultdb": {
+          "has_native_resultdb_integration": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -354,6 +369,9 @@
         "override_compile_targets": [
           "resource_sizes_system_webview_google_bundle"
         ],
+        "resultdb": {
+          "has_native_resultdb_integration": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -380,6 +398,9 @@
         "override_compile_targets": [
           "resource_sizes_trichrome_google"
         ],
+        "resultdb": {
+          "has_native_resultdb_integration": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -903,6 +924,9 @@
         "override_compile_targets": [
           "resource_sizes_chrome_modern_minimal_apks"
         ],
+        "resultdb": {
+          "has_native_resultdb_integration": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -929,6 +953,9 @@
         "override_compile_targets": [
           "resource_sizes_chrome_modern_public_minimal_apks"
         ],
+        "resultdb": {
+          "has_native_resultdb_integration": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -955,6 +982,9 @@
         "override_compile_targets": [
           "resource_sizes_monochrome_minimal_apks"
         ],
+        "resultdb": {
+          "has_native_resultdb_integration": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -981,6 +1011,9 @@
         "override_compile_targets": [
           "resource_sizes_monochrome_public_minimal_apks"
         ],
+        "resultdb": {
+          "has_native_resultdb_integration": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -1007,6 +1040,9 @@
         "override_compile_targets": [
           "resource_sizes_system_webview_bundle"
         ],
+        "resultdb": {
+          "has_native_resultdb_integration": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -1033,6 +1069,9 @@
         "override_compile_targets": [
           "resource_sizes_system_webview_google_bundle"
         ],
+        "resultdb": {
+          "has_native_resultdb_integration": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -1059,6 +1098,9 @@
         "override_compile_targets": [
           "resource_sizes_trichrome"
         ],
+        "resultdb": {
+          "has_native_resultdb_integration": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -1085,6 +1127,9 @@
         "override_compile_targets": [
           "resource_sizes_trichrome_google"
         ],
+        "resultdb": {
+          "has_native_resultdb_integration": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -1118,6 +1163,9 @@
         "override_compile_targets": [
           "resource_sizes_chromecast"
         ],
+        "resultdb": {
+          "has_native_resultdb_integration": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -1151,6 +1199,9 @@
         "override_compile_targets": [
           "resource_sizes_lacros_chrome"
         ],
+        "resultdb": {
+          "has_native_resultdb_integration": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl
index 44b7a50..7db4f1280 100644
--- a/testing/buildbot/gn_isolate_map.pyl
+++ b/testing/buildbot/gn_isolate_map.pyl
@@ -869,6 +869,7 @@
     "label": "//content/test:fuchsia_telemetry_gpu_integration_test",
     "script": "//testing/scripts/run_gpu_integration_test_as_googletest.py",
     "type": "script",
+    "python3": True,
   },
   "gcm_unit_tests": {
     "label": "//google_apis/gcm:gcm_unit_tests",
@@ -1695,6 +1696,7 @@
     "label": "//chrome/test:telemetry_gpu_integration_test",
     "script": "//testing/scripts/run_gpu_integration_test_as_googletest.py",
     "type": "script",
+    "python3": True,
   },
   "telemetry_gpu_integration_test_android_chrome": {
     "args": [
@@ -1703,6 +1705,7 @@
     "label": "//chrome/test:telemetry_gpu_integration_test_android_chrome",
     "script": "//testing/scripts/run_gpu_integration_test_as_googletest.py",
     "type": "script",
+    "python3": True,
   },
   "telemetry_gpu_integration_test_android_webview": {
     "args": [
@@ -1711,6 +1714,7 @@
     "label": "//chrome/test:telemetry_gpu_integration_test_android_webview",
     "script": "//testing/scripts/run_gpu_integration_test_as_googletest.py",
     "type": "script",
+    "python3": True,
   },
   "telemetry_gpu_integration_test_scripts_only": {
     "label": "//chrome/test:telemetry_gpu_integration_test_scripts_only",
diff --git a/testing/buildbot/internal.chromeos.fyi.json b/testing/buildbot/internal.chromeos.fyi.json
index 596eb76..059f563e 100644
--- a/testing/buildbot/internal.chromeos.fyi.json
+++ b/testing/buildbot/internal.chromeos.fyi.json
@@ -1283,7 +1283,7 @@
       {
         "args": [],
         "cros_board": "atlas",
-        "cros_img": "atlas-release/R96-14233.0.0",
+        "cros_img": "atlas-release/R96-14236.0.0",
         "name": "lacros_fyi_tast_tests_ATLAS_LKGM",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
@@ -1327,7 +1327,7 @@
       {
         "args": [],
         "cros_board": "eve",
-        "cros_img": "eve-release/R96-14233.0.0",
+        "cros_img": "eve-release/R96-14236.0.0",
         "name": "lacros_fyi_tast_tests_EVE_LKGM",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
@@ -1371,7 +1371,7 @@
       {
         "args": [],
         "cros_board": "atlas",
-        "cros_img": "atlas-release/R96-14233.0.0",
+        "cros_img": "atlas-release/R96-14236.0.0",
         "name": "ozone_unittests_ATLAS_LKGM",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1411,7 +1411,7 @@
       {
         "args": [],
         "cros_board": "eve",
-        "cros_img": "eve-release/R96-14233.0.0",
+        "cros_img": "eve-release/R96-14236.0.0",
         "name": "ozone_unittests_EVE_LKGM",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1458,7 +1458,7 @@
       {
         "args": [],
         "cros_board": "kevin",
-        "cros_img": "kevin-release/R96-14233.0.0",
+        "cros_img": "kevin-release/R96-14236.0.0",
         "name": "lacros_all_tast_tests_KEVIN_LKGM",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index cf1321f..58989f4a 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -387,7 +387,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M95',
-          'revision': 'version:95.0.4638.23',
+          'revision': 'version:95.0.4638.24',
         }
       ],
     },
@@ -411,7 +411,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M94',
-          'revision': 'version:94.0.4606.61',
+          'revision': 'version:94.0.4606.63',
         }
       ],
     },
@@ -459,7 +459,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M95',
-          'revision': 'version:95.0.4638.23',
+          'revision': 'version:95.0.4638.24',
         }
       ],
     },
@@ -483,7 +483,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M94',
-          'revision': 'version:94.0.4606.61',
+          'revision': 'version:94.0.4606.63',
         }
       ],
     },
@@ -531,7 +531,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M95',
-          'revision': 'version:95.0.4638.23',
+          'revision': 'version:95.0.4638.24',
         }
       ],
     },
@@ -555,7 +555,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M94',
-          'revision': 'version:94.0.4606.61',
+          'revision': 'version:94.0.4606.63',
         }
       ],
     },
@@ -587,7 +587,7 @@
   'CROS_ATLAS_LKGM': {
     'skylab': {
       'cros_board': 'atlas',
-      'cros_img': 'atlas-release/R96-14233.0.0',
+      'cros_img': 'atlas-release/R96-14236.0.0',
     },
     'identifier': 'ATLAS_LKGM',
   },
@@ -615,7 +615,7 @@
   'CROS_EVE_LKGM': {
     'skylab': {
       'cros_board': 'eve',
-      'cros_img': 'eve-release/R96-14233.0.0',
+      'cros_img': 'eve-release/R96-14236.0.0',
     },
     'identifier': 'EVE_LKGM',
   },
@@ -643,7 +643,7 @@
   'CROS_KEVIN_LKGM': {
     'skylab': {
       'cros_board': 'kevin',
-      'cros_img': 'kevin-release/R96-14233.0.0',
+      'cros_img': 'kevin-release/R96-14236.0.0',
     },
     'identifier': 'KEVIN_LKGM',
   },
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index b202919..6cdf9e7c 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -1088,27 +1088,6 @@
             ]
         }
     ],
-    "AutofillFixFillableFieldTypes": [
-        {
-            "platforms": [
-                "android",
-                "chromeos",
-                "chromeos_lacros",
-                "ios",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "AutofillFixFillableFieldTypes"
-                    ]
-                }
-            ]
-        }
-    ],
     "AutofillIgnoreAutocompleteForImport": [
         {
             "platforms": [
@@ -1173,28 +1152,6 @@
             ]
         }
     ],
-    "AutofillMetadataUploads": [
-        {
-            "platforms": [
-                "android",
-                "android_weblayer",
-                "chromeos",
-                "chromeos_lacros",
-                "ios",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "AutofillMetadataUploads"
-                    ]
-                }
-            ]
-        }
-    ],
     "AutofillNameSectionsWithRendererIds": [
         {
             "platforms": [
@@ -1578,46 +1535,6 @@
             ]
         }
     ],
-    "CBCMRemoteCommandsStudy": [
-        {
-            "platforms": [
-                "chromeos",
-                "chromeos_lacros",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "CBCMPolicyInvalidations",
-                        "CBCMRemoteCommands"
-                    ]
-                }
-            ]
-        }
-    ],
-    "CLSScrollAnchoring": [
-        {
-            "platforms": [
-                "android",
-                "chromeos",
-                "chromeos_lacros",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "CLSScrollAnchoring"
-                    ]
-                }
-            ]
-        }
-    ],
     "CPSS": [
         {
             "platforms": [
@@ -2174,28 +2091,6 @@
             ]
         }
     ],
-    "ClickAsPointerEvent": [
-        {
-            "platforms": [
-                "android",
-                "android_weblayer",
-                "android_webview",
-                "chromeos",
-                "chromeos_lacros",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled_20201116",
-                    "enable_features": [
-                        "ClickPointerEvent"
-                    ]
-                }
-            ]
-        }
-    ],
     "ClientSideDetectionReferrerChain": [
         {
             "platforms": [
@@ -2714,27 +2609,6 @@
             ]
         }
     ],
-    "CrossOriginEmbedderPolicyCredentialless": [
-        {
-            "platforms": [
-                "android",
-                "android_webview",
-                "chromeos",
-                "chromeos_lacros",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "CrossOriginEmbedderPolicyCredentialless"
-                    ]
-                }
-            ]
-        }
-    ],
     "CupsIppPrintingBackend": [
         {
             "platforms": [
@@ -2823,27 +2697,6 @@
             ]
         }
     ],
-    "DeclarativeShadowDOM": [
-        {
-            "platforms": [
-                "android",
-                "android_webview",
-                "chromeos",
-                "chromeos_lacros",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "DeclarativeShadowDOM"
-                    ]
-                }
-            ]
-        }
-    ],
     "DefaultPassthroughCommandDecoder": [
         {
             "platforms": [
@@ -2996,25 +2849,6 @@
             ]
         }
     ],
-    "DesktopTabGroupsCollapseFreezing": [
-        {
-            "platforms": [
-                "chromeos",
-                "chromeos_lacros",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "TabGroupsCollapseFreezing"
-                    ]
-                }
-            ]
-        }
-    ],
     "DesktopTabGroupsUserEducation": [
         {
             "platforms": [
@@ -3174,26 +3008,6 @@
             ]
         }
     ],
-    "DisablePolicyViolatingExtensionsRemotely": [
-        {
-            "platforms": [
-                "chromeos",
-                "chromeos_lacros",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "DisablePolicyViolationExtensionsRemotely",
-                        "DisablePotentiallyUwsExtensionsRemotely"
-                    ]
-                }
-            ]
-        }
-    ],
     "DiscardableMemoryExperiments": [
         {
             "platforms": [
@@ -3345,27 +3159,6 @@
             ]
         }
     ],
-    "DownloadOfflineContentProvider": [
-        {
-            "platforms": [
-                "android",
-                "android_weblayer",
-                "chromeos",
-                "chromeos_lacros",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "UseDownloadOfflineContentProvider"
-                    ]
-                }
-            ]
-        }
-    ],
     "DownloadProgressInfoBar": [
         {
             "platforms": [
@@ -3562,25 +3355,6 @@
             ]
         }
     ],
-    "EnterpriseFileSystemConnectors": [
-        {
-            "platforms": [
-                "chromeos",
-                "chromeos_lacros",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "FileSystemConnectorsEnabled"
-                    ]
-                }
-            ]
-        }
-    ],
     "EnterpriseRealtimeExtensionRequest": [
         {
             "platforms": [
@@ -4688,28 +4462,6 @@
             ]
         }
     ],
-    "InputTargetClientHighPriority": [
-        {
-            "platforms": [
-                "android",
-                "android_webview",
-                "chromeos",
-                "chromeos_lacros",
-                "ios",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "InputTargetClientHighPriority"
-                    ]
-                }
-            ]
-        }
-    ],
     "InstalledAppsInCbd": [
         {
             "platforms": [
@@ -4927,27 +4679,6 @@
             ]
         }
     ],
-    "LayoutShiftNormalization": [
-        {
-            "platforms": [
-                "android",
-                "chromeos",
-                "chromeos_lacros",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "LayoutShiftNormalizationEmitShiftsForKeyMetrics",
-                        "LayoutShiftNormalizationRecordUKM"
-                    ]
-                }
-            ]
-        }
-    ],
     "LiteVideo": [
         {
             "platforms": [
@@ -5037,26 +4768,6 @@
             ]
         }
     ],
-    "MediaCapabilitiesQueryGpuFactories": [
-        {
-            "platforms": [
-                "android",
-                "chromeos",
-                "chromeos_lacros",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "MediaCapabilitiesQueryGpuFactories"
-                    ]
-                }
-            ]
-        }
-    ],
     "MediaFoundationD3D11VideoCapture": [
         {
             "platforms": [
@@ -5108,26 +4819,6 @@
             ]
         }
     ],
-    "MediaSessionWebRTC": [
-        {
-            "platforms": [
-                "android",
-                "chromeos",
-                "chromeos_lacros",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "MediaSessionWebRTC"
-                    ]
-                }
-            ]
-        }
-    ],
     "MeetDevicesMojoServices": [
         {
             "platforms": [
@@ -5426,21 +5117,6 @@
             ]
         }
     ],
-    "NetworkServiceSandbox": [
-        {
-            "platforms": [
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "NetworkServiceSandbox"
-                    ]
-                }
-            ]
-        }
-    ],
     "NtpRealboxAnswersInSuggest": [
         {
             "platforms": [
@@ -5752,28 +5428,6 @@
             ]
         }
     ],
-    "OneCopyRasterBufferPlaybackNormalThreadPriority": [
-        {
-            "platforms": [
-                "android",
-                "android_weblayer",
-                "android_webview",
-                "chromeos",
-                "chromeos_lacros",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "OneCopyRasterBufferPlaybackNormalThreadPriority"
-                    ]
-                }
-            ]
-        }
-    ],
     "OneTimeGeolocationPermission": [
         {
             "platforms": [
@@ -6329,27 +5983,6 @@
             ]
         }
     ],
-    "PaintHoldingCrossOrigin": [
-        {
-            "platforms": [
-                "android",
-                "android_weblayer",
-                "chromeos",
-                "chromeos_lacros",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "PaintHoldingCrossOrigin"
-                    ]
-                }
-            ]
-        }
-    ],
     "PaintPreviewShowOnStartup": [
         {
             "platforms": [
@@ -6470,6 +6103,25 @@
             ]
         }
     ],
+    "PdfUnseasoned": [
+        {
+            "platforms": [
+                "chromeos",
+                "chromeos_lacros",
+                "linux",
+                "mac",
+                "windows"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "PdfUnseasoned"
+                    ]
+                }
+            ]
+        }
+    ],
     "PenetratingImageSelection": [
         {
             "platforms": [
@@ -6666,25 +6318,6 @@
             ]
         }
     ],
-    "PolicyInstalledDesktopWebAppIdentityUpdate": [
-        {
-            "platforms": [
-                "chromeos",
-                "chromeos_lacros",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "WebAppManifestPolicyAppIdentityUpdate"
-                    ]
-                }
-            ]
-        }
-    ],
     "PowerScheduler2": [
         {
             "platforms": [
@@ -7565,27 +7198,6 @@
             ]
         }
     ],
-    "SafeBrowsingCSDRequestWithToken": [
-        {
-            "platforms": [
-                "android",
-                "android_weblayer",
-                "chromeos",
-                "chromeos_lacros",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "SafeBrowsingCSDRequestWithToken"
-                    ]
-                }
-            ]
-        }
-    ],
     "SafeBrowsingCTDownloadWarning": [
         {
             "platforms": [
@@ -7707,24 +7319,6 @@
             ]
         }
     ],
-    "SafeBrowsingPerProfileNetworkContexts": [
-        {
-            "platforms": [
-                "windows",
-                "linux",
-                "mac"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "SafeBrowsingRemoveCookies",
-                        "SafeBrowsingSeparateNetworkContexts"
-                    ]
-                }
-            ]
-        }
-    ],
     "SafeBrowsingVisualFeaturesSizes": [
         {
             "platforms": [
@@ -7839,25 +7433,6 @@
             ]
         }
     ],
-    "SettingsLandingPageRedesign": [
-        {
-            "platforms": [
-                "chromeos",
-                "chromeos_lacros",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "SettingsLandingPageRedesign"
-                    ]
-                }
-            ]
-        }
-    ],
     "SettingsRefresh": [
         {
             "platforms": [
@@ -8152,28 +7727,6 @@
             ]
         }
     ],
-    "StorageServiceOutOfProcess": [
-        {
-            "platforms": [
-                "chromeos",
-                "chromeos_lacros",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Unsandboxed_BeforeSandboxAvailable",
-                    "enable_features": [
-                        "StorageServiceOutOfProcess"
-                    ],
-                    "disable_features": [
-                        "StorageServiceSandbox"
-                    ]
-                }
-            ]
-        }
-    ],
     "SubframeShutdownDelay": [
         {
             "platforms": [
@@ -8457,47 +8010,6 @@
             ]
         }
     ],
-    "TextFragmentAnchor": [
-        {
-            "platforms": [
-                "android",
-                "android_weblayer",
-                "android_webview",
-                "chromeos",
-                "chromeos_lacros",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled_20191216",
-                    "enable_features": [
-                        "TextFragmentAnchor"
-                    ]
-                }
-            ]
-        }
-    ],
-    "TextFragmentColorChangeBlink": [
-        {
-            "platforms": [
-                "android",
-                "chromeos",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "TextFragmentColorChange"
-                    ]
-                }
-            ]
-        }
-    ],
     "ToolbarMicIphAndroid": [
         {
             "platforms": [
@@ -8554,28 +8066,6 @@
             ]
         }
     ],
-    "TransformInterop": [
-        {
-            "platforms": [
-                "android",
-                "android_weblayer",
-                "android_webview",
-                "chromeos",
-                "chromeos_lacros",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "TransformInterop"
-                    ]
-                }
-            ]
-        }
-    ],
     "TranslateRankerModel": [
         {
             "platforms": [
@@ -8714,6 +8204,32 @@
             ]
         }
     ],
+    "UMA-NonUniformity-Trial-1-Percent": [
+        {
+            "platforms": [
+                "android",
+                "android_weblayer",
+                "android_webview",
+                "ios",
+                "chromeos",
+                "chromeos_lacros",
+                "linux",
+                "mac",
+                "windows"
+            ],
+            "experiments": [
+                {
+                    "name": "group_01",
+                    "params": {
+                        "delta": "0.01"
+                    },
+                    "enable_features": [
+                        "NonUniformityValidation"
+                    ]
+                }
+            ]
+        }
+    ],
     "UnidoPreferSync": [
         {
             "platforms": [
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc
index d0cff4b..6c3eff4 100644
--- a/third_party/blink/common/features.cc
+++ b/third_party/blink/common/features.cc
@@ -977,7 +977,7 @@
 // Uses page viewport instead of frame viewport in the Largest Contentful Paint
 // heuristic where images occupying the full viewport are ignored.
 const base::Feature kUsePageViewportInLCP{"UsePageViewportInLCP",
-                                          base::FEATURE_DISABLED_BY_DEFAULT};
+                                          base::FEATURE_ENABLED_BY_DEFAULT};
 
 // Enable `Sec-CH-UA-Platform` client hint and request header to be sent by
 // default
diff --git a/third_party/blink/common/mobile_metrics/mobile_friendliness_mojom_traits.h b/third_party/blink/common/mobile_metrics/mobile_friendliness_mojom_traits.h
index 67f6633..e5a32df 100644
--- a/third_party/blink/common/mobile_metrics/mobile_friendliness_mojom_traits.h
+++ b/third_party/blink/common/mobile_metrics/mobile_friendliness_mojom_traits.h
@@ -14,8 +14,7 @@
 class StructTraits<blink::mojom::MobileFriendlinessDataView,
                    blink::MobileFriendliness> {
  public:
-  static blink::mojom::ViewportStatus viewport_device_width(
-      const blink::MobileFriendliness& mf) {
+  static bool viewport_device_width(const blink::MobileFriendliness& mf) {
     return mf.viewport_device_width;
   }
   static double viewport_initial_scale_x10(
@@ -25,8 +24,7 @@
   static int viewport_hardcoded_width(const blink::MobileFriendliness& mf) {
     return mf.viewport_hardcoded_width;
   }
-  static blink::mojom::ViewportStatus allow_user_zoom(
-      const blink::MobileFriendliness& mf) {
+  static bool allow_user_zoom(const blink::MobileFriendliness& mf) {
     return mf.allow_user_zoom;
   }
   static int small_text_ratio(const blink::MobileFriendliness& mf) {
diff --git a/third_party/blink/public/common/mobile_metrics/mobile_friendliness.h b/third_party/blink/public/common/mobile_metrics/mobile_friendliness.h
index cb62777..3f174bb 100644
--- a/third_party/blink/public/common/mobile_metrics/mobile_friendliness.h
+++ b/third_party/blink/public/common/mobile_metrics/mobile_friendliness.h
@@ -24,7 +24,7 @@
 
   // Whether <meta name="viewport" content="width=device-width"> is specified or
   // not.
-  mojom::ViewportStatus viewport_device_width = mojom::ViewportStatus::kUnknown;
+  bool viewport_device_width = false;
 
   // The value specified in meta tag like <meta name="viewport"
   // content="initial-scale=1.0">.
@@ -38,7 +38,7 @@
 
   // Whether the page allows user to zoom in/out.
   // It is specified like <meta name="viewport" content="user-scalable=no">.
-  mojom::ViewportStatus allow_user_zoom = mojom::ViewportStatus::kUnknown;
+  bool allow_user_zoom = true;
 
   // Percentage of small font size text area in all text area.
   // Default -1 means "Unknown" and should not be sent as UKM.
diff --git a/third_party/blink/public/mojom/mobile_metrics/mobile_friendliness.mojom b/third_party/blink/public/mojom/mobile_metrics/mobile_friendliness.mojom
index b808d176..dc74b4b 100644
--- a/third_party/blink/public/mojom/mobile_metrics/mobile_friendliness.mojom
+++ b/third_party/blink/public/mojom/mobile_metrics/mobile_friendliness.mojom
@@ -4,20 +4,14 @@
 
 module blink.mojom;
 
-enum ViewportStatus {
-  kUnknown,
-  kYes,
-  kNo,
-};
-
 // Metrics about mobile friendliness for UpdateTiming call. The various values
 // are calculated at different times by different signals, so the values may be
 // invalid (e.g. unknown or -1) if they have not yet been determined.
 struct MobileFriendliness {
   // Whether <meta name="viewport" content="width=device-width"> is specified or
   // not.
-  // Default value is kUnknown.
-  ViewportStatus viewport_device_width;
+  // Default value is false.
+  bool viewport_device_width;
 
   // The value specified in viewport initial-scale in meta tag multiplied by 10.
   // Default value is -1 as an invalid data.
@@ -28,8 +22,8 @@
   int32 viewport_hardcoded_width;
 
   // Whether the page allows user to zoom in/out.
-  // Default value is kUnknown.
-  ViewportStatus allow_user_zoom;
+  // Default value is true.
+  bool allow_user_zoom;
 
   // Percentage of small font text area in total text area.
   // Default value is -1 as an invalid data.
diff --git a/third_party/blink/renderer/core/html/forms/html_select_menu_element.cc b/third_party/blink/renderer/core/html/forms/html_select_menu_element.cc
index f412927f..6470268 100644
--- a/third_party/blink/renderer/core/html/forms/html_select_menu_element.cc
+++ b/third_party/blink/renderer/core/html/forms/html_select_menu_element.cc
@@ -41,6 +41,9 @@
   template <typename StringType>
   void PartRemoved(const StringType& part_name, Element* element);
 
+  template <typename StringType>
+  void SlotChanged(const StringType& slot_name);
+
   Member<HTMLSelectMenuElement> select_;
   Member<MutationObserver> observer_;
 };
@@ -52,7 +55,7 @@
   init->setAttributeOldValue(true);
   init->setAttributes(true);
   // TODO(crbug.com/1121840) There are more attributes that affect <selectmenu>.
-  init->setAttributeFilter({"part"});
+  init->setAttributeFilter({"part", "slot"});
   init->setChildList(true);
   init->setSubtree(true);
   observer_->observe(select_, init, ASSERT_NO_EXCEPTION);
@@ -83,6 +86,12 @@
           PartRemoved(record->oldValue(), target);
           PartInserted(target->getAttribute(html_names::kPartAttr), target);
         }
+      } else if (record->attributeName() == html_names::kSlotAttr) {
+        auto* target = DynamicTo<Element>(record->target());
+        if (target && record->oldValue() != target->SlotName()) {
+          SlotChanged(record->oldValue());
+          SlotChanged(target->SlotName());
+        }
       }
     } else if (record->type() == "childList") {
       for (unsigned i = 0; i < record->addedNodes()->length(); ++i) {
@@ -93,6 +102,7 @@
 
         const AtomicString& part = element->getAttribute(html_names::kPartAttr);
         PartInserted(part, element);
+        SlotChanged(element->SlotName());
       }
 
       for (unsigned i = 0; i < record->removedNodes()->length(); ++i) {
@@ -103,6 +113,7 @@
 
         const AtomicString& part = element->getAttribute(html_names::kPartAttr);
         PartRemoved(part, element);
+        SlotChanged(element->SlotName());
       }
     }
   }
@@ -138,6 +149,17 @@
   }
 }
 
+template <typename StringType>
+void HTMLSelectMenuElement::SelectMutationCallback::SlotChanged(
+    const StringType& slot_name) {
+  if (slot_name == kListboxPartName) {
+    select_->UpdateListboxPart();
+  } else if (slot_name == kButtonPartName) {
+    select_->UpdateButtonPart();
+    select_->UpdateSelectedValuePart();
+  }
+}
+
 HTMLSelectMenuElement::HTMLSelectMenuElement(Document& document)
     : HTMLElement(html_names::kSelectmenuTag, document) {
   DCHECK(RuntimeEnabledFeatures::HTMLSelectMenuElementEnabled());
diff --git a/third_party/blink/renderer/core/html/forms/text_control_element.cc b/third_party/blink/renderer/core/html/forms/text_control_element.cc
index 4996197..37288c6 100644
--- a/third_party/blink/renderer/core/html/forms/text_control_element.cc
+++ b/third_party/blink/renderer/core/html/forms/text_control_element.cc
@@ -807,6 +807,13 @@
       if (auto* frame = GetDocument().GetFrame())
         frame->GetSpellChecker().RemoveSpellingAndGrammarMarkers(*inner_editor);
     }
+  } else if (params.name == html_names::kSpellcheckAttr) {
+    if (HTMLElement* inner_editor = InnerEditorElement()) {
+      if (auto* frame = GetDocument().GetFrame()) {
+        frame->GetSpellChecker().RespondToChangedEnablement(
+            *inner_editor, IsSpellCheckingEnabled());
+      }
+    }
   } else {
     HTMLFormControlElementWithState::ParseAttribute(params);
   }
diff --git a/third_party/blink/renderer/core/html/media/html_video_element.cc b/third_party/blink/renderer/core/html/media/html_video_element.cc
index 3b5dd16..333991bf 100644
--- a/third_party/blink/renderer/core/html/media/html_video_element.cc
+++ b/third_party/blink/renderer/core/html/media/html_video_element.cc
@@ -739,7 +739,7 @@
   lazy_load_intersection_observer_ = nullptr;
 
   auto notify_visible = [](HTMLVideoElement* self) {
-    if (self->web_media_player_)
+    if (self && self->web_media_player_)
       self->web_media_player_->OnBecameVisible();
   };
 
diff --git a/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.cc b/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.cc
index f9a92a7..7ce303c 100644
--- a/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.cc
+++ b/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.cc
@@ -4,6 +4,7 @@
 
 #include "third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.h"
 
+#include "third_party/blink/public/common/mobile_metrics/mobile_friendliness.h"
 #include "third_party/blink/public/mojom/mobile_metrics/mobile_friendliness.mojom-blink.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -26,7 +27,6 @@
 
 namespace blink {
 
-using mojom::blink::ViewportStatus;
 static constexpr int kSmallFontThreshold = 9;
 static constexpr int kTimeBudgetExceeded = -2;
 
@@ -150,7 +150,7 @@
 // x_positions: Collects and inserts every x dimension positions.
 // vertices: Inserts y dimension keyed vertex positions with its attribute.
 // Returns total count of tap targets.
-// Returns -1 if time limit exceeded.
+// Returns kTimeBudgetExceeded if time limit exceeded.
 int ExtractAndCountAllTapTargets(
     LayoutObject* const root,
     int finger_radius,
@@ -163,7 +163,7 @@
   int tap_targets = 0;
   for (LayoutObject* object = root; object;) {
     if (IsTimeBudgetExpired(started))
-      return -1;
+      return kTimeBudgetExceeded;
 
     Node* node = object->GetNode();
     const ComputedStyle* style = object->Style();
@@ -245,7 +245,7 @@
 // Precondition: |vertex| must be sorted by its |first|.
 // rightmost_position: Rightmost x position in all vertices.
 // Returns bad tap targets count.
-// Returns -1 if time limit exceeded.
+// Returns kTimeBudgetExceeded if time limit exceeded.
 int CountBadTapTargets(wtf_size_t rightmost_position,
                        const Vector<std::pair<int, EdgeOrCenter>>& vertices,
                        const base::Time& started) {
@@ -275,7 +275,7 @@
       }
     }
     if (IsTimeBudgetExpired(started))
-      return -1;
+      return kTimeBudgetExceeded;
   }
   return bad_tap_targets;
 }
@@ -285,7 +285,7 @@
 // Counts and calculate ration of bad tap targets. The process is a surface scan
 // with region tracking by Fenwick tree. The detail of the algorithm is
 // go/bad-tap-target-ukm
-void MobileFriendlinessChecker::ComputeBadTapTargetsRatio() {
+int MobileFriendlinessChecker::ComputeBadTapTargetsRatio() {
   base::Time started = base::Time::Now();
   constexpr float kOneDipInMm = 0.15875;
   const float scale_factor = frame_view_->GetChromeClient()
@@ -308,10 +308,8 @@
   const int all_tap_targets = ExtractAndCountAllTapTargets(
       frame_view_->GetFrame().GetDocument()->GetLayoutView(), finger_radius,
       scroll_y, screen_height, x_positions, started, vertices);
-  if (all_tap_targets == -1) {
-    mobile_friendliness_.bad_tap_targets_ratio = kTimeBudgetExceeded;
-    return;
-  }
+  if (all_tap_targets <= 0)
+    return all_tap_targets;  // Means there is no tap target or timeout.
 
   // Compress x dimension of all vertices to save memory.
   // This will reduce rightmost position of vertices without sacrificing
@@ -333,27 +331,24 @@
   // Sweep x-compressed y-ordered vertices to detect bad tap targets.
   const int bad_tap_targets =
       CountBadTapTargets(x_positions.size(), vertices, started);
-  if (bad_tap_targets == -1) {
-    mobile_friendliness_.bad_tap_targets_ratio = kTimeBudgetExceeded;
-    return;
-  }
+  if (bad_tap_targets == kTimeBudgetExceeded)
+    return kTimeBudgetExceeded;
 
-  if (all_tap_targets > 0) {
-    mobile_friendliness_.bad_tap_targets_ratio =
-        bad_tap_targets * 100.0 / all_tap_targets;
-  } else {
-    mobile_friendliness_.bad_tap_targets_ratio = 0;
-  }
+  return bad_tap_targets * 100.0 / all_tap_targets;
 }
 
 void MobileFriendlinessChecker::EvaluateNow() {
+  // This checker has nothing to do.
+  if (!tap_target_check_enabled_ && !font_size_check_enabled_)
+    return;
+
   // If detached, there's no need to calculate any metrics.
   // Or if this is before FCP, there's nothing to evaluate.
   if (!frame_view_->GetChromeClient() || !fcp_detected_)
     return;
 
   if (tap_target_check_enabled_)
-    ComputeBadTapTargetsRatio();
+    mobile_friendliness_.bad_tap_targets_ratio = ComputeBadTapTargetsRatio();
 
   if (font_size_check_enabled_)
     mobile_friendliness_.small_text_ratio = text_area_sizes_.SmallTextRatio();
@@ -366,49 +361,37 @@
 
 void MobileFriendlinessChecker::NotifyViewportUpdated(
     const ViewportDescription& viewport) {
+  if (viewport.type != ViewportDescription::Type::kViewportMeta)
+    return;
+
   const double zoom = viewport.zoom_is_explicit ? viewport.zoom : 1.0;
+  mobile_friendliness_.viewport_device_width =
+      viewport.max_width.IsDeviceWidth();
+  if (viewport.max_width.IsFixed()) {
+    mobile_friendliness_.viewport_hardcoded_width =
+        viewport.max_width.GetFloatValue();
+    // Convert value from Blink space to device-independent pixels.
+    if (viewport_scalar_ != 0)
+      mobile_friendliness_.viewport_hardcoded_width /= viewport_scalar_;
+  }
 
-  switch (viewport.type) {
-    case ViewportDescription::Type::kUserAgentStyleSheet:
-      if (mobile_friendliness_.viewport_device_width ==
-          ViewportStatus::kUnknown)
-        mobile_friendliness_.viewport_device_width = ViewportStatus::kNo;
+  if (viewport.zoom_is_explicit) {
+    mobile_friendliness_.viewport_initial_scale_x10 =
+        std::round(viewport.zoom * 10);
+  }
 
-      if (mobile_friendliness_.allow_user_zoom == ViewportStatus::kUnknown)
-        mobile_friendliness_.allow_user_zoom = ViewportStatus::kYes;
-      break;
-    case ViewportDescription::Type::kViewportMeta:
-      mobile_friendliness_.viewport_device_width =
-          viewport.max_width.IsDeviceWidth() ? ViewportStatus::kYes
-                                             : ViewportStatus::kNo;
-      if (viewport.max_width.IsFixed()) {
-        mobile_friendliness_.viewport_hardcoded_width =
-            viewport.max_width.GetFloatValue();
-        // Convert value from Blink space to device-independent pixels.
-        if (viewport_scalar_ != 0)
-          mobile_friendliness_.viewport_hardcoded_width /= viewport_scalar_;
-      }
-      if (viewport.zoom_is_explicit) {
-        mobile_friendliness_.viewport_initial_scale_x10 =
-            std::round(viewport.zoom * 10);
-      }
-      if (viewport.user_zoom_is_explicit) {
-        mobile_friendliness_.allow_user_zoom =
-            viewport.user_zoom ? ViewportStatus::kYes : ViewportStatus::kNo;
-      }
-      if (viewport.max_zoom_is_explicit &&
-          viewport.max_zoom / zoom < kMaximumScalePreventsZoomingThreshold) {
-        mobile_friendliness_.allow_user_zoom = ViewportStatus::kNo;
-      }
-      break;
-    default:
-      return;
+  if (viewport.user_zoom_is_explicit) {
+    mobile_friendliness_.allow_user_zoom = viewport.user_zoom;
+    // If zooming is only allowed slightly.
+    if (viewport.max_zoom / zoom < kMaximumScalePreventsZoomingThreshold)
+      mobile_friendliness_.allow_user_zoom = false;
   }
 }
 
 int MobileFriendlinessChecker::TextAreaWithFontSize::SmallTextRatio() const {
   if (total_text_area == 0)
     return 0;
+
   return small_font_area * 100 / total_text_area;
 }
 
diff --git a/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.h b/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.h
index 5b4e6ae4..c6c54b9 100644
--- a/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.h
+++ b/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.h
@@ -44,13 +44,20 @@
 
  private:
   void ComputeSmallTextRatio(const LayoutObject& object);
+
+  // Returns the percentage of the width of the content that overflows the
+  // viewport.
+  // Returns 0 if all content fits in the viewport.
   int ComputeContentOutsideViewport();
-  void ComputeBadTapTargetsRatio();
+
+  // Returns percentage value [0-100] of bad tap targets in the area of the
+  // first page. Returns kTimeBudgetExceeded if the time limit is exceeded.
+  int ComputeBadTapTargetsRatio();
 
  private:
   TextAreaWithFontSize text_area_sizes_;
   Member<LocalFrameView> frame_view_;
-  blink::MobileFriendliness mobile_friendliness_;
+  MobileFriendliness mobile_friendliness_;
   bool font_size_check_enabled_;
   bool tap_target_check_enabled_;
   float viewport_scalar_;
diff --git a/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker_test.cc b/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker_test.cc
index cdadd47b..e19969be 100644
--- a/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker_test.cc
+++ b/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker_test.cc
@@ -18,9 +18,9 @@
 namespace blink {
 
 using mobile_metrics_test_helpers::MobileFriendlinessTree;
-using mojom::ViewportStatus;
 
 static constexpr char kBaseUrl[] = "http://www.test.com/";
+
 class MobileFriendlinessCheckerTest : public testing::Test {
  public:
   ~MobileFriendlinessCheckerTest() override {
@@ -108,23 +108,23 @@
 TEST_F(MobileFriendlinessCheckerTest, NoViewportSetting) {
   MobileFriendliness actual_mf =
       CalculateMainFrameMetricsForHTMLString("<body>bar</body>");
-  EXPECT_EQ(actual_mf.viewport_device_width, mojom::ViewportStatus::kNo);
-  EXPECT_EQ(actual_mf.allow_user_zoom, mojom::ViewportStatus::kYes);
+  EXPECT_EQ(actual_mf.viewport_device_width, false);
+  EXPECT_EQ(actual_mf.allow_user_zoom, true);
   EXPECT_EQ(actual_mf.small_text_ratio, 100);
 }
 
 TEST_F(MobileFriendlinessCheckerTest, DeviceWidth) {
   MobileFriendliness actual_mf =
       CalculateMainFrameMetricsForFile("viewport/viewport-1.html");
-  EXPECT_EQ(actual_mf.viewport_device_width, mojom::ViewportStatus::kYes);
-  EXPECT_EQ(actual_mf.allow_user_zoom, mojom::ViewportStatus::kYes);
+  EXPECT_EQ(actual_mf.viewport_device_width, true);
+  EXPECT_EQ(actual_mf.allow_user_zoom, true);
 }
 
 TEST_F(MobileFriendlinessCheckerTest, HardcodedViewport) {
   MobileFriendliness actual_mf =
       CalculateMainFrameMetricsForFile("viewport/viewport-30.html");
-  EXPECT_EQ(actual_mf.viewport_device_width, blink::mojom::ViewportStatus::kNo);
-  EXPECT_EQ(actual_mf.allow_user_zoom, mojom::ViewportStatus::kYes);
+  EXPECT_EQ(actual_mf.viewport_device_width, false);
+  EXPECT_EQ(actual_mf.allow_user_zoom, true);
   EXPECT_EQ(actual_mf.viewport_hardcoded_width, 200);
 }
 
@@ -133,8 +133,8 @@
   MobileFriendliness actual_mf =
       CalculateMainFrameMetricsForFile("viewport/viewport-30.html",
                                        /*device_scale=*/3.0);
-  EXPECT_EQ(actual_mf.viewport_device_width, blink::mojom::ViewportStatus::kNo);
-  EXPECT_EQ(actual_mf.allow_user_zoom, mojom::ViewportStatus::kYes);
+  EXPECT_EQ(actual_mf.viewport_device_width, false);
+  EXPECT_EQ(actual_mf.allow_user_zoom, true);
   EXPECT_EQ(actual_mf.viewport_hardcoded_width, 200);
 }
 
@@ -143,8 +143,8 @@
   // pages. But we cannot determine that such page must not be mobile friendly.
   MobileFriendliness actual_mf =
       CalculateMainFrameMetricsForFile("viewport/viewport-34.html");
-  EXPECT_EQ(actual_mf.viewport_device_width, mojom::ViewportStatus::kYes);
-  EXPECT_EQ(actual_mf.allow_user_zoom, mojom::ViewportStatus::kYes);
+  EXPECT_EQ(actual_mf.viewport_device_width, true);
+  EXPECT_EQ(actual_mf.allow_user_zoom, true);
   EXPECT_EQ(actual_mf.viewport_initial_scale_x10, 5);
 }
 
@@ -154,7 +154,7 @@
       <meta name="viewport" content="user-scalable=yes, maximum-scale=1.1">
     </head>
   )");
-  EXPECT_EQ(actual_mf.allow_user_zoom, mojom::ViewportStatus::kNo);
+  EXPECT_EQ(actual_mf.allow_user_zoom, false);
 }
 
 TEST_F(MobileFriendlinessCheckerTest, AllowUserScalableWithLargeMaxZoom) {
@@ -163,7 +163,7 @@
       <meta name="viewport" content="user-scalable=yes, maximum-scale=2.0">
     </head>
   )");
-  EXPECT_EQ(actual_mf.allow_user_zoom, mojom::ViewportStatus::kYes);
+  EXPECT_EQ(actual_mf.allow_user_zoom, true);
 }
 
 TEST_F(MobileFriendlinessCheckerTest,
@@ -173,23 +173,23 @@
       <meta name="viewport" content="user-scalable=yes, maximum-scale=2.0, initial-scale=1.9">
     </head>
   )");
-  EXPECT_EQ(actual_mf.allow_user_zoom, mojom::ViewportStatus::kNo);
+  EXPECT_EQ(actual_mf.allow_user_zoom, false);
 }
 
 TEST_F(MobileFriendlinessCheckerTest, UserZoom) {
   MobileFriendliness actual_mf = CalculateMainFrameMetricsForFile(
       "viewport-initial-scale-and-user-scalable-no.html");
-  EXPECT_EQ(actual_mf.viewport_device_width, mojom::ViewportStatus::kYes);
+  EXPECT_EQ(actual_mf.viewport_device_width, true);
   EXPECT_EQ(actual_mf.viewport_initial_scale_x10, 20);
-  EXPECT_EQ(actual_mf.allow_user_zoom, mojom::ViewportStatus::kNo);
+  EXPECT_EQ(actual_mf.allow_user_zoom, false);
   EXPECT_EQ(actual_mf.small_text_ratio, 100);
 }
 
 TEST_F(ClockFixedMobileFriendlinessCheckerTest, NoText) {
   MobileFriendliness actual_mf =
       CalculateMainFrameMetricsForHTMLString(R"(<body></body>)");
-  EXPECT_EQ(actual_mf.viewport_device_width, mojom::ViewportStatus::kNo);
-  EXPECT_EQ(actual_mf.allow_user_zoom, mojom::ViewportStatus::kYes);
+  EXPECT_EQ(actual_mf.viewport_device_width, false);
+  EXPECT_EQ(actual_mf.allow_user_zoom, true);
   EXPECT_EQ(actual_mf.small_text_ratio, 0);
   EXPECT_EQ(actual_mf.bad_tap_targets_ratio, 0);
 }
@@ -200,8 +200,8 @@
   This is legible font size example.
 </div>
 )");
-  EXPECT_EQ(actual_mf.viewport_device_width, mojom::ViewportStatus::kNo);
-  EXPECT_EQ(actual_mf.allow_user_zoom, mojom::ViewportStatus::kYes);
+  EXPECT_EQ(actual_mf.viewport_device_width, false);
+  EXPECT_EQ(actual_mf.allow_user_zoom, true);
   EXPECT_EQ(actual_mf.small_text_ratio, 0);
 }
 
@@ -211,8 +211,8 @@
   Small font text.
 </div>
 )");
-  EXPECT_EQ(actual_mf.viewport_device_width, mojom::ViewportStatus::kNo);
-  EXPECT_EQ(actual_mf.allow_user_zoom, mojom::ViewportStatus::kYes);
+  EXPECT_EQ(actual_mf.viewport_device_width, false);
+  EXPECT_EQ(actual_mf.allow_user_zoom, true);
   EXPECT_EQ(actual_mf.small_text_ratio, 100);
 }
 
@@ -297,8 +297,8 @@
 </html>
 )");
   EXPECT_EQ(actual_mf.small_text_ratio, 0);
-  EXPECT_EQ(actual_mf.viewport_device_width, mojom::ViewportStatus::kNo);
-  EXPECT_EQ(actual_mf.allow_user_zoom, mojom::ViewportStatus::kYes);
+  EXPECT_EQ(actual_mf.viewport_device_width, false);
+  EXPECT_EQ(actual_mf.allow_user_zoom, true);
 }
 
 TEST_F(MobileFriendlinessCheckerTest, ScaleZoomedLegibleFont) {
@@ -312,9 +312,9 @@
   </body>
 </html>
 )");
-  EXPECT_EQ(actual_mf.viewport_device_width, mojom::ViewportStatus::kYes);
+  EXPECT_EQ(actual_mf.viewport_device_width, true);
   EXPECT_EQ(actual_mf.viewport_initial_scale_x10, 100);
-  EXPECT_EQ(actual_mf.allow_user_zoom, mojom::ViewportStatus::kYes);
+  EXPECT_EQ(actual_mf.allow_user_zoom, true);
   EXPECT_EQ(actual_mf.small_text_ratio, 0);
 }
 
@@ -329,10 +329,10 @@
   </body>
 </html>
 )");
-  EXPECT_EQ(actual_mf.viewport_device_width, mojom::ViewportStatus::kNo);
+  EXPECT_EQ(actual_mf.viewport_device_width, false);
   EXPECT_EQ(actual_mf.viewport_hardcoded_width, 480);
   EXPECT_EQ(actual_mf.viewport_initial_scale_x10, 5);
-  EXPECT_EQ(actual_mf.allow_user_zoom, mojom::ViewportStatus::kYes);
+  EXPECT_EQ(actual_mf.allow_user_zoom, true);
   EXPECT_EQ(actual_mf.small_text_ratio, 100);
 }
 
@@ -347,8 +347,8 @@
   </body>
 </html>
 )");
-  EXPECT_EQ(actual_mf.viewport_device_width, blink::mojom::ViewportStatus::kNo);
-  EXPECT_EQ(actual_mf.allow_user_zoom, mojom::ViewportStatus::kYes);
+  EXPECT_EQ(actual_mf.viewport_device_width, false);
+  EXPECT_EQ(actual_mf.allow_user_zoom, true);
   EXPECT_EQ(actual_mf.viewport_hardcoded_width, 960);
   EXPECT_EQ(actual_mf.small_text_ratio, 100);
 }
@@ -361,8 +361,8 @@
   </body>
 </html>
 )");
-  EXPECT_EQ(actual_mf.viewport_device_width, mojom::ViewportStatus::kNo);
-  EXPECT_EQ(actual_mf.allow_user_zoom, mojom::ViewportStatus::kYes);
+  EXPECT_EQ(actual_mf.viewport_device_width, false);
+  EXPECT_EQ(actual_mf.allow_user_zoom, true);
   EXPECT_EQ(actual_mf.small_text_ratio, 100);
 }
 
@@ -1024,8 +1024,8 @@
   MobileFriendlinessTree actual_mf_tree =
       CalculateMetricsForFile("single_iframe.html");
   const MobileFriendliness& mainframe_mf = actual_mf_tree.mf;
-  EXPECT_EQ(mainframe_mf.viewport_device_width, mojom::ViewportStatus::kNo);
-  EXPECT_EQ(mainframe_mf.allow_user_zoom, mojom::ViewportStatus::kYes);
+  EXPECT_EQ(mainframe_mf.viewport_device_width, false);
+  EXPECT_EQ(mainframe_mf.allow_user_zoom, true);
   EXPECT_EQ(mainframe_mf.bad_tap_targets_ratio, 0);
 
   EXPECT_EQ(actual_mf_tree.children.size(), 1u);
diff --git a/third_party/blink/renderer/modules/manifest/manifest_parser.cc b/third_party/blink/renderer/modules/manifest/manifest_parser.cc
index 6187cba5..84085847 100644
--- a/third_party/blink/renderer/modules/manifest/manifest_parser.cc
+++ b/third_party/blink/renderer/modules/manifest/manifest_parser.cc
@@ -272,10 +272,13 @@
 KURL ManifestParser::ParseURL(const JSONObject* object,
                               const String& key,
                               const KURL& base_url,
-                              ParseURLRestrictions origin_restriction) {
+                              ParseURLRestrictions origin_restriction,
+                              bool ignore_empty_string) {
   absl::optional<String> url_str = ParseString(object, key, NoTrim);
   if (!url_str.has_value())
     return KURL();
+  if (ignore_empty_string && url_str.value() == "")
+    return KURL();
 
   KURL resolved = KURL(base_url, *url_str);
   if (!resolved.IsValid()) {
@@ -395,7 +398,8 @@
   KURL start_url_origin = KURL(SecurityOrigin::Create(start_url)->ToString());
 
   KURL id = ParseURL(object, "id", start_url_origin,
-                     ParseURLRestrictions::kSameOriginOnly);
+                     ParseURLRestrictions::kSameOriginOnly,
+                     /*ignore_empty_string=*/true);
   if (id.IsValid()) {
     ManifestUmaUtil::ParseIdResult(
         ManifestUmaUtil::ParseIdResultType::kSucceed);
diff --git a/third_party/blink/renderer/modules/manifest/manifest_parser.h b/third_party/blink/renderer/modules/manifest/manifest_parser.h
index e6d1071..e8a0fc0 100644
--- a/third_party/blink/renderer/modules/manifest/manifest_parser.h
+++ b/third_party/blink/renderer/modules/manifest/manifest_parser.h
@@ -99,10 +99,14 @@
   // enforce matching of the document's and parsed URL's origins.
   // Returns a KURL. If the parsing failed or origin matching was enforced but
   // not present, the returned KURL will be empty.
+  // |ignore_empty_string| treats empty string as the field missing.
+  // TODO(crbug.com/1223173): remove ignore_empty_string when all url fields are
+  // parsed the same.
   KURL ParseURL(const JSONObject* object,
                 const String& key,
                 const KURL& base_url,
-                ParseURLRestrictions origin_restriction);
+                ParseURLRestrictions origin_restriction,
+                bool ignore_empty_string = false);
 
   // Helper function to parse "enum" fields that accept a single value or a
   // list of values to allow sites to be backwards compatible with browsers that
diff --git a/third_party/blink/renderer/modules/manifest/manifest_parser_unittest.cc b/third_party/blink/renderer/modules/manifest/manifest_parser_unittest.cc
index 4708643..f275db76 100644
--- a/third_party/blink/renderer/modules/manifest/manifest_parser_unittest.cc
+++ b/third_party/blink/renderer/modules/manifest/manifest_parser_unittest.cc
@@ -302,7 +302,7 @@
     auto& manifest =
         ParseManifest(R"({ "start_url": "/start?query=a", "id": "" })");
     ASSERT_EQ(0u, GetErrorCount());
-    EXPECT_EQ("", manifest->id);
+    EXPECT_EQ("start?query=a", manifest->id);
   }
   // Full url.
   {
diff --git a/third_party/blink/renderer/modules/screen_enumeration/window_screens.cc b/third_party/blink/renderer/modules/screen_enumeration/window_screens.cc
index 80aeb17f..de17c01 100644
--- a/third_party/blink/renderer/modules/screen_enumeration/window_screens.cc
+++ b/third_party/blink/renderer/modules/screen_enumeration/window_screens.cc
@@ -70,13 +70,24 @@
                      context->GetTaskRunner(TaskType::kMiscPlatformAPI)));
   }
 
+  auto permission_descriptor = CreatePermissionDescriptor(
+      mojom::blink::PermissionName::WINDOW_PLACEMENT);
   auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
-  permission_service_->RequestPermission(
-      CreatePermissionDescriptor(
-          mojom::blink::PermissionName::WINDOW_PLACEMENT),
-      LocalFrame::HasTransientUserActivation(GetSupplementable()->GetFrame()),
-      WTF::Bind(&WindowScreens::OnPermissionRequestComplete,
-                WrapPersistent(this), WrapPersistent(resolver)));
+  auto callback = WTF::Bind(&WindowScreens::OnPermissionRequestComplete,
+                            WrapPersistent(this), WrapPersistent(resolver));
+
+  // Only allow the user prompts when the frame has a transient activation.
+  // Otherwise, resolve or reject the promise with the current permission state.
+  // This allows sites with permission already granted to obtain screen info
+  // when the document loads, to populate multi-screen UI.
+  if (LocalFrame::HasTransientUserActivation(GetSupplementable()->GetFrame())) {
+    permission_service_->RequestPermission(std::move(permission_descriptor),
+                                           /*user_gesture=*/true,
+                                           std::move(callback));
+  } else {
+    permission_service_->HasPermission(std::move(permission_descriptor),
+                                       std::move(callback));
+  }
 
   return resolver->Promise();
 }
@@ -90,7 +101,10 @@
     auto* const isolate = resolver->GetScriptState()->GetIsolate();
     ScriptState::Scope scope(resolver->GetScriptState());
     resolver->Reject(V8ThrowDOMException::CreateOrEmpty(
-        isolate, DOMExceptionCode::kNotAllowedError, "Permission denied."));
+        isolate, DOMExceptionCode::kNotAllowedError,
+        status == mojom::blink::PermissionStatus::DENIED
+            ? "Permission denied."
+            : "Permission decision deferred."));
     return;
   }
 
diff --git a/third_party/blink/renderer/modules/webtransport/web_transport.cc b/third_party/blink/renderer/modules/webtransport/web_transport.cc
index 616dcdc..6564a4b9 100644
--- a/third_party/blink/renderer/modules/webtransport/web_transport.cc
+++ b/third_party/blink/renderer/modules/webtransport/web_transport.cc
@@ -774,34 +774,33 @@
 
 void WebTransport::close(const WebTransportCloseInfo* close_info) {
   DVLOG(1) << "WebTransport::close() this=" << this;
-  // TODO(ricea): Send |close_info| to the network service.
-
-  if (cleanly_closed_) {
-    // close() has already been called. Ignore it.
+  v8::Isolate* isolate = script_state_->GetIsolate();
+  if (!connector_.is_bound() && !transport_remote_.is_bound()) {
+    // This session has been closed or errored.
     return;
   }
-  cleanly_closed_ = true;
 
-  datagram_underlying_source_->Close();
-
-  received_streams_underlying_source_->Close();
-  received_bidirectional_streams_underlying_source_->Close();
-
-  // If we don't manage to close the writable stream here, then it will
-  // error when a write() is attempted.
-  if (!WritableStream::IsLocked(outgoing_datagrams_) &&
-      !WritableStream::CloseQueuedOrInFlight(outgoing_datagrams_)) {
-    auto promise = WritableStream::Close(script_state_, outgoing_datagrams_);
-    promise->MarkAsHandled();
+  if (!transport_remote_.is_bound()) {
+    // The state is "connecting".
+    v8::Local<v8::Value> error =
+        WebTransportError::Create(isolate, /*stream_error_code=*/absl::nullopt,
+                                  "close() is called while connecting.",
+                                  WebTransportError::Source::kSession);
+    Cleanup(error, error, /*abruptly=*/true);
+    return;
   }
-  closed_resolver_->Resolve(close_info);
 
-  v8::Local<v8::Value> reason = WebTransportError::Create(
-      script_state_->GetIsolate(), /*stream_error_code=*/absl::nullopt,
-      "Connection closed.", WebTransportError::Source::kSession);
-  ready_resolver_->Reject(reason);
-  RejectPendingStreamResolvers();
-  ResetAll();
+  v8::Local<v8::Object> reason = v8::Object::New(isolate);
+  // TODO(yhirano): Set up `reason` correctly. We probably need to accept
+  // "any", to maintain the object identity.
+
+  v8::Local<v8::Value> error = WebTransportError::Create(
+      isolate, /*stream_error_code=*/absl::nullopt, "The session is closed.",
+      WebTransportError::Source::kSession);
+
+  // TODO(yhirano): Call transport_remote_->Close().
+
+  Cleanup(reason, error, /*abruptly=*/false);
 }
 
 void WebTransport::setDatagramWritableQueueExpirationDuration(double duration) {
@@ -854,15 +853,11 @@
   DCHECK(!error);
   DVLOG(1) << "WebTransport::OnHandshakeFailed() this=" << this;
   ScriptState::Scope scope(script_state_);
-  {
-    v8::Local<v8::Value> reason = WebTransportError::Create(
-        script_state_->GetIsolate(),
-        /*stream_error_code=*/absl::nullopt, "Connection lost.",
-        WebTransportError::Source::kSession);
-    ready_resolver_->Reject(reason);
-    closed_resolver_->Reject(reason);
-  }
-  ResetAll();
+  v8::Local<v8::Value> error_to_pass = WebTransportError::Create(
+      script_state_->GetIsolate(),
+      /*stream_error_code=*/absl::nullopt, "Opening handshake failed.",
+      WebTransportError::Source::kSession);
+  Cleanup(error_to_pass, error_to_pass, /*abruptly=*/true);
 }
 
 void WebTransport::OnDatagramReceived(base::span<const uint8_t> data) {
@@ -894,6 +889,26 @@
   stream->OnIncomingStreamClosed(fin_received);
 }
 
+void WebTransport::OnClosed(
+    const absl::optional<WebTransportCloseInfo>& close_info) {
+  ScriptState::Scope scope(script_state_);
+  v8::Isolate* isolate = script_state_->GetIsolate();
+
+  v8::Local<v8::Value> reason;
+  if (close_info) {
+    reason = ToV8(&close_info.value(), script_state_);
+  } else {
+    WebTransportCloseInfo empty_close_info;
+    reason = ToV8(&empty_close_info, script_state_);
+  }
+
+  v8::Local<v8::Value> error = WebTransportError::Create(
+      isolate, /*stream_error_code=*/absl::nullopt, "The session is closed.",
+      WebTransportError::Source::kSession);
+
+  Cleanup(reason, error, /*abruptly=*/false);
+}
+
 void WebTransport::ContextDestroyed() {
   DVLOG(1) << "WebTransport::ContextDestroyed() this=" << this;
   // Child streams must be reset first to ensure that garbage collection
@@ -1100,34 +1115,59 @@
   feature_handle_for_scheduler_.reset();
 }
 
-void WebTransport::OnConnectionError() {
-  DVLOG(1) << "WebTransport::OnConnectionError() this=" << this;
+// https://w3c.github.io/webtransport/#webtransport-cleanup
+void WebTransport::Cleanup(v8::Local<v8::Value> reason,
+                           v8::Local<v8::Value> error,
+                           bool abruptly) {
+  v8::Isolate* isolate = script_state_->GetIsolate();
 
-  ScriptState::Scope scope(script_state_);
-  if (!cleanly_closed_) {
-    v8::Local<v8::Value> reason = WebTransportError::Create(
-        script_state_->GetIsolate(),
-        /*stream_error_code=*/absl::nullopt, "Connection lost.",
-        WebTransportError::Source::kSession);
-    datagram_underlying_source_->Error(reason);
-    received_streams_underlying_source_->Error(reason);
-    received_bidirectional_streams_underlying_source_->Error(reason);
-    WritableStreamDefaultController::ErrorIfNeeded(
-        script_state_, outgoing_datagrams_->Controller(), reason);
-    ready_resolver_->Reject(reason);
-    closed_resolver_->Reject(reason);
-  }
+  RejectPendingStreamResolvers(error);
+  // TODO(yhirano): Error all the incoming/outgoing streams.
 
-  RejectPendingStreamResolvers();
+  datagram_underlying_source_->Error(error);
+  outgoing_datagrams_->Controller()->error(script_state_,
+                                           ScriptValue(isolate, error));
+
+  // We use local variables to avoid re-entrant problems.
+  auto* incoming_bidirectional_streams_source =
+      received_bidirectional_streams_underlying_source_.Get();
+  auto* incoming_unidirectional_streams_source =
+      received_streams_underlying_source_.Get();
+  auto* closed_resolver = closed_resolver_.Get();
+  auto* ready_resolver = ready_resolver_.Get();
+
   ResetAll();
+
+  if (abruptly) {
+    closed_resolver->Reject(error);
+    ready_resolver->Reject(error);
+    incoming_bidirectional_streams_source->Error(error);
+    incoming_unidirectional_streams_source->Error(error);
+  } else {
+    closed_resolver->Resolve(reason);
+    DCHECK_EQ(ready_.V8Promise()->State(),
+              v8::Promise::PromiseState::kFulfilled);
+    incoming_bidirectional_streams_source->Close();
+    incoming_unidirectional_streams_source->Close();
+  }
 }
 
-void WebTransport::RejectPendingStreamResolvers() {
-  v8::Local<v8::Value> reason = WebTransportError::Create(
-      script_state_->GetIsolate(), /*stream_error_code=*/absl::nullopt,
-      "Connection lost.", WebTransportError::Source::kSession);
+void WebTransport::OnConnectionError() {
+  DVLOG(1) << "WebTransport::OnConnectionError() this=" << this;
+  v8::Isolate* isolate = script_state_->GetIsolate();
+
+  ScriptState::Scope scope(script_state_);
+  v8::Local<v8::Value> error = WebTransportError::Create(
+      isolate,
+      /*stream_error_code=*/absl::nullopt, "Connection lost.",
+      WebTransportError::Source::kSession);
+
+  Cleanup(error, error, /*abruptly=*/true);
+}
+
+void WebTransport::RejectPendingStreamResolvers(v8::Local<v8::Value> error) {
   for (ScriptPromiseResolver* resolver : create_stream_resolvers_) {
-    resolver->Reject(reason);
+    resolver->Reject(error);
   }
   create_stream_resolvers_.clear();
 }
diff --git a/third_party/blink/renderer/modules/webtransport/web_transport.h b/third_party/blink/renderer/modules/webtransport/web_transport.h
index 63b78dde..16577a4 100644
--- a/third_party/blink/renderer/modules/webtransport/web_transport.h
+++ b/third_party/blink/renderer/modules/webtransport/web_transport.h
@@ -86,6 +86,8 @@
   void OnDatagramReceived(base::span<const uint8_t> data) override;
   void OnIncomingStreamClosed(uint32_t stream_id, bool fin_received) override;
 
+  void OnClosed(const absl::optional<WebTransportCloseInfo>&);
+
   // Implementation of ExecutionContextLifecycleObserver
   void ContextDestroyed() final;
 
@@ -119,8 +121,11 @@
   void ResetAll();
 
   void Dispose();
+  void Cleanup(v8::Local<v8::Value> reason,
+               v8::Local<v8::Value> error,
+               bool abruptly);
   void OnConnectionError();
-  void RejectPendingStreamResolvers();
+  void RejectPendingStreamResolvers(v8::Local<v8::Value> error);
   void OnCreateSendStreamResponse(ScriptPromiseResolver*,
                                   mojo::ScopedDataPipeProducerHandle,
                                   bool succeeded,
@@ -131,8 +136,6 @@
                                            bool succeeded,
                                            uint32_t stream_id);
 
-  bool cleanly_closed_ = false;
-
   Member<DatagramDuplexStream> datagrams_;
 
   Member<ReadableStream> received_datagrams_;
diff --git a/third_party/blink/renderer/modules/webtransport/web_transport_test.cc b/third_party/blink/renderer/modules/webtransport/web_transport_test.cc
index f3d35d0..8673d62 100644
--- a/third_party/blink/renderer/modules/webtransport/web_transport_test.cc
+++ b/third_party/blink/renderer/modules/webtransport/web_transport_test.cc
@@ -555,7 +555,7 @@
 
   EXPECT_FALSE(web_transport->HasPendingActivity());
   EXPECT_TRUE(ready_tester.IsRejected());
-  EXPECT_TRUE(closed_tester.IsFulfilled());
+  EXPECT_TRUE(closed_tester.IsRejected());
 }
 
 TEST_F(WebTransportTest, CloseAfterConnection) {
@@ -809,19 +809,6 @@
   return result;
 }
 
-bool IsDone(ScriptState* script_state, ScriptValue iterator_result) {
-  bool done = false;
-  v8::Local<v8::Value> value;
-  if (!V8UnpackIteratorResult(script_state,
-                              iterator_result.V8Value().As<v8::Object>(), &done)
-           .ToLocal(&value)) {
-    ADD_FAILURE() << "unable to unpack iterator_result";
-    return false;
-  }
-
-  return done;
-}
-
 TEST_F(WebTransportTest, ReceiveDatagramBeforeRead) {
   V8TestingScope scope;
   auto* web_transport =
@@ -885,7 +872,7 @@
   test::RunPendingTasks();
 }
 
-TEST_F(WebTransportTest, DatagramsStillReadableAfterClose) {
+TEST_F(WebTransportTest, DatagramsShouldBeErroredAfterClose) {
   V8TestingScope scope;
   auto* web_transport =
       CreateAndConnectSuccessfully(scope, "https://example.com");
@@ -904,15 +891,7 @@
   ScriptPromise result1 = reader->read(script_state, ASSERT_NO_EXCEPTION);
   ScriptPromiseTester tester1(script_state, result1);
   tester1.WaitUntilSettled();
-  EXPECT_TRUE(tester1.IsFulfilled());
-  EXPECT_THAT(GetValueAsVector(script_state, tester1.Value()),
-              ElementsAre('A'));
-
-  ScriptPromise result2 = reader->read(script_state, ASSERT_NO_EXCEPTION);
-  ScriptPromiseTester tester2(script_state, result2);
-  tester2.WaitUntilSettled();
-  EXPECT_TRUE(tester2.IsFulfilled());
-  EXPECT_TRUE(IsDone(script_state, tester2.Value()));
+  EXPECT_TRUE(tester1.IsRejected());
 }
 
 TEST_F(WebTransportTest, ResettingIncomingHighWaterMarkWorksAfterClose) {
@@ -937,8 +916,7 @@
 
   ScriptPromiseTester tester(script_state, result);
   tester.WaitUntilSettled();
-  EXPECT_TRUE(tester.IsFulfilled());
-  EXPECT_TRUE(IsDone(script_state, tester.Value()));
+  EXPECT_TRUE(tester.IsRejected());
 }
 
 TEST_F(WebTransportTest, TransportErrorErrorsReadableStream) {
@@ -1712,6 +1690,61 @@
   ConnectSuccessfully(web_transport, kDurationDelta);
 }
 
+TEST_F(WebTransportTest, OnClosed) {
+  V8TestingScope scope;
+  v8::Isolate* isolate = scope.GetIsolate();
+
+  auto* web_transport =
+      CreateAndConnectSuccessfully(scope, "https://example.com");
+
+  auto* script_state = scope.GetScriptState();
+  ScriptPromiseTester tester(script_state, web_transport->closed());
+
+  absl::optional<WebTransportCloseInfo> input_close_info(absl::in_place);
+  input_close_info->setErrorCode(99);
+  input_close_info->setReason("reason");
+
+  web_transport->OnClosed(input_close_info);
+
+  tester.WaitUntilSettled();
+
+  EXPECT_TRUE(tester.IsFulfilled());
+  ScriptValue value = tester.Value();
+  ASSERT_FALSE(value.IsEmpty());
+  ASSERT_TRUE(value.IsObject());
+  WebTransportCloseInfo* close_info = WebTransportCloseInfo::Create(
+      isolate, value.V8Value(), ASSERT_NO_EXCEPTION);
+  EXPECT_TRUE(close_info->hasErrorCode());
+  EXPECT_TRUE(close_info->hasReason());
+  EXPECT_EQ(close_info->errorCode(), 99);
+  EXPECT_EQ(close_info->reason(), "reason");
+}
+
+TEST_F(WebTransportTest, OnClosedWithNull) {
+  V8TestingScope scope;
+  v8::Isolate* isolate = scope.GetIsolate();
+
+  auto* web_transport =
+      CreateAndConnectSuccessfully(scope, "https://example.com");
+
+  auto* script_state = scope.GetScriptState();
+  ScriptPromiseTester tester(script_state, web_transport->closed());
+
+  web_transport->OnClosed(absl::nullopt);
+
+  tester.WaitUntilSettled();
+
+  EXPECT_TRUE(tester.IsFulfilled());
+  ScriptValue value = tester.Value();
+  ASSERT_FALSE(value.IsEmpty());
+  ASSERT_TRUE(value.IsObject());
+  WebTransportCloseInfo* close_info = WebTransportCloseInfo::Create(
+      isolate, value.V8Value(), ASSERT_NO_EXCEPTION);
+  // TODO(yhirano): `close_info` should be empty but actually not because of the
+  // IDL definition for WebTransportCloseInfo. Fix that.
+  DCHECK(close_info);
+}
+
 }  // namespace
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index c73cfd69..417b6854d 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1794,6 +1794,7 @@
     {
       name: "PrefersContrast",
       depends_on: ["ForcedColors"],
+      status: "stable",
     },
     {
       name: "PrefersReducedData",
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 794a3704b..2e4565f6 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -2847,6 +2847,12 @@
 crbug.com/626703 virtual/plz-dedicated-worker/external/wpt/service-workers/service-worker/worker-interception.https.html [ Pass ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 [ Linux ] external/wpt/html/semantics/forms/the-selectmenu-element/selectmenu-parts-structure.tentative.html [ Timeout ]
+crbug.com/626703 [ Mac10.14 ] external/wpt/html/semantics/forms/the-selectmenu-element/selectmenu-parts-structure.tentative.html [ Timeout ]
+crbug.com/626703 [ Linux ] virtual/synchronous_html_parser/external/wpt/html/semantics/forms/the-selectmenu-element/selectmenu-parts-structure.tentative.html [ Timeout ]
+crbug.com/626703 [ Mac10.14 ] virtual/synchronous_html_parser/external/wpt/html/semantics/forms/the-selectmenu-element/selectmenu-parts-structure.tentative.html [ Timeout ]
+crbug.com/626703 [ Linux ] virtual/coep-for-shared-worker/external/wpt/html/cross-origin-embedder-policy/reporting-subresource-corp.https.html [ Skip Timeout ]
+crbug.com/626703 [ Mac11.0 ] virtual/coep-for-shared-worker/external/wpt/html/cross-origin-embedder-policy/reporting-subresource-corp.https.html [ Skip Timeout ]
 crbug.com/626703 [ Linux ] external/wpt/css/css-flexbox/dynamic-isize-change-002.html [ Crash ]
 crbug.com/626703 external/wpt/css/css-text/tab-size/tab-size-block-ancestor.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-pseudo/highlight-styling-004.html [ Failure ]
@@ -4151,9 +4157,6 @@
 # CSS Scrollbars Level 1
 crbug.com/891944 external/wpt/css/cssom-view/client-props-root.html [ Failure ]
 
-# CSS prefers-contrast media query not implemented
-crbug.com/1107431 external/wpt/css/mediaqueries/prefers-contrast.html [ Failure ]
-
 # Sheriff failures 2017-03-10
 crbug.com/741210 [ Mac ] inspector-protocol/emulation/device-emulation-restore.js [ Failure ]
 
@@ -6898,7 +6901,11 @@
 # Sheriff 2021-09-16
 crbug.com/1250457 [ Win7 ] http/tests/devtools/sources/debugger-ui/script-formatter-breakpoints-3.js [ Failure ]
 crbug.com/1250457 [ Mac ] virtual/scroll-unification/plugins/plugin-map-data-to-src.html [ Failure ]
-crbug.com/1250457 [ Mac ] virtual/coep-for-shared-worker/external/wpt/html/cross-origin-embedder-policy/reporting-subresource-corp.https.html [ Failure ]
+crbug.com/1250457 [ Mac10.12 ] virtual/coep-for-shared-worker/external/wpt/html/cross-origin-embedder-policy/reporting-subresource-corp.https.html [ Failure ]
+crbug.com/1250457 [ Mac10.13 ] virtual/coep-for-shared-worker/external/wpt/html/cross-origin-embedder-policy/reporting-subresource-corp.https.html [ Failure ]
+crbug.com/1250457 [ Mac10.14 ] virtual/coep-for-shared-worker/external/wpt/html/cross-origin-embedder-policy/reporting-subresource-corp.https.html [ Failure ]
+crbug.com/1250457 [ Mac10.15 ] virtual/coep-for-shared-worker/external/wpt/html/cross-origin-embedder-policy/reporting-subresource-corp.https.html [ Failure ]
+crbug.com/1250457 [ Mac11-arm64 ] virtual/coep-for-shared-worker/external/wpt/html/cross-origin-embedder-policy/reporting-subresource-corp.https.html [ Failure ]
 crbug.com/1250457 [ Mac ] storage/websql/open-database-set-empty-version.html [ Timeout ]
 crbug.com/1250457 [ Mac ] virtual/not-plz-service-worker/external/wpt/html/cross-origin-embedder-policy/credentialless/iframe-coep-credentialless.tentative.https.html?9-last [ Timeout ]
 crbug.com/1250457 [ Mac ] virtual/not-plz-service-worker/external/wpt/service-workers/cache-storage/serviceworker/cache-matchAll.https.html [ Skip Timeout ]
diff --git a/third_party/blink/web_tests/editing/spelling/spellcheck-remove-markers.html b/third_party/blink/web_tests/editing/spelling/spellcheck-remove-markers.html
index df14b8c..fdfa4e35 100644
--- a/third_party/blink/web_tests/editing/spelling/spellcheck-remove-markers.html
+++ b/third_party/blink/web_tests/editing/spelling/spellcheck-remove-markers.html
@@ -134,4 +134,17 @@
         '<div contenteditable spellcheck="false">zz. I have a issue.</div>',
         'Setting "spellcheck" attribute to "false" removes spelling markers.')
     });
+
+    spellcheck_test(
+    '<textarea>|zz. I have a issue.</textarea>',
+    '',
+    '<textarea>#zz#. I have ~a~ issue.</textarea>',
+    {
+      title: '11) Setup for the initial markers.',
+      callback: sample => spellcheck_test(
+        sample,
+        document => document.querySelector('textarea').setAttribute('spellcheck', 'false'),
+        '<textarea spellcheck="false">zz. I have a issue.</textarea>',
+        'Setting "spellcheck" attribute to "false" removes spelling markers for textarea.')
+    });
 </script>
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
index 72ffa06..ffccb82 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -703,6 +703,13 @@
        {}
       ]
      ],
+     "balance-extremely-tall-monolithic-content-crash.html": [
+      "1fb178ffb25c77d415665aa0c1a4348ae4f51421",
+      [
+       null,
+       {}
+      ]
+     ],
      "change-abspos-width-in-second-column-crash.html": [
       "78243c76878bcb75331a1a8f91644347df5500ea",
       [
@@ -134136,6 +134143,19 @@
        {}
       ]
      ],
+     "highlight-cascade-003.html": [
+      "61bc46d4c50feab4f275e6d0785bf729c4239b27",
+      [
+       null,
+       [
+        [
+         "/css/css-pseudo/highlight-cascade-003-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
      "highlight-painting-001.html": [
       "ef253e6117c94ef63f9be97eaac0d94667c9fce3",
       [
@@ -156139,6 +156159,19 @@
         {}
        ]
       ],
+      "display-contents-remove-whitespace-change.html": [
+       "baf42aa3a8a6f6b2af963b38b2441f7f9e12a3e7",
+       [
+        null,
+        [
+         [
+          "/css/reference/pass_if_two_words.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
       "eol-spaces-bidi-001.html": [
        "b8bcbe17b738d40e4facffc0285282fe20002d30",
        [
@@ -156936,6 +156969,19 @@
         {}
        ]
       ],
+      "remove-slotted-with-whitespace-sibling.html": [
+       "806bf05eac1800478c1fdc6ac14b556c87e55267",
+       [
+        null,
+        [
+         [
+          "/css/reference/pass_if_two_words.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
       "seg-break-transformation-018.tentative.html": [
        "2faf185856baf75b4820b57cd9b4ffe4161f7a29",
        [
@@ -162499,7 +162545,7 @@
       ]
      ],
      "css-transforms-transformlist.html": [
-      "b0f159a40ba428100a16a1fb1a74441cc414081b",
+      "1551554545b8697d7baf49dde0ea61825c641918",
       [
        null,
        [
@@ -165713,7 +165759,7 @@
       ]
      ],
      "skew-test1.html": [
-      "1f366673488b1a1a4cc2f95096f57a9ef358a23e",
+      "b7baf138727b526e0e25c5697d47ace4b17d1272",
       [
        null,
        [
@@ -168143,7 +168189,7 @@
        ]
       ],
       "svg-origin-relative-length-030.html": [
-       "a3c96c2a16758465e7cc3fcd74bb37fc885fe0b0",
+       "3faaee6647347a8fc3fc6ce86672c805d484047d",
        [
         null,
         [
@@ -168221,7 +168267,7 @@
        ]
       ],
       "svg-origin-relative-length-036.html": [
-       "ac39e86f9331991f54610212a7e550df08787bd8",
+       "2ed45e7cfe1c6f43890a70e1ce9de6569984ec37",
        [
         null,
         [
@@ -168325,7 +168371,7 @@
        ]
       ],
       "svg-origin-relative-length-044.html": [
-       "92944c7bf6ad58e31aa995aef2a554e2003cf2d6",
+       "e8352af4017e29de442132a66620ec4eaa48a0a8",
        [
         null,
         [
@@ -168351,7 +168397,7 @@
        ]
       ],
       "svg-origin-relative-length-046.html": [
-       "29072ba1893bcb094d9b5e29225087a349d8d7bb",
+       "fd7d9764e3bf8c8b29f4749cd6bcf98748b35e3a",
        [
         null,
         [
@@ -169160,7 +169206,7 @@
       ]
      ],
      "transform-rotate-006.html": [
-      "eddfb7a29b5a0b68382347f0df7d12d6d0911eba",
+      "678d0cbeec3078acbcec2b956035a8d29092afe5",
       [
        null,
        [
@@ -169207,7 +169253,7 @@
       ]
      ],
      "transform-scale-001.html": [
-      "9a67ecf2e1066513f7078b93082325a2de8f707c",
+      "d046cc3fb313dae2719fcc7fe1a0c0f98d6fad6d",
       [
        null,
        [
@@ -169220,7 +169266,7 @@
       ]
      ],
      "transform-scale-002.html": [
-      "2c4742a5323ee5122814af6035865a64f10c2968",
+      "dad5f25af5c7a038718f1bb4017e8c65f1e9c972",
       [
        null,
        [
@@ -169272,7 +169318,7 @@
       ]
      ],
      "transform-scaley-001.html": [
-      "833ccbd237f619a3985a3da97cc35f65a954b633",
+      "e226156bf8275d13903ec79263fd68cdf8593d8d",
       [
        null,
        [
@@ -169474,7 +169520,7 @@
       ]
      ],
      "transform-table-008.html": [
-      "ba5a782622ae526df77f53f0fa01d4727ba65be9",
+      "24a96d44bd8d9b98b686f5d8273fd3bedb399fc9",
       [
        null,
        [
@@ -169928,12 +169974,12 @@
       ]
      ],
      "transform-translatex-006.html": [
-      "e01d0f759c681b7e08cbc0ed3760b88777b284a6",
+      "fd6f46fc165650291cf6e3eb20e2a511de39dc50",
       [
        null,
        [
         [
-         "/css/css-transforms/transform-translatex-ref.html",
+         "/css/css-transforms/reference/transform-translatex-006-ref.html",
          "=="
         ]
        ],
@@ -171454,7 +171500,7 @@
       ]
      ],
      "ttwf-transform-translatex-001.html": [
-      "f85d332400f35fdc6e2f81dfbdebfb470b6dfc6b",
+      "bef05c05fd9dc61807c2da6bba9952b9dca05cb8",
       [
        null,
        [
@@ -218196,7 +218242,7 @@
       []
      ],
      "checkReport.sub.js": [
-      "bd447161ec76861604c0d07138b92a45a4bc9860",
+      "9cc242662bc6ba227dd209d5b65843ae68236dc1",
       []
      ],
      "dedicated-worker-helper.js": [
@@ -246115,6 +246161,10 @@
       "17629a6dbad7fb5700b35b8bd0ea5280dba69140",
       []
      ],
+     "highlight-cascade-003-ref.html": [
+      "256c28ba0c068630cf675698e019b656a6c56da7",
+      []
+     ],
      "highlight-painting-001-ref.html": [
       "c5d8814a8252b0a8e4be1b43f635cd7b11f548fc",
       []
@@ -253023,7 +253073,7 @@
        []
       ],
       "skew-test1-ref.html": [
-       "d69df1ba455ae7cf049c68481ecc721676f3f22f",
+       "394de2b6c259f0f2f070f0bd2993c0e284b0e972",
        []
       ],
       "subpixel-transform-changes-001-ref.html": [
@@ -253066,7 +253116,7 @@
        "5f5a9af957990707ab0169e740967278df04697e",
        []
       ],
-      "transform-translateX-001-ref.html": [
+      "transform-translatex-006-ref.html": [
        "a1cee2aa91eb9ba2928ef5b7e2d0cb152cebebe0",
        []
       ],
@@ -253127,7 +253177,7 @@
        []
       ],
       "ttwf-reftest-transform-translatex-001.html": [
-       "0e454068261495c98d76329062ecb0fb1c2d75b1",
+       "68ab44af7879dbe1e7416a69d7f37a61aac02d60",
        []
       ],
       "ttwf-reftest-transform-translatey-001.html": [
@@ -253774,7 +253824,7 @@
       []
      ],
      "transform-scale-ref.html": [
-      "79a70df6de9d013f94db70a6069a70afec721355",
+      "4bcfab0c7dc29fd8a02e4b3b4c141282601c1b48",
       []
      ],
      "transform-scalex-ref.html": [
@@ -253782,7 +253832,7 @@
       []
      ],
      "transform-scaley-ref.html": [
-      "706b796d1aa09cd86c00f33a46afca7ecc9d7135",
+      "b84ede464dc8069ac337d0d180b8041de1ad180f",
       []
      ],
      "transform-singular-ref.html": [
@@ -255869,6 +255919,14 @@
       "a22882a9996b14afa942d3403fa1a873f526073a",
       []
      ],
+     "acos-asin-atan-atan2-computed-expected.txt": [
+      "2ba4cc738545190856f16d4bda9dee144cb62a24",
+      []
+     ],
+     "acos-asin-atan-atan2-serialize-expected.txt": [
+      "e87d77c6e5d64110d94a0fa5447de2ad256427d4",
+      []
+     ],
      "calc-background-image-gradient-1-ref.html": [
       "3fefef23ff7ea3811064c953bddc327098454199",
       []
@@ -260870,7 +260928,7 @@
       []
      ],
      "numeric-testcommon.js": [
-      "f5ba0881805de293dbf2f1421e278553f54d66ac",
+      "534d379fe4ae6623dcd88a26c30071b6d7edd9da",
       []
      ],
      "parsing-testcommon.js": [
@@ -272994,7 +273052,7 @@
       },
       "navigation-reporting": {
        "report-only-four-reports.https.html.sub.headers": [
-        "292f6e8c0638df86d8ce80baed6e3d3302e45d18",
+        "9e864109a1e6218f0f91ef85245e52590d1407ad",
         []
        ],
        "report-only-from-unsafe-none.https.html.headers": [
@@ -273002,7 +273060,7 @@
         []
        ],
        "report-only-same-origin-report-to.https.html.sub.headers": [
-        "3f3197fc72925171e9119758e7a825ea0527109a",
+        "97104b6d6cfbd8065d3fb820183434cee1704609",
         []
        ],
        "report-only-same-origin-with-coep-report-only.https.html.headers": [
@@ -273018,19 +273076,19 @@
         []
        ],
        "reporting-coop-navigated-popup.https.html.sub.headers": [
-        "af9f1e77f21229eb6106fedd0566afd96f55e848",
+        "795e7891cb1986dff28ba453298057d2bd0153e5",
         []
        ],
        "reporting-popup-same-origin-allow-popups-report-to.https.html.sub.headers": [
-        "ab69a89b8b885f09714bd5fa6549e6ca18edf678",
+        "50d1e34efc224071a093fc9718a3aa864805c798",
         []
        ],
        "reporting-popup-same-origin-coep-report-to.https.html.sub.headers": [
-        "5308f7a5b12615d90c293d405bdcbef6eafff4bf",
+        "a978bd3e00766a1b84b1c7a306721a12576d0c4b",
         []
        ],
        "reporting-popup-same-origin-report-to.https.html.sub.headers": [
-        "936b29824287e85eb4dc07d39c0fe129e8f105b4",
+        "200360e3c97acdad37641d49beddc1550277a9a0",
         []
        ],
        "reporting-popup-same-origin.https.html.headers": [
@@ -273038,17 +273096,17 @@
         []
        ],
        "reporting-popup-unsafe-none-report-to.https.html.sub.headers": [
-        "144a3bd1324f001bd681ce404b1576da7650afa2",
+        "f22298ef94ce55884b14e163b4bfa10871a9a1d1",
         []
        ]
       },
       "resources": {
        "reporting-common.js": [
-        "e44a70426d7277061c9385f0d2ea57b44acf87d7",
+        "246c9224a3aed467d126a65b6129921c7b14199f",
         []
        ],
        "test-access-property.js": [
-        "c8c0ea2f537cd41395a1a47fc33a451d9b23e3a8",
+        "fe01e9128c51bd0ee65ba212967dcc989ac1bf1e",
         []
        ],
        "try-access.js": [
@@ -280079,10 +280137,6 @@
         "d12943105f8c47d32f47eec0aa773a9a98046bfa",
         []
        ],
-       "selectmenu-popup.tentative-expected.txt": [
-        "056f1af9c5bb3f1bf9eb3b4fda895738c556884f",
-        []
-       ],
        "support": {
         "cat.png": [
          "85dd7324815b8f8ef1a1d0496224c1a0661db9d8",
@@ -292285,13 +292339,33 @@
      []
     ],
     "cross-origin-report-no-credentials.https.sub.html.sub.headers": [
-     "007c097f058586877e4c969a43faccb80037c3d2",
+     "24eaf19fecb9299e1d0cf157ef4c94af709db640",
      []
     ],
     "cross-origin-reports-isolated.https.sub.html.sub.headers": [
      "00b60a2d0c4db4bd0505d03e03a98a105ef2a57e",
      []
     ],
+    "document-reporting-bypass-report-to.https.sub.html.sub.headers": [
+     "b2a3d20f482151a27a545c8894805737a57ff035",
+     []
+    ],
+    "document-reporting-default-endpoint.https.sub.html.sub.headers": [
+     "e374d79be0c1d88017d2fd9c2de02b5187738ef5",
+     []
+    ],
+    "document-reporting-named-endpoints.https.sub.html.sub.headers": [
+     "2d5a308db27f7b2595114bf7e4fd8fa9612dfc0e",
+     []
+    ],
+    "document-reporting-override-endpoint.https.sub.html.sub.headers": [
+     "46954f4d5cbc9a17a9bcbf91481e905748441edd",
+     []
+    ],
+    "document-reporting-path-absolute.https.sub.html.sub.headers": [
+     "547cd6a588e6ce4110709f493bcd6561a9c52e2a",
+     []
+    ],
     "idlharness.any-expected.txt": [
      "55ab8a9bd30bc2473b9faa72c0baf27e7dfdf298",
      []
@@ -292305,12 +292379,12 @@
      []
     ],
     "path-absolute-endpoint.https.sub.html.sub.headers": [
-     "5bd5ae7f0f53a63eecc6a2534185323483a060ec",
+     "64d0894062d47f6b65b74317a31cb7c1a1049b7f",
      []
     ],
     "resources": {
      "README.md": [
-      "f3ee06c14a44799fe7cced086302f5d0e2ad677c",
+      "b77d1f96b7d6b5886f1d43b2b44aea76afd56df6",
       []
      ],
      "csp-error.https.sub.html": [
@@ -292333,12 +292407,28 @@
       "2f5eeb4d8c787d3551efbc143813f98de9a94e12",
       []
      ],
+     "generate-csp-report.https.sub.html": [
+      "7adec0f30909c8424fa495874db8de34db30fcca",
+      []
+     ],
+     "generate-csp-report.https.sub.html.sub.headers": [
+      "44242c3c89e73ba4e9db232a138a897bff6611c8",
+      []
+     ],
+     "generate-report-once.py": [
+      "076d5008751f5083353214362506bdf123a22919",
+      []
+     ],
+     "generate-report.https.sub.html": [
+      "ee40c46e3870db95c679c82263c8ed79bceff09b",
+      []
+     ],
      "report-helper.js": [
-      "cc4f07f067c6a90e3bb78a90dd45e0357795c5f9",
+      "213a635c493a198f12075992ecc8630d01717f51",
       []
      ],
      "report.py": [
-      "9310808a654bb3a0399692372f822116494edd73",
+      "b5ee0c07d863e513f246f398134d6c18f4ade150",
       []
      ],
      "second-csp-report.https.sub.html": [
@@ -292351,7 +292441,7 @@
      ]
     },
     "same-origin-report-credentials.https.sub.html.sub.headers": [
-     "8244fafb22c34fb6aef0dd2587c12bbedc70e7f6",
+     "a88efd0cf93dc1e34749ee415bf663afc26d3d73",
      []
     ]
    },
@@ -328371,7 +328461,7 @@
       ]
      ],
      "worker-from-guid.sub.html": [
-      "0525ed2bf9b0a1dfbffb2b6f834f22695ed994b1",
+      "045afb808224ab75537d4d2f2c455fc1a54fb49b",
       [
        null,
        {}
@@ -359665,6 +359755,27 @@
        {}
       ]
      ],
+     "acos-asin-atan-atan2-computed.html": [
+      "6fc8bdfe6af42bb53bbdfdaff71a9bb13135ccb4",
+      [
+       null,
+       {}
+      ]
+     ],
+     "acos-asin-atan-atan2-invalid.html": [
+      "af997c12aaaea42ba1aa2d758b6aa5e979daac5e",
+      [
+       null,
+       {}
+      ]
+     ],
+     "acos-asin-atan-atan2-serialize.html": [
+      "637667fcb821b4a3f822df603749c125e9cf521f",
+      [
+       null,
+       {}
+      ]
+     ],
      "animations": {
       "calc-interpolation.html": [
        "de76386e0dadc292cc66dec1170e57b19f2cdc69",
@@ -421718,7 +421829,7 @@
         ]
        ],
        "property-opener-set.https.html": [
-        "478fc5c82fe25620b970841ede9a652d7339abbe",
+        "10c251140b8895594e50ef2da3aa6fc0ecfd6ecf",
         [
          null,
          {}
@@ -421780,7 +421891,7 @@
       },
       "navigation-reporting": {
        "report-only-four-reports.https.html": [
-        "95e87e61bb75ae40a9cad440ce37ab5c91ae4db6",
+        "ca1471ccc0ab82ec343ff9990fb52961755ee6de",
         [
          null,
          {
@@ -421798,7 +421909,7 @@
         ]
        ],
        "report-only-same-origin-report-to.https.html": [
-        "d61b987887ef76bb57546e33e01d02fbf66b0a57",
+        "52b1f2a09f6f6efe06b810e47614f453122ab534",
         [
          null,
          {
@@ -421843,14 +421954,14 @@
         ]
        ],
        "reporting-coop-navigated-popup.https.html": [
-        "70e5eae996736d74b392130ff7067119ead7e6dd",
+        "68ecd913756fa254b29e12c434e0519206c7fda1",
         [
          null,
          {}
         ]
        ],
        "reporting-popup-same-origin-allow-popups-report-to.https.html": [
-        "760db13dcec2af116ca8729ab31d04a198e0f049",
+        "d674e2e449356b9670f73b3391cce8ddb7fd4dbb",
         [
          null,
          {
@@ -421859,7 +421970,7 @@
         ]
        ],
        "reporting-popup-same-origin-coep-report-to.https.html": [
-        "06170f68e3f2fe5feeb55757f8a55ed12c4923aa",
+        "88b180702f9d9c2695a6e922358c0a1c0b6fda82",
         [
          null,
          {
@@ -421868,7 +421979,7 @@
         ]
        ],
        "reporting-popup-same-origin-report-to.https.html": [
-        "cee3aae692f8c42631d2d9b6a820f6e80277528a",
+        "47bb67cc4b77521f44cc6e6694597fb57871328e",
         [
          null,
          {
@@ -421886,7 +421997,7 @@
         ]
        ],
        "reporting-popup-unsafe-none-report-to.https.html": [
-        "4e8ce4fe6bfccb20dc9350cd7b9e5eb19cfe4e8e",
+        "2563dbb01faaddb530819a9af04ae84230d17589",
         [
          null,
          {
@@ -431658,7 +431769,7 @@
         ]
        ],
        "selectmenu-parts-structure.tentative.html": [
-        "62f9b29e3009709cd8551a70fceac1b3ec95ca9d",
+        "9f7a8ac6ef5a5888a546b393ee45c5cc192c4723",
         [
          null,
          {
@@ -431676,7 +431787,7 @@
         ]
        ],
        "selectmenu-popup.tentative.html": [
-        "00c8441fbafec5b27a7ee2352890ce71f668d825",
+        "a43761d331d49d2b6f533a84b55ce9296257df64",
         [
          null,
          {
@@ -469351,7 +469462,7 @@
      ]
     ],
     "cross-origin-report-no-credentials.https.sub.html": [
-     "d4ff60f35198639f1e9412c7681f9fa3b28e0438",
+     "727259b0d96fe150a93b3380ca4326467b8757f7",
      [
       null,
       {}
@@ -469373,6 +469484,59 @@
       }
      ]
     ],
+    "document-reporting-bypass-report-to.https.sub.html": [
+     "394bc9e40a0a8b3dba5c2f176230d1e73dc0c46b",
+     [
+      null,
+      {}
+     ]
+    ],
+    "document-reporting-default-endpoint.https.sub.html": [
+     "24c1216afaa99917c0afd84f6e3e09ac4ab63089",
+     [
+      null,
+      {
+       "testdriver": true
+      }
+     ]
+    ],
+    "document-reporting-destroy-after-document-close.https.sub.html": [
+     "49ad1fab4e0346885f3289ae55af80c71da3b06f",
+     [
+      null,
+      {}
+     ]
+    ],
+    "document-reporting-named-endpoints.https.sub.html": [
+     "c24601147a2a2aac5dee708c9ec7a2f73594dde7",
+     [
+      null,
+      {}
+     ]
+    ],
+    "document-reporting-not-batch-different-document.https.html": [
+     "e124bd7fbdf011dd229360d9addffbe517610a08",
+     [
+      null,
+      {}
+     ]
+    ],
+    "document-reporting-override-endpoint.https.sub.html": [
+     "9264786093e7a9f524727ad98a0c13b61e133bd2",
+     [
+      null,
+      {}
+     ]
+    ],
+    "document-reporting-path-absolute.https.sub.html": [
+     "e23dd85e7c4c5efa1aae87cdd85a5fb1ed143680",
+     [
+      null,
+      {
+       "testdriver": true
+      }
+     ]
+    ],
     "generateTestReport.html": [
      "1c6e7dc225726f46f42c5f50e54bd54b46cf9be6",
      [
@@ -469434,7 +469598,7 @@
      ]
     ],
     "path-absolute-endpoint.https.sub.html": [
-     "ecd44c35ddf23e8e5d5cc14e86e8ef619709db2b",
+     "fe119ac5cdf530d245974b60ecc30575266b8522",
      [
       null,
       {}
@@ -469448,7 +469612,7 @@
      ]
     ],
     "same-origin-report-credentials.https.sub.html": [
-     "a7264fa593fc206aaec28db707d88a4f1495c7ec",
+     "fb753783e636d05c137241592e59d8152188f6f6",
      [
       null,
       {}
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-browser-manual.tentative.html b/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-browser-manual.tentative.html
index 8bc5b11..d13d0986 100644
--- a/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-browser-manual.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-browser-manual.tentative.html
@@ -2,7 +2,8 @@
 <title>Test "browser" in display-override member + media feature</title>
 <link rel="help" href="https://w3c.github.io/manifest/#dom-displaymodetype-browser" />
 <link rel="help" href="https://w3c.github.io/manifest/#the-display-mode-media-feature" />
-<link rel="manifest" href="display-override-member-media-feature-browser.webmanifest" />
+<link rel="manifest" href="resources/display-override-member-media-feature-browser.webmanifest" />
+<script src="resources/display-override-member-media-feature-manual.js"></script>
 <meta name="viewport" content="width=device-width, initial-scale=1">
 <h1>Test "browser" in display-override member + media feature</h1>
 <style>
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-browser.webmanifest b/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-browser.webmanifest
deleted file mode 100644
index f65c7de9..0000000
--- a/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-browser.webmanifest
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-    "display_override": [ "browser" ]
-}
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-fullscreen-manual.tentative.html b/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-fullscreen-manual.tentative.html
index b3cc4d39..0b9923f 100644
--- a/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-fullscreen-manual.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-fullscreen-manual.tentative.html
@@ -2,7 +2,8 @@
 <title>Test "fullscreen" in display-override member + media feature</title>
 <link rel="help" href="https://w3c.github.io/manifest/#dom-displaymodetype-fullscreen" />
 <link rel="help" href="https://w3c.github.io/manifest/#the-display-mode-media-feature" />
-<link rel="manifest" href="display-override-member-media-feature-fullscreen.webmanifest" />
+<link rel="manifest" href="resources/display-override-member-media-feature-fullscreen.webmanifest" />
+<script src="resources/display-override-member-media-feature-manual.js"></script>
 <meta name="viewport" content="width=device-width, initial-scale=1">
 <h1>Test "fullscreen" in display-override member + media feature</h1>
 <style>
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-fullscreen.webmanifest b/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-fullscreen.webmanifest
deleted file mode 100644
index c43856c8..0000000
--- a/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-fullscreen.webmanifest
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-    "display_override": [ "fullscreen" ]
-}
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-minimal-ui-manual.tentative.html b/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-minimal-ui-manual.tentative.html
index 1b69b2d..5b9d6397 100644
--- a/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-minimal-ui-manual.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-minimal-ui-manual.tentative.html
@@ -2,7 +2,8 @@
 <title>Test "minimal-ui" in display-override member + media feature</title>
 <link rel="help" href="https://w3c.github.io/manifest/#dom-displaymodetype-minimal-ui" />
 <link rel="help" href="https://w3c.github.io/manifest/#the-display-mode-media-feature" />
-<link rel="manifest" href="display-override-member-media-feature-minimal-ui.webmanifest" />
+<link rel="manifest" href="resources/display-override-member-media-feature-minimal-ui.webmanifest" />
+<script src="resources/display-override-member-media-feature-manual.js"></script>
 <meta name="viewport" content="width=device-width, initial-scale=1">
 <h1>Test "minimal-ui" in display-override member + media feature</h1>
 <style>
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-minimal-ui.webmanifest b/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-minimal-ui.webmanifest
deleted file mode 100644
index 68fcc76..0000000
--- a/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-minimal-ui.webmanifest
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-    "display_override": [ "minimal-ui" ]
-}
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-service-worker.js b/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-service-worker.js
new file mode 100644
index 0000000..eec0d997
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-service-worker.js
@@ -0,0 +1,56 @@
+// Some user agents only offer app installation if there is a SW and it handles
+// offline requests.
+
+const cacheVersion = "1.2";
+const CACHE_NAME = `cache-v${cacheVersion}`;
+
+// The resources cached by this service worker.
+const resources = [
+  "display-override-member-media-feature-browser-manual.tentative.html",
+  "display-override-member-media-feature-fullscreen-manual.tentative.html",
+  "display-override-member-media-feature-minimal-ui-manual.tentative.html",
+  "display-override-member-media-feature-standalone-manual.tentative.html",
+  "display-override-member-media-feature-standalone-overrides-browser-manual.tentative.html",
+  "display-override-member-media-feature-service-worker.js",
+  "resources/display-override-member-media-feature-manual.js",
+  "resources/icon.png",
+];
+
+// Load all resources for this service worker.
+const precache = async () => {
+  const cache = await caches.open(CACHE_NAME);
+  await cache.addAll(resources);
+};
+
+// Get a resource from the cache.
+const fromCache = async request => {
+  const cache = await caches.open(CACHE_NAME);
+  return await cache.match(request.url);
+};
+
+// Attempt to get resources from the network first, fallback to the cache if we're
+// offline.
+const networkFallbackToCache = async request => {
+  try {
+    const response = await fetch(request);
+    if (response.ok) return response;
+  } catch (err) {}
+  return await fromCache(request);
+};
+
+// When we have a new service worker, update the caches and swap immediately.
+self.addEventListener("install", e => {
+  e.waitUntil(precache().then(() => self.skipWaiting()));
+});
+
+// Claim existing clients.
+self.addEventListener("activate", e => {
+  e.waitUntil(self.clients.claim());
+});
+
+// When a resource need to be fetched, check whether it is
+// contained in the cache and return the cached version, otherwise
+// get it from the network.
+self.addEventListener("fetch", e => {
+  e.respondWith(networkFallbackToCache(e.request));
+});
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-standalone-manual.tentative.html b/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-standalone-manual.tentative.html
index bccba1f..db1ed38 100644
--- a/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-standalone-manual.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-standalone-manual.tentative.html
@@ -2,7 +2,8 @@
 <title>Test "standalone" in display-override member + media feature</title>
 <link rel="help" href="https://w3c.github.io/manifest/#the-display-mode-media-feature" />
 <link rel="help" href="https://w3c.github.io/manifest/#dom-displaymodetype-standalone" />
-<link rel="manifest" href="display-override-member-media-feature-standalone.webmanifest" />
+<link rel="manifest" href="resources/display-override-member-media-feature-standalone.webmanifest" />
+<script src="resources/display-override-member-media-feature-manual.js"></script>
 <meta name="viewport" content="width=device-width, initial-scale=1">
 <h1>Test "standalone" in display-override member + media feature</h1>
 <style>
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-standalone-overrides-browser-manual.tentative.html b/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-standalone-overrides-browser-manual.tentative.html
index e91ea4e3..d42feb3 100644
--- a/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-standalone-overrides-browser-manual.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-standalone-overrides-browser-manual.tentative.html
@@ -4,7 +4,8 @@
 <link rel="help" href="https://w3c.github.io/manifest/#the-display-mode-media-feature" />
 <link rel="help" href="https://w3c.github.io/manifest/#dom-displaymodetype-browser" />
 <link rel="help" href="https://w3c.github.io/manifest/#dom-displaymodetype-standalone" />
-<link rel="manifest" href="display-override-member-media-feature-standalone-overrides-browser.webmanifest" />
+<link rel="manifest" href="resources/display-override-member-media-feature-standalone-overrides-browser.webmanifest" />
+<script src="resources/display-override-member-media-feature-manual.js"></script>
 <meta name="viewport" content="width=device-width, initial-scale=1">
 <h1>Test "standalone" in display-override member + "browser" in display member + media feature</h1>
 <style>
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-standalone-overrides-browser.webmanifest b/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-standalone-overrides-browser.webmanifest
deleted file mode 100644
index 0f33e3b8..0000000
--- a/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-standalone-overrides-browser.webmanifest
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-    "display": "browser",
-    "display_override": [ "standalone" ]
-}
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-standalone.webmanifest b/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-standalone.webmanifest
deleted file mode 100644
index c6f4b66b..0000000
--- a/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-standalone.webmanifest
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-    "display_override": [ "standalone" ]
-}
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/resources/display-override-member-media-feature-browser.webmanifest b/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/resources/display-override-member-media-feature-browser.webmanifest
new file mode 100644
index 0000000..a384f6f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/resources/display-override-member-media-feature-browser.webmanifest
@@ -0,0 +1,11 @@
+{
+    "name": "Display override member media feature WPT",
+    "icons": [
+        {
+            "src": "icon.png",
+            "sizes": "192x192"
+        }
+    ],
+    "start_url": "../display-override-member-media-feature-browser-manual.tentative.html",
+    "display_override": [ "browser" ]
+}
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-browser.webmanifest.headers b/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/resources/display-override-member-media-feature-browser.webmanifest.headers
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-browser.webmanifest.headers
rename to third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/resources/display-override-member-media-feature-browser.webmanifest.headers
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/resources/display-override-member-media-feature-fullscreen.webmanifest b/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/resources/display-override-member-media-feature-fullscreen.webmanifest
new file mode 100644
index 0000000..70cad0a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/resources/display-override-member-media-feature-fullscreen.webmanifest
@@ -0,0 +1,11 @@
+{
+    "name": "Display override member media feature WPT",
+    "icons": [
+        {
+            "src": "icon.png",
+            "sizes": "192x192"
+        }
+    ],
+    "start_url": "../display-override-member-media-feature-fullscreen-manual.tentative.html",
+    "display_override": [ "fullscreen" ]
+}
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-fullscreen.webmanifest.headers b/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/resources/display-override-member-media-feature-fullscreen.webmanifest.headers
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-fullscreen.webmanifest.headers
rename to third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/resources/display-override-member-media-feature-fullscreen.webmanifest.headers
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/resources/display-override-member-media-feature-manual.js b/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/resources/display-override-member-media-feature-manual.js
new file mode 100644
index 0000000..eca3502
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/resources/display-override-member-media-feature-manual.js
@@ -0,0 +1,4 @@
+if ('serviceWorker' in navigator) {
+  navigator.serviceWorker.register(
+    'display-override-member-media-feature-service-worker.js');
+}
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/resources/display-override-member-media-feature-minimal-ui.webmanifest b/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/resources/display-override-member-media-feature-minimal-ui.webmanifest
new file mode 100644
index 0000000..474f5852
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/resources/display-override-member-media-feature-minimal-ui.webmanifest
@@ -0,0 +1,11 @@
+{
+    "name": "Display override member media feature WPT",
+    "icons": [
+        {
+            "src": "icon.png",
+            "sizes": "192x192"
+        }
+    ],
+    "start_url": "../display-override-member-media-feature-browser-manual.tentative.html",
+    "display_override": [ "minimal-ui" ]
+}
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-minimal-ui.webmanifest.headers b/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/resources/display-override-member-media-feature-minimal-ui.webmanifest.headers
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-minimal-ui.webmanifest.headers
rename to third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/resources/display-override-member-media-feature-minimal-ui.webmanifest.headers
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/resources/display-override-member-media-feature-standalone-overrides-browser.webmanifest b/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/resources/display-override-member-media-feature-standalone-overrides-browser.webmanifest
new file mode 100644
index 0000000..dcdd293a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/resources/display-override-member-media-feature-standalone-overrides-browser.webmanifest
@@ -0,0 +1,12 @@
+{
+    "name": "Display override member media feature WPT",
+    "icons": [
+        {
+            "src": "icon.png",
+            "sizes": "192x192"
+        }
+    ],
+    "start_url": "../display-override-member-media-feature-browser-manual.tentative.html",
+    "display": "browser",
+    "display_override": [ "standalone" ]
+}
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-standalone-overrides-browser.webmanifest.headers b/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/resources/display-override-member-media-feature-standalone-overrides-browser.webmanifest.headers
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-standalone-overrides-browser.webmanifest.headers
rename to third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/resources/display-override-member-media-feature-standalone-overrides-browser.webmanifest.headers
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/resources/display-override-member-media-feature-standalone.webmanifest b/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/resources/display-override-member-media-feature-standalone.webmanifest
new file mode 100644
index 0000000..dfd6b77
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/resources/display-override-member-media-feature-standalone.webmanifest
@@ -0,0 +1,11 @@
+{
+    "name": "Display override member media feature WPT",
+    "icons": [
+        {
+            "src": "icon.png",
+            "sizes": "192x192"
+        }
+    ],
+    "start_url": "../display-override-member-media-feature-browser-manual.tentative.html",
+    "display_override": [ "standalone" ]
+}
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-standalone.webmanifest.headers b/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/resources/display-override-member-media-feature-standalone.webmanifest.headers
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/display-override-member-media-feature-standalone.webmanifest.headers
rename to third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/resources/display-override-member-media-feature-standalone.webmanifest.headers
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/resources/icon.png b/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/resources/icon.png
new file mode 100644
index 0000000..637cc8d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/appmanifest/display-override-member/resources/icon.png
Binary files differ
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/css-transforms-transformlist.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/css-transforms-transformlist.html
index b0f159a4..1551554 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/css-transforms-transformlist.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/css-transforms-transformlist.html
@@ -6,7 +6,7 @@
     <link rel="author" title="Rik Cabanier" href="mailto:cabanier@adobe.com">
     <link rel="help" href="http://www.w3.org/TR/css-transforms-1/#transform-attribute-dom">
     <link rel="match" href="reference/css-transforms-transformlist-ref.html">
-    <meta name="assert" content="This test verifies that the CSS transform ends up in the list of SVG transforms">
+    <meta name="assert" content="This test verifies that the CSS transform does not end up in the list of SVG transforms">
     <style type="text/css">
 
        #rect {
@@ -25,7 +25,7 @@
 	window.addEventListener('load', function(){
 		var r = document.getElementById("rect");
 		var result = document.getElementById("result");
-		if(r.transform.baseVal.length>0)
+		if (r.transform.baseVal.length == 0)
 			result.style.backgroundColor = "rgb(0, 255, 0)";
 
 		document.getElementById("svgelement").style.display="none";
@@ -35,7 +35,7 @@
 <body>
     <p>The test passes if there is a green square and no red.</p>
     <svg id="svgelement">
-		<rect id="rect" width="100" height="100"></rect>
+		<rect id="rect" style="transform: translate(20px, 20px)" width="100" height="100"></rect>
 	</svg>
     <div id="result"></div>
 </body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/reference/skew-test1-ref.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/reference/skew-test1-ref.html
index d69df1ba..394de2b 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/reference/skew-test1-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/reference/skew-test1-ref.html
@@ -26,8 +26,8 @@
     <h4>
       There should be a green block on the page.
     </h4>
-    <svg xmlns="http://www.w3.org/2000/svg" version="1.1">
-      <polygon points="0,0 150,55 235,205 88,150" style="fill:lime"/>
+    <svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="300" height="300">
+      <polygon points="0,0 150,54.595535 236.602540,204.595535 86.602540,150" style="fill:lime"/>
     </svg>
 
 </body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/reference/transform-translateX-001-ref.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/reference/transform-translatex-006-ref.html
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/css/css-transforms/reference/transform-translateX-001-ref.html
rename to third_party/blink/web_tests/external/wpt/css/css-transforms/reference/transform-translatex-006-ref.html
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/reference/ttwf-reftest-transform-translatex-001.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/reference/ttwf-reftest-transform-translatex-001.html
index 0e45406..68ab44a 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/reference/ttwf-reftest-transform-translatex-001.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/reference/ttwf-reftest-transform-translatex-001.html
@@ -7,7 +7,7 @@
         .greenSquare {
             position: absolute;
             top: 100px;
-            left: 1000px;
+            left: 150px;
             width: 100px;
             height: 100px;
             background: green;
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/skew-test1.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/skew-test1.html
index 1f36667..b7baf13 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/skew-test1.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/skew-test1.html
@@ -40,10 +40,10 @@
     Test 1 - Tests with degrees on block elements.
     </h3>
     <h4>
-      There should be a green block on the page
+      There should be a green block on the page.
     </h4>
-    <svg xmlns="http://www.w3.org/2000/svg" version="1.1">
-      <polygon points="0,0 150,55 235,205 88,150" style="fill:red"/>
+    <svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="300" height="300">
+      <polygon points="1,1 149,56 235,203 88,149" style="fill:red"/>
     </svg>
 
   <div class="skew_div">
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-030.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-030.html
index a3c96c2..3faaee6 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-030.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-030.html
@@ -8,7 +8,7 @@
   <link rel="help" href="http://www.w3.org/TR/css-transforms-1/#svg-user-coordinate-space">
   <link rel="match" href="reference/svg-origin-relative-length-ref.html">
   <meta name="flags" content="svg">
-  <meta name="assert" content="The initial point of origin gets translated to 225,75 since 'right 75' is relative to the bounding box of the object.">
+  <meta name="assert" content="The initial point of origin gets translated to 225,75 since 'right 0' is relative to the bounding box of the object.">
   <style type="text/css">
     svg {
       width: 200px;
@@ -30,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(75,75)" transform-origin="right 75"/>
+     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(75,75)" transform-origin="right 0"/>
    </svg>
  </body>
 </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-036.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-036.html
index ac39e86f..2ed45e7cf 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-036.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-036.html
@@ -8,7 +8,7 @@
   <link rel="help" href="http://www.w3.org/TR/css-transforms-1/#svg-user-coordinate-space">
   <link rel="match" href="reference/svg-origin-relative-length-ref.html">
   <meta name="flags" content="svg">
-  <meta name="assert" content="The initial point of origin gets translated to 75,75 since 'left 75' is relative to the bounding box of the object.">
+  <meta name="assert" content="The initial point of origin gets translated to 75,75 since 'left 0' is relative to the bounding box of the object.">
   <style type="text/css">
     svg {
       width: 200px;
@@ -30,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(-75,-75)" transform-origin="left 75"/>
+     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(-75,-75)" transform-origin="left 0"/>
    </svg>
  </body>
 </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-044.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-044.html
index 92944c7..e8352af 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-044.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-044.html
@@ -8,7 +8,7 @@
   <link rel="help" href="http://www.w3.org/TR/css-transforms-1/#svg-user-coordinate-space">
   <link rel="match" href="reference/svg-origin-relative-length-ref.html">
   <meta name="flags" content="svg">
-  <meta name="assert" content="The initial point of origin gets translated to 0,150 since '0 center' is relative to the bounding box of the object.">
+  <meta name="assert" content="The initial point of origin gets translated to 0,150 since '-75 center' is relative to the bounding box of the object.">
   <style type="text/css">
     svg {
       width: 200px;
@@ -30,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(-225,-75)" transform-origin="0 center"/>
+     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(-225,-75)" transform-origin="-75 center"/>
    </svg>
  </body>
 </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-046.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-046.html
index 29072ba..fd7d9764 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-046.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-046.html
@@ -8,7 +8,7 @@
   <link rel="help" href="http://www.w3.org/TR/css-transforms-1/#svg-user-coordinate-space">
   <link rel="match" href="reference/svg-origin-relative-length-ref.html">
   <meta name="flags" content="svg">
-  <meta name="assert" content="The initial point of origin gets translated to 150,0 since 'center 0' is relative to the bounding box of the object.">
+  <meta name="assert" content="The initial point of origin gets translated to 150,0 since 'center -75' is relative to the bounding box of the object.">
   <style type="text/css">
     svg {
       width: 200px;
@@ -30,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(75,-75)" transform-origin="center 0"/>
+     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(75,-75)" transform-origin="center -75"/>
    </svg>
  </body>
 </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-rotate-006.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-rotate-006.html
index eddfb7a..678d0cb 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-rotate-006.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-rotate-006.html
@@ -13,7 +13,7 @@
     <link rel="mismatch" href="transform-rotate-001-notref.html">
     <style>
       div {
-        transform: rotate(45deg) rotate(0.125turn);
+        transform: rotate(45deg) rotate(1turn);
         width: 100px;
         height: 100px;
       }
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-scale-001.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-scale-001.html
index 9a67ecf..d046cc3 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-scale-001.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-scale-001.html
@@ -10,6 +10,10 @@
     box by a factor of one-half.'>
     <link rel="match" href="transform-scale-ref.html">
     <style>
+      body {
+        margin: 0;
+      }
+
       div {
         background: green;
         width: 100px;
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-scale-002.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-scale-002.html
index 2c4742a..dad5f25 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-scale-002.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-scale-002.html
@@ -10,6 +10,10 @@
     by a factor of one-half.'>
     <link rel="match" href="transform-scale-ref.html">
     <style>
+      body {
+        margin: 0;
+      }
+
       div {
         background: green;
         width: 100px;
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-scale-ref.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-scale-ref.html
index 79a70df..4bcfab0 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-scale-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-scale-ref.html
@@ -5,6 +5,10 @@
     <link rel="author" title="Clint Talbert" href="mailto:ctalbert@mozilla.com">
     <link rel="author" title="Aryeh Gregor" href="mailto:ayg@aryeh.name">
     <style>
+      body {
+        margin: 0;
+      }
+
       div {
         background: green;
         width: 50px;
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-scaley-001.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-scaley-001.html
index 833ccbd2..e226156 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-scaley-001.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-scaley-001.html
@@ -10,6 +10,10 @@
     box's width by a factor of one-half.">
     <link rel="match" href="transform-scaley-ref.html">
     <style>
+      body {
+        margin: 0;
+      }
+
       div {
         background: green;
         width: 100px;
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-scaley-ref.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-scaley-ref.html
index 706b796..b84ede4 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-scaley-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-scaley-ref.html
@@ -5,6 +5,10 @@
     <link rel="author" title="Clint Talbert" href="mailto:ctalbert@mozilla.com">
     <link rel="author" title="Aryeh Gregor" href="mailto:ayg@aryeh.name">
     <style>
+      body {
+        margin: 0;
+      }
+
       div {
         background: green;
         width: 100px;
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-table-008.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-table-008.html
index ba5a782..24a96d44 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-table-008.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-table-008.html
@@ -26,6 +26,7 @@
       body > div > div > div > div > div {
         transform: rotateX(90deg);
       }
+    </style>
   </head>
   <body>
     <p>Nothing should appear except this sentence.</p>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-translatex-006.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-translatex-006.html
index e01d0f7..fd6f46f 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-translatex-006.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-translatex-006.html
@@ -5,7 +5,7 @@
     <link rel="author" title="Serena Wales" href="mailto:serena@codeforamerica.org">
     <link rel="help" href="http://www.w3.org/TR/css-transforms-1/#transform-property">
     <link rel="help" href="http://www.w3.org/TR/css-transforms-1/#two-d-transform-functions">
-    <link rel="match" href="transform-translatex-ref.html">
+    <link rel="match" href="reference/transform-translatex-006-ref.html">
     <meta name="assert" content="This tests that translateX(50px) translates a box by 50 pixels in the X direction.">
     <style type="text/css">
         /* Positioned container allows for the self-describing statement to still
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/ttwf-transform-translatex-001.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/ttwf-transform-translatex-001.html
index f85d3324..bef05c0 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/ttwf-transform-translatex-001.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/ttwf-transform-translatex-001.html
@@ -13,13 +13,13 @@
             left: 0px;
             width: 100px;
             height: 100px;
-            transform: translateX(100px);
+            transform: translateX(150px);
             background: green;
          }
         .redSquare {
             position: absolute;
             top: 100px;
-            left: 100px;
+            left: 150px;
             width: 98px;
             height: 98px;
             background: red;
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/acos-asin-atan-atan2-computed-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-values/acos-asin-atan-atan2-computed-expected.txt
new file mode 100644
index 0000000..2ba4cc7
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-values/acos-asin-atan-atan2-computed-expected.txt
@@ -0,0 +1,44 @@
+This is a testharness.js-based test.
+FAIL acos(1) should be used-value-equivalent to 0deg assert_equals: rotate(acos(1)) and rotate(0deg) serialize to the same thing in used values. expected "matrix(1, 0, 0, 1, 0, 0)" but got "none"
+FAIL atan(0) should be used-value-equivalent to 0deg assert_equals: rotate(atan(0)) and rotate(0deg) serialize to the same thing in used values. expected "matrix(1, 0, 0, 1, 0, 0)" but got "none"
+FAIL asin(0) should be used-value-equivalent to 0deg assert_equals: rotate(asin(0)) and rotate(0deg) serialize to the same thing in used values. expected "matrix(1, 0, 0, 1, 0, 0)" but got "none"
+FAIL atan2(0,0) should be used-value-equivalent to 0deg assert_equals: rotate(atan2(0,0)) and rotate(0deg) serialize to the same thing in used values. expected "matrix(1, 0, 0, 1, 0, 0)" but got "none"
+FAIL calc(asin(sin(pi/2))) should be used-value-equivalent to 90deg Cannot read properties of undefined (reading 'split')
+FAIL calc(acos(cos(pi - 3.14159265358979323846))) should be used-value-equivalent to 0deg Cannot read properties of undefined (reading 'split')
+FAIL calc(atan(e - 2.7182818284590452354) ) should be used-value-equivalent to 0deg Cannot read properties of undefined (reading 'split')
+FAIL calc(asin(sin(30deg + 1.0471967rad ) )) should be used-value-equivalent to 90deg Cannot read properties of undefined (reading 'split')
+PASS calc(acos(cos(30deg - 0.523599rad ) )) should be used-value-equivalent to 0deg
+FAIL calc(asin(sin(3.14159 / 2 + 1 - 1) )) should be used-value-equivalent to 90deg Cannot read properties of undefined (reading 'split')
+FAIL calc(asin(sin(100grad) )) should be used-value-equivalent to 90deg Cannot read properties of undefined (reading 'split')
+FAIL calc(acos(cos(0 / 2 + 1 - 1) )) should be used-value-equivalent to 0deg Cannot read properties of undefined (reading 'split')
+FAIL calc(atan(tan(30deg + 0.261799rad ) )) should be used-value-equivalent to 45deg Cannot read properties of undefined (reading 'split')
+FAIL calc(atan(tan(0.7853975rad ) )) should be used-value-equivalent to 45deg Cannot read properties of undefined (reading 'split')
+FAIL calc(atan(tan(3.14159 / 4 + 1 - 1) )) should be used-value-equivalent to 45deg Cannot read properties of undefined (reading 'split')
+FAIL calc(asin(sin(0.25turn)) ) should be used-value-equivalent to 90deg Cannot read properties of undefined (reading 'split')
+FAIL calc(atan2(0,1)) should be used-value-equivalent to 0deg Cannot read properties of undefined (reading 'split')
+FAIL calc(atan2(0,-1)) should be used-value-equivalent to -180deg Cannot read properties of undefined (reading 'split')
+FAIL calc(atan2(1,-1)) should be used-value-equivalent to 135deg Cannot read properties of undefined (reading 'split')
+FAIL calc(atan2(-1,1)) should be used-value-equivalent to -45deg Cannot read properties of undefined (reading 'split')
+FAIL calc(cos(sin(acos(cos(pi))))) should be used-value-equivalent to 1 Cannot read properties of undefined (reading 'split')
+FAIL calc(sin(atan(tan(pi/2)))) should be used-value-equivalent to 1 Cannot read properties of undefined (reading 'split')
+FAIL atan2(1px, -1px) should be used-value-equivalent to 135deg Cannot read properties of undefined (reading 'split')
+FAIL atan2(1cm, -1cm) should be used-value-equivalent to 135deg Cannot read properties of undefined (reading 'split')
+FAIL atan2(1mm, -1mm) should be used-value-equivalent to 135deg Cannot read properties of undefined (reading 'split')
+FAIL atan2(1Q, -1Q) should be used-value-equivalent to 135deg Cannot read properties of undefined (reading 'split')
+FAIL atan2(1in, -1in) should be used-value-equivalent to 135deg Cannot read properties of undefined (reading 'split')
+FAIL atan2(1pc, -1pc) should be used-value-equivalent to 135deg Cannot read properties of undefined (reading 'split')
+FAIL atan2(1pt, -1pt) should be used-value-equivalent to 135deg Cannot read properties of undefined (reading 'split')
+FAIL atan2(1em, -1em) should be used-value-equivalent to 135deg Cannot read properties of undefined (reading 'split')
+FAIL atan2(1ex, -1ex) should be used-value-equivalent to 135deg Cannot read properties of undefined (reading 'split')
+FAIL atan2(1ch, -1ch) should be used-value-equivalent to 135deg Cannot read properties of undefined (reading 'split')
+FAIL atan2(1rem, -1rem) should be used-value-equivalent to 135deg Cannot read properties of undefined (reading 'split')
+FAIL atan2(1vh, -1vh) should be used-value-equivalent to 135deg Cannot read properties of undefined (reading 'split')
+FAIL atan2(1vw, -1vw) should be used-value-equivalent to 135deg Cannot read properties of undefined (reading 'split')
+FAIL atan2(1deg, -1deg) should be used-value-equivalent to 135deg Cannot read properties of undefined (reading 'split')
+FAIL atan2(1grad, -1grad) should be used-value-equivalent to 135deg Cannot read properties of undefined (reading 'split')
+FAIL atan2(1turn, -1turn) should be used-value-equivalent to 135deg Cannot read properties of undefined (reading 'split')
+FAIL atan2(1rad, -1rad) should be used-value-equivalent to 135deg Cannot read properties of undefined (reading 'split')
+FAIL atan2(1s, -1s) should be used-value-equivalent to 135deg Cannot read properties of undefined (reading 'split')
+FAIL atan2(1ms, -1ms) should be used-value-equivalent to 135deg Cannot read properties of undefined (reading 'split')
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/acos-asin-atan-atan2-computed.html b/third_party/blink/web_tests/external/wpt/css/css-values/acos-asin-atan-atan2-computed.html
new file mode 100644
index 0000000..6fc8bdf
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-values/acos-asin-atan-atan2-computed.html
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<link rel="help" href="https://drafts.csswg.org/css-values-4/#comp-func">
+<link rel="help" href="https://drafts.csswg.org/css-values-4/#numbers">
+<link rel="help" href="https://drafts.csswg.org/css-values-4/#calc-type-checking">
+<link rel="author" title="Apple Inc">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../support/numeric-testcommon.js"></script>
+<div id="target"></div>
+<script>
+function test_angle_equals(value, expected) {
+  test_math_used(`rotate(${value})`, `rotate(${expected})`,
+	{prop:'transform', base:'none',
+     msg: `${value} should be used-value-equivalent to ${expected}`});
+}
+// Simple tests
+test_angle_equals('acos(1)', '0deg');
+test_angle_equals('atan(0)', '0deg');
+test_angle_equals('asin(0)', '0deg');
+test_angle_equals('atan2(0,0)', '0deg');
+
+// Test pi
+test_math_used('calc(asin(sin(pi/2)))', '90deg', {type:'angle', approx:0.1});
+test_math_used('calc(acos(cos(pi - 3.14159265358979323846)))', '0deg', {type:'angle', approx:0.1});
+
+// Test e
+test_math_used('calc(atan(e - 2.7182818284590452354) )', '0deg', {type:'angle', approx:0.1});
+
+// General calculations
+test_math_used('calc(asin(sin(30deg + 1.0471967rad ) ))', '90deg', {type:'angle', approx:0.1});
+test_math_used('calc(acos(cos(30deg - 0.523599rad ) ))', '0deg'), {type:'angle', approx:0.1};
+test_math_used('calc(asin(sin(3.14159 / 2 + 1 - 1) ))', '90deg', {type:'angle', approx:0.1});
+test_math_used('calc(asin(sin(100grad) ))', '90deg', {type:'angle', approx:0.1});
+test_math_used('calc(acos(cos(0 / 2 + 1 - 1) ))', '0deg', {type:'angle', approx:0.1});
+test_math_used('calc(atan(tan(30deg + 0.261799rad ) ))', '45deg', {type:'angle', approx:0.1});
+test_math_used('calc(atan(tan(0.7853975rad ) ))', '45deg', {type:'angle', approx:0.1});
+test_math_used('calc(atan(tan(3.14159 / 4 + 1 - 1) ))', '45deg', {type:'angle', approx:0.1});
+test_math_used('calc(asin(sin(0.25turn)) )', '90deg', {type:'angle', approx:0.1});
+test_math_used('calc(atan2(0,1))', '0deg', {type:'angle', approx:0.1});
+test_math_used('calc(atan2(0,-1))', '-180deg', {type:'angle', approx:0.1});
+test_math_used('calc(atan2(1,-1))', '135deg', {type:'angle', approx:0.1});
+test_math_used('calc(atan2(-1,1))', '-45deg', {type:'angle', approx:0.1});
+
+// Test nesting
+test_math_used('calc(cos(sin(acos(cos(pi)))))', '1', {type:'number', approx:0.1});
+test_math_used('calc(sin(atan(tan(pi/2))))', '1', {type:'number', approx:0.1});
+
+// Test types for atan2
+test_math_used('atan2(1px, -1px)', '135deg', {type:'angle', approx:0.1});
+test_math_used('atan2(1cm, -1cm)', '135deg', {type:'angle', approx:0.1});
+test_math_used('atan2(1mm, -1mm)', '135deg', {type:'angle', approx:0.1});
+test_math_used('atan2(1Q, -1Q)', '135deg', {type:'angle', approx:0.1});
+test_math_used('atan2(1in, -1in)', '135deg', {type:'angle', approx:0.1});
+test_math_used('atan2(1pc, -1pc)', '135deg', {type:'angle', approx:0.1});
+test_math_used('atan2(1pt, -1pt)', '135deg', {type:'angle', approx:0.1});
+test_math_used('atan2(1em, -1em)', '135deg', {type:'angle', approx:0.1});
+test_math_used('atan2(1ex, -1ex)', '135deg', {type:'angle', approx:0.1});
+test_math_used('atan2(1ch, -1ch)', '135deg', {type:'angle', approx:0.1});
+test_math_used('atan2(1rem, -1rem)', '135deg', {type:'angle', approx:0.1});
+test_math_used('atan2(1vh, -1vh)', '135deg', {type:'angle', approx:0.1});
+test_math_used('atan2(1vw, -1vw)', '135deg', {type:'angle', approx:0.1});
+test_math_used('atan2(1deg, -1deg)', '135deg', {type:'angle', approx:0.1});
+test_math_used('atan2(1grad, -1grad)', '135deg', {type:'angle', approx:0.1});
+test_math_used('atan2(1turn, -1turn)', '135deg', {type:'angle', approx:0.1});
+test_math_used('atan2(1rad, -1rad)', '135deg', {type:'angle', approx:0.1});
+test_math_used('atan2(1s, -1s)', '135deg', {type:'angle', approx:0.1});
+test_math_used('atan2(1ms, -1ms)', '135deg', {type:'angle', approx:0.1});
+
+</script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/acos-asin-atan-atan2-invalid.html b/third_party/blink/web_tests/external/wpt/css/css-values/acos-asin-atan-atan2-invalid.html
new file mode 100644
index 0000000..af997c1
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-values/acos-asin-atan-atan2-invalid.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<link rel="help" href="https://drafts.csswg.org/css-values-4/#comp-func">
+<link rel="help" href="https://drafts.csswg.org/css-values-4/#angles">
+<link rel="help" href="https://drafts.csswg.org/css-values-4/#calc-type-checking">
+<link rel="author" title="Apple Inc">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../support/parsing-testcommon.js"></script>
+<script>
+function test_invalid_angle(value) {
+  test_invalid_value('transform', `rotate(${value})`);
+}
+
+// Syntax checking
+test_invalid_angle('asin()');
+test_invalid_angle('asin( )');
+test_invalid_angle('asin(,)');
+test_invalid_angle('asin(1dag)');
+test_invalid_angle('asin(1deg, )');
+test_invalid_angle('asin(, 1deg)');
+test_invalid_angle('asin(1deg + )');
+test_invalid_angle('asin(1deg - )');
+test_invalid_angle('asin(1deg * )');
+test_invalid_angle('asin(1deg / )');
+test_invalid_angle('asin(1deg 2deg)');
+test_invalid_angle('asin(1deg, , 2deg)');
+test_invalid_angle('acos()');
+test_invalid_angle('acos( )');
+test_invalid_angle('acos(,)');
+test_invalid_angle('acos(1dag)');
+test_invalid_angle('acos(1deg, )');
+test_invalid_angle('acos(, 1deg)');
+test_invalid_angle('acos(1deg + )');
+test_invalid_angle('acos(1deg - )');
+test_invalid_angle('acos(1deg * )');
+test_invalid_angle('acos(1deg / )');
+test_invalid_angle('acos(1deg 2deg)');
+test_invalid_angle('acos(1deg, , 2deg)');
+test_invalid_angle('atan()');
+test_invalid_angle('atan( )');
+test_invalid_angle('atan(,)');
+test_invalid_angle('atan(1dag)');
+test_invalid_angle('atan(1deg, )');
+test_invalid_angle('atan(, 1deg)');
+test_invalid_angle('atan(1deg + )');
+test_invalid_angle('atan(1deg - )');
+test_invalid_angle('atan(1deg * )');
+test_invalid_angle('atan(1deg / )');
+test_invalid_angle('atan(1deg 2deg)');
+test_invalid_angle('atan(1deg, , 2deg)');
+test_invalid_angle('asin(90px)');
+test_invalid_angle('asin(30deg + 1.0471967rad, 0)');
+test_invalid_angle('acos( 0 ,)');
+test_invalid_angle('acos( () 30deg - 0.523599rad )');
+test_invalid_angle('atan(45deg )');
+test_invalid_angle('atan(30deg, + 0.261799rad)');
+test_invalid_angle('atan2()');
+test_invalid_angle('atan2( )');
+test_invalid_angle('atan2(,)');
+test_invalid_angle('atan2(1dag)');
+test_invalid_angle('atan2(1deg, )');
+test_invalid_angle('atan2(, 1deg)');
+test_invalid_angle('atan2(1deg + )');
+test_invalid_angle('atan2(1deg - )');
+test_invalid_angle('atan2(1deg * )');
+test_invalid_angle('atan2(1deg / )');
+test_invalid_angle('atan2(1deg 2deg)');
+test_invalid_angle('atan2(1deg, , 2deg)');
+test_invalid_angle('atan2(90px)');
+test_invalid_angle('atan2(30deg + 1.0471967rad, 0)');
+test_invalid_angle('atan2( 0 ,)');
+test_invalid_angle('atan2( () 30deg - 0.523599rad )');
+test_invalid_angle('atan2(45deg )');
+test_invalid_angle('atan2(30deg, + 0.261799rad)');
+</script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/acos-asin-atan-atan2-serialize-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-values/acos-asin-atan-atan2-serialize-expected.txt
new file mode 100644
index 0000000..e87d77c6e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-values/acos-asin-atan-atan2-serialize-expected.txt
@@ -0,0 +1,11 @@
+This is a testharness.js-based test.
+FAIL 'rotate(acos(0))' as a specified value should serialize as 'rotate(calc(90deg))'. assert_not_equals: 'rotate(acos(0))' should be valid in transform. got disallowed value ""
+FAIL 'rotate(acos(0))' as a computed value should serialize as 'matrix(6.12323e-17, 1, -1, 6.12323e-17, 0, 0)'. assert_equals: 'rotate(acos(0))' and 'matrix(6.12323e-17, 1, -1, 6.12323e-17, 0, 0)' should serialize the same in computed values. expected "matrix(6.12323e-17, 1, -1, 6.12323e-17, 0, 0)" but got "none"
+FAIL 'rotate(asin(1))' as a specified value should serialize as 'rotate(calc(90deg))'. assert_not_equals: 'rotate(asin(1))' should be valid in transform. got disallowed value ""
+FAIL 'rotate(asin(1))' as a computed value should serialize as 'matrix(6.12323e-17, 1, -1, 6.12323e-17, 0, 0)'. assert_equals: 'rotate(asin(1))' and 'matrix(6.12323e-17, 1, -1, 6.12323e-17, 0, 0)' should serialize the same in computed values. expected "matrix(6.12323e-17, 1, -1, 6.12323e-17, 0, 0)" but got "none"
+FAIL 'rotate(calc(acos(pi - pi)))' as a specified value should serialize as 'rotate(calc(90deg))'. assert_not_equals: 'rotate(calc(acos(pi - pi)))' should be valid in transform. got disallowed value ""
+FAIL 'rotate(calc(acos(pi - pi)))' as a computed value should serialize as 'matrix(6.12323e-17, 1, -1, 6.12323e-17, 0, 0)'. assert_equals: 'rotate(calc(acos(pi - pi)))' and 'matrix(6.12323e-17, 1, -1, 6.12323e-17, 0, 0)' should serialize the same in computed values. expected "matrix(6.12323e-17, 1, -1, 6.12323e-17, 0, 0)" but got "none"
+FAIL 'rotate(calc(asin(pi - pi + 1)))' as a specified value should serialize as 'rotate(calc(90deg))'. assert_not_equals: 'rotate(calc(asin(pi - pi + 1)))' should be valid in transform. got disallowed value ""
+FAIL 'rotate(calc(asin(pi - pi + 1)))' as a computed value should serialize as 'matrix(6.12323e-17, 1, -1, 6.12323e-17, 0, 0)'. assert_equals: 'rotate(calc(asin(pi - pi + 1)))' and 'matrix(6.12323e-17, 1, -1, 6.12323e-17, 0, 0)' should serialize the same in computed values. expected "matrix(6.12323e-17, 1, -1, 6.12323e-17, 0, 0)" but got "none"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/acos-asin-atan-atan2-serialize.html b/third_party/blink/web_tests/external/wpt/css/css-values/acos-asin-atan-atan2-serialize.html
new file mode 100644
index 0000000..637667f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-values/acos-asin-atan-atan2-serialize.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<link rel="help" href="https://drafts.csswg.org/css-values-4/#comp-func">
+<link rel="help" href="https://drafts.csswg.org/css-values-4/#angles">
+<link rel="help" href="https://drafts.csswg.org/css-values-4/#calc-serialize">
+<link rel="author" title="Apple Inc">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../support/serialize-testcommon.js"></script>
+<div id=target></div>
+<script>
+function test_serialization(t,s,c,u, {prop="transform"}={}) {
+	t = `rotate(${t})`;
+    test_specified_serialization(prop, t, `rotate(${s})`);
+    test_computed_serialization(prop, t, c);
+    if(u) test_used_serialization(prop, t, u);
+}
+
+// Browsers aren't perfectly interoperable about how a 90deg rotation is serialized,
+// but that's not the focus of this test,
+// so just capture *whatever* the browser does and expect that.
+const rotateMatrix = (()=>{
+    const el = document.querySelector("#target");
+    el.style.transform = "rotate(90deg)";
+    const ret = getComputedStyle(el).transform;
+    el.removeAttribute('style');
+    return ret;
+})();
+
+test_serialization(
+    'acos(0)',
+    'calc(90deg)',
+    rotateMatrix);
+test_serialization(
+    'asin(1)',
+    'calc(90deg)',
+    rotateMatrix);
+
+test_serialization(
+    'calc(acos(pi - pi))',
+    'calc(90deg)',
+    rotateMatrix);
+test_serialization(
+    'calc(asin(pi - pi + 1))',
+    'calc(90deg)',
+    rotateMatrix);
+</script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/support/numeric-testcommon.js b/third_party/blink/web_tests/external/wpt/css/support/numeric-testcommon.js
index f5ba088..534d379 100644
--- a/third_party/blink/web_tests/external/wpt/css/support/numeric-testcommon.js
+++ b/third_party/blink/web_tests/external/wpt/css/support/numeric-testcommon.js
@@ -184,7 +184,7 @@
         testEl.style[prop] = e;
         const expectedValue = getComputedStyle(testEl)[prop];
         assert_not_equals(expectedValue, '', `${expectedString} isn't valid in '${prop}'; got the default value instead.`)
-        if(approx && type == "number"){
+        if(approx && (type == "number" || type == "angle")){
             let parsedUsed = usedValue.split('(')[1].split(')')[0].split(',').map(parseFloat);
             let parsedExpected = expectedValue.split('(')[1].split(')')[0].split(',').map(parseFloat);
             assert_array_approx_equals(parsedUsed, parsedExpected, approx, `${testString} and ${expectedString} ${approx} serialize to the same thing in ${stage} values.`);
@@ -192,4 +192,4 @@
             assert_equals(usedValue, expectedValue, `${testString} and ${expectedString} serialize to the same thing in ${stage} values.`);
         }
     }, msg || `${testString} should be ${stage}-value-equivalent to ${expectedString}`);
-}
+}
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-selectmenu-element/selectmenu-parts-structure.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-selectmenu-element/selectmenu-parts-structure.tentative.html
index 62f9b29e..9f7a8ac 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-selectmenu-element/selectmenu-parts-structure.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-selectmenu-element/selectmenu-parts-structure.tentative.html
@@ -97,6 +97,19 @@
   </div>
 </selectmenu>
 
+<selectmenu id="selectMenu10">
+  <div slot="button" id="selectMenu10-div">Test 10</div>
+  <option>one</option>
+  <option id="selectMenu10-option2">two</option>
+</selectmenu>
+
+<selectmenu id="selectMenu11">
+  <popup slot="listbox" part="listbox">
+    <option>one</option>
+  </popup>
+  <div slot="button" part="listbox" id="selectMenu11-button">Test</div>
+</selectmenu>
+
 <script>
   function clickOn(element) {
     const actions = new test_driver.Actions();
@@ -260,4 +273,38 @@
     assert_false(selectMenu.open);
     assert_equals(selectMenu.value, "four", "New options should get controller code after listbox switch");
     }, "Ensure that option controller code is updated when listbox changes");
+
+  promise_test(async () => {
+    const selectMenu = document.getElementById("selectMenu10");
+    const selectMenu10Div = document.getElementById("selectMenu10-div");
+
+    await clickOn(selectMenu10Div);
+    assert_false(selectMenu.open, "Controller code not applied due to part attribute missing");
+    selectMenu10Div.part = "button";
+    await clickOn(selectMenu10Div);
+    assert_true(selectMenu.open);
+
+    const option2 = document.getElementById("selectMenu10-option2");
+    await clickOn(option2);
+    assert_equals(selectMenu.value, "two");
+
+    selectMenu10Div.slot = "";
+    await clickOn(selectMenu);
+    assert_true(selectMenu.open, "Default button part should be used");
+    selectMenu10Div.part = "option";
+    await clickOn(selectMenu10Div);
+    assert_equals(selectMenu.value, "Test 10");
+  }, "Ensure that controller code is applied after updating the slot attribute");
+
+  promise_test(async () => {
+    const selectMenu = document.getElementById("selectMenu11");
+    const selectMenu11Button= document.getElementById("selectMenu11-button");
+
+    await clickOn(selectMenu11Button);
+    assert_false(selectMenu.open, "Controller code not applied due to part attribute not being button");
+    selectMenu11Button.remove();
+
+    await clickOn(selectMenu);
+    assert_true(selectMenu.open, "Default button part should be used");
+  }, "Ensure that controller code is applied when slot and part attributes are different");
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-selectmenu-element/selectmenu-popup.tentative-expected.txt b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-selectmenu-element/selectmenu-popup.tentative-expected.txt
deleted file mode 100644
index 056f1af..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-selectmenu-element/selectmenu-popup.tentative-expected.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-This is a testharness.js-based test.
-PASS Opening the popup and clicking an option should change the selectmenu's value
-PASS With custom button and popup: opening the popup and clicking an option should change the selectmenu's value
-FAIL Clicking a popup with no listbox part does nothing assert_equals: expected false but got true
-PASS Clicking a popup with a listbox that was removed does nothing
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-selectmenu-element/selectmenu-popup.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-selectmenu-element/selectmenu-popup.tentative.html
index 00c8441..a43761d3 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-selectmenu-element/selectmenu-popup.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-selectmenu-element/selectmenu-popup.tentative.html
@@ -90,7 +90,6 @@
     const selectMenu2 = document.getElementById("selectMenu2");
     await clickOn(selectMenu2);
     assert_equals(selectMenu2.value, "");
-    // TODO(crbug.com/1234899) Fails because listbox pointer isn't cleared when default listbox is swapped out due to initial <slot> replacement
     assert_equals(selectMenu2.open, false);
   }, "Clicking a popup with no listbox part does nothing");
 
diff --git a/third_party/blink/web_tests/external/wpt/infrastructure/server/webtransport-h3.sub.any-expected.txt b/third_party/blink/web_tests/external/wpt/infrastructure/server/webtransport-h3.sub.any-expected.txt
index c581aa01..6b34f70 100644
--- a/third_party/blink/web_tests/external/wpt/infrastructure/server/webtransport-h3.sub.any-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/infrastructure/server/webtransport-h3.sub.any-expected.txt
@@ -1,4 +1,4 @@
 This is a testharness.js-based test.
-FAIL WebTransport server should be running and should handle a bidirectional stream promise_test: Unhandled rejection with value: object "WebTransportError: Connection lost."
+FAIL WebTransport server should be running and should handle a bidirectional stream promise_test: Unhandled rejection with value: object "WebTransportError: Opening handshake failed."
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/infrastructure/server/webtransport-h3.sub.any.serviceworker-expected.txt b/third_party/blink/web_tests/external/wpt/infrastructure/server/webtransport-h3.sub.any.serviceworker-expected.txt
index c581aa01..6b34f70 100644
--- a/third_party/blink/web_tests/external/wpt/infrastructure/server/webtransport-h3.sub.any.serviceworker-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/infrastructure/server/webtransport-h3.sub.any.serviceworker-expected.txt
@@ -1,4 +1,4 @@
 This is a testharness.js-based test.
-FAIL WebTransport server should be running and should handle a bidirectional stream promise_test: Unhandled rejection with value: object "WebTransportError: Connection lost."
+FAIL WebTransport server should be running and should handle a bidirectional stream promise_test: Unhandled rejection with value: object "WebTransportError: Opening handshake failed."
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/infrastructure/server/webtransport-h3.sub.any.sharedworker-expected.txt b/third_party/blink/web_tests/external/wpt/infrastructure/server/webtransport-h3.sub.any.sharedworker-expected.txt
index c581aa01..6b34f70 100644
--- a/third_party/blink/web_tests/external/wpt/infrastructure/server/webtransport-h3.sub.any.sharedworker-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/infrastructure/server/webtransport-h3.sub.any.sharedworker-expected.txt
@@ -1,4 +1,4 @@
 This is a testharness.js-based test.
-FAIL WebTransport server should be running and should handle a bidirectional stream promise_test: Unhandled rejection with value: object "WebTransportError: Connection lost."
+FAIL WebTransport server should be running and should handle a bidirectional stream promise_test: Unhandled rejection with value: object "WebTransportError: Opening handshake failed."
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/infrastructure/server/webtransport-h3.sub.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/infrastructure/server/webtransport-h3.sub.any.worker-expected.txt
index c581aa01..6b34f70 100644
--- a/third_party/blink/web_tests/external/wpt/infrastructure/server/webtransport-h3.sub.any.worker-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/infrastructure/server/webtransport-h3.sub.any.worker-expected.txt
@@ -1,4 +1,4 @@
 This is a testharness.js-based test.
-FAIL WebTransport server should be running and should handle a bidirectional stream promise_test: Unhandled rejection with value: object "WebTransportError: Connection lost."
+FAIL WebTransport server should be running and should handle a bidirectional stream promise_test: Unhandled rejection with value: object "WebTransportError: Opening handshake failed."
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/inspector-protocol/emulation/set-css-media-feature-override-expected.txt b/third_party/blink/web_tests/inspector-protocol/emulation/set-css-media-feature-override-expected.txt
index 1e21354..69327c9 100644
--- a/third_party/blink/web_tests/inspector-protocol/emulation/set-css-media-feature-override-expected.txt
+++ b/third_party/blink/web_tests/inspector-protocol/emulation/set-css-media-feature-override-expected.txt
@@ -1,52 +1,52 @@
 Tests that CSS media features can be overridden.
 matchMedia("(prefers-color-scheme: __invalid__)").matches: false
-matchMedia("(prefers-color-scheme: __invalid__)").matches applied: 3px x 2px, rgb(255, 0, 0)
+matchMedia("(prefers-color-scheme: __invalid__)").matches applied: 3px x 2px, rgb(0, 0, 255)
 matchMedia("(prefers-color-scheme: no-preference)").matches: false
-matchMedia("(prefers-color-scheme: no-preference)").matches applied: 3px x 2px, rgb(255, 0, 0)
+matchMedia("(prefers-color-scheme: no-preference)").matches applied: 3px x 2px, rgb(0, 0, 255)
 matchMedia("(prefers-color-scheme: light)").matches: true
-matchMedia("(prefers-color-scheme: light)").matches applied: 3px x 2px, rgb(255, 0, 0)
+matchMedia("(prefers-color-scheme: light)").matches applied: 3px x 2px, rgb(0, 0, 255)
 matchMedia("(prefers-color-scheme: dark)").matches: true
-matchMedia("(prefers-color-scheme: dark)").matches applied: 4px x 2px, rgb(255, 0, 0)
+matchMedia("(prefers-color-scheme: dark)").matches applied: 4px x 2px, rgb(0, 0, 255)
 matchMedia("(prefers-color-scheme: __invalid__)").matches: false
-matchMedia("(prefers-color-scheme: __invalid__)").matches applied: 3px x 2px, rgb(255, 0, 0)
+matchMedia("(prefers-color-scheme: __invalid__)").matches applied: 3px x 2px, rgb(0, 0, 255)
 matchMedia("(prefers-reduced-motion: __invalid__)").matches: false
-matchMedia("(prefers-reduced-motion: __invalid__)").matches applied: 3px x 2px, rgb(255, 0, 0)
+matchMedia("(prefers-reduced-motion: __invalid__)").matches applied: 3px x 2px, rgb(0, 0, 255)
 matchMedia("(prefers-reduced-motion: no-preference)").matches: true
-matchMedia("(prefers-reduced-motion: no-preference)").matches applied: 3px x 2px, rgb(255, 0, 0)
+matchMedia("(prefers-reduced-motion: no-preference)").matches applied: 3px x 2px, rgb(0, 0, 255)
 matchMedia("(prefers-reduced-motion: reduce)").matches: true
-matchMedia("(prefers-reduced-motion: reduce)").matches applied: 3px x 3px, rgb(255, 0, 0)
+matchMedia("(prefers-reduced-motion: reduce)").matches applied: 3px x 3px, rgb(0, 0, 255)
 matchMedia("(prefers-reduced-motion: __invalid__)").matches: false
-matchMedia("(prefers-reduced-motion: __invalid__)").matches applied: 3px x 2px, rgb(255, 0, 0)
+matchMedia("(prefers-reduced-motion: __invalid__)").matches applied: 3px x 2px, rgb(0, 0, 255)
 matchMedia("(prefers-contrast: __invalid__)").matches: false
-matchMedia("(prefers-contrast: __invalid__)").matches applied: 3px x 2px, rgb(255, 0, 0)
-matchMedia("(prefers-contrast: no-preference)").matches: false
-matchMedia("(prefers-contrast: no-preference)").matches applied: 3px x 2px, rgb(255, 0, 0)
-matchMedia("(prefers-contrast: more)").matches: false
-matchMedia("(prefers-contrast: more)").matches applied: 3px x 2px, rgb(255, 0, 0)
-matchMedia("(prefers-contrast: less)").matches: false
-matchMedia("(prefers-contrast: less)").matches applied: 3px x 2px, rgb(255, 0, 0)
-matchMedia("(prefers-contrast: custom)").matches: false
-matchMedia("(prefers-contrast: custom)").matches applied: 3px x 2px, rgb(255, 0, 0)
+matchMedia("(prefers-contrast: __invalid__)").matches applied: 3px x 2px, rgb(0, 0, 255)
+matchMedia("(prefers-contrast: no-preference)").matches: true
+matchMedia("(prefers-contrast: no-preference)").matches applied: 3px x 2px, rgb(0, 0, 255)
+matchMedia("(prefers-contrast: more)").matches: true
+matchMedia("(prefers-contrast: more)").matches applied: 3px x 2px, rgb(0, 128, 0)
+matchMedia("(prefers-contrast: less)").matches: true
+matchMedia("(prefers-contrast: less)").matches applied: 3px x 2px, rgb(255, 255, 0)
+matchMedia("(prefers-contrast: custom)").matches: true
+matchMedia("(prefers-contrast: custom)").matches applied: 3px x 2px, rgb(255, 165, 0)
 matchMedia("(prefers-contrast: __invalid__)").matches: false
-matchMedia("(prefers-contrast: __invalid__)").matches applied: 3px x 2px, rgb(255, 0, 0)
+matchMedia("(prefers-contrast: __invalid__)").matches applied: 3px x 2px, rgb(0, 0, 255)
 matchMedia("(color-gamut: __invalid__)").matches: false
-matchMedia("(color-gamut: __invalid__)").matches applied: 3px x 2px, rgb(255, 0, 0)
+matchMedia("(color-gamut: __invalid__)").matches applied: 3px x 2px, rgb(0, 0, 255)
 matchMedia("(color-gamut: p3)").matches: true
-matchMedia("(color-gamut: p3)").matches applied: 6px x 6px, rgb(255, 0, 0)
+matchMedia("(color-gamut: p3)").matches applied: 6px x 6px, rgb(0, 0, 255)
 matchMedia("(color-gamut: rec2020)").matches: true
-matchMedia("(color-gamut: rec2020)").matches applied: 7px x 7px, rgb(255, 0, 0)
+matchMedia("(color-gamut: rec2020)").matches applied: 7px x 7px, rgb(0, 0, 255)
 matchMedia("(color-gamut: __invalid__)").matches: false
-matchMedia("(color-gamut: __invalid__)").matches applied: 3px x 2px, rgb(255, 0, 0)
+matchMedia("(color-gamut: __invalid__)").matches applied: 3px x 2px, rgb(0, 0, 255)
 matchMedia("(forced-colors: __invalid__)").matches: false
-matchMedia("(forced-colors: __invalid__)").matches applied: 3px x 2px, rgb(255, 0, 0)
+matchMedia("(forced-colors: __invalid__)").matches applied: 3px x 2px, rgb(0, 0, 255)
 matchMedia("(forced-colors: active)").matches: true
-matchMedia("(forced-colors: active)").matches applied: 3px x 2px, rgb(255, 0, 0)
+matchMedia("(forced-colors: active)").matches applied: 3px x 2px, rgb(0, 0, 255)
 matchMedia("(forced-colors: none)").matches: true
-matchMedia("(forced-colors: none)").matches applied: 3px x 2px, rgb(255, 0, 0)
+matchMedia("(forced-colors: none)").matches applied: 3px x 2px, rgb(0, 0, 255)
 matchMedia("(forced-colors: __invalid__)").matches: false
-matchMedia("(forced-colors: __invalid__)").matches applied: 3px x 2px, rgb(255, 0, 0)
+matchMedia("(forced-colors: __invalid__)").matches applied: 3px x 2px, rgb(0, 0, 255)
 matchMedia("(prefers-color-scheme: dark) and (prefers-reduced-motion: reduce)").matches: true
-matchMedia("(prefers-color-scheme: dark) and (prefers-reduced-motion: reduce)").matches applied: 999px x 999px, rgb(255, 0, 0)
+matchMedia("(prefers-color-scheme: dark) and (prefers-reduced-motion: reduce)").matches applied: 999px x 999px, rgb(0, 0, 255)
 matchMedia("(prefers-color-scheme: __invalid__)").matches: false
-matchMedia("(prefers-color-scheme: __invalid__)").matches applied: 3px x 2px, rgb(255, 0, 0)
+matchMedia("(prefers-color-scheme: __invalid__)").matches applied: 3px x 2px, rgb(0, 0, 255)
 
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/wpt_internal/mediastream/mediastreamtrackprocessor-transfer-to-worker-expected.txt b/third_party/blink/web_tests/platform/mac-mac11-arm64/wpt_internal/mediastream/mediastreamtrackprocessor-transfer-to-worker-expected.txt
new file mode 100644
index 0000000..d6d7a697
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/wpt_internal/mediastream/mediastreamtrackprocessor-transfer-to-worker-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+FAIL Test we can transfer a Video MediaStreamTrackProcessor stream assert_true: Stream is ended before we could read enough frames expected true got false
+PASS Test we can transfer an Audio MediaStreamTrackProcessor stream
+Harness: the test ran to completion.
+
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index c8383d66..8bb2ef8 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -14200,6 +14200,7 @@
   <int value="81" label="Formfill metadata"/>
   <int value="82" label="Federated identity active session"/>
   <int value="83" label="Auto-darken web content"/>
+  <int value="84" label="Request desktop site"/>
 </enum>
 
 <enum name="ContentTypeParseableResult">
@@ -40988,13 +40989,16 @@
 
 <enum name="HistoryClustersInitialState">
   <summary>
-    The intial state that describes how an interaction with the HistoryClusters,
-    or Journeys, UI was started.
+    The initial state that describes how an interaction with the
+    HistoryClusters, or Journeys, UI was started.
   </summary>
   <int value="0" label="Unknown"/>
   <int value="1" label="kDirectNavigation">
     The UI was reached via direct navigation, not through any dedicated surface.
   </int>
+  <int value="2" label="kIndirectNavigation">
+    The UI was reached via indirect navigation, e.g. a link.
+  </int>
 </enum>
 
 <enum name="HistoryFaviconsRecoveryEnum">
@@ -89680,6 +89684,11 @@
   <int value="3" label="Not connected (Wake On WiFi disabled)"/>
 </enum>
 
+<enum name="WiFiCQMNotificationType">
+  <int value="0" label="Packet loss"/>
+  <int value="1" label="Beacon loss"/>
+</enum>
+
 <enum name="WiFiPCIStatus">
   <int value="0" label="(Bad status) NIC not detected in lspci"/>
   <int value="1"
@@ -90902,6 +90911,9 @@
 </enum>
 
 <enum name="WindowsServiceStatus">
+  <obsolete>
+    Removed in M96.
+  </obsolete>
   <int value="0" label="Unknown"/>
   <int value="1" label="Not Found"/>
   <int value="2" label="Found"/>
diff --git a/tools/metrics/histograms/metadata/input/histograms.xml b/tools/metrics/histograms/metadata/input/histograms.xml
index f9ccbff..d9c27e2 100644
--- a/tools/metrics/histograms/metadata/input/histograms.xml
+++ b/tools/metrics/histograms/metadata/input/histograms.xml
@@ -26,10 +26,13 @@
   <owner>myy@chromium.org</owner>
   <owner>essential-inputs-team@google.com</owner>
   <summary>
-    The number of active input methods. Recorded when the user logs in to Chrome
-    OS or each cold start of Chrome on Android. The active input methods are
-    selected by user in the language settings page on Chrome OS and in system
-    language settings on Android.
+    The number of enabled input methods. Recorded when the user logs in to
+    Chrome OS or each cold start of Chrome on Android. The enabled input methods
+    are selected by user in the language settings page on Chrome OS and in
+    system language settings on Android. NOTE: 'Active' in the metric name is a
+    legacy misnomer; 'active' should refer to just the single current aka.
+    activated input method that is one of the enabled input methods whose total
+    count is being tracked by this metric.
   </summary>
 </histogram>
 
diff --git a/tools/metrics/histograms/metadata/network/histograms.xml b/tools/metrics/histograms/metadata/network/histograms.xml
index 9437d48..ea74e0d3 100644
--- a/tools/metrics/histograms/metadata/network/histograms.xml
+++ b/tools/metrics/histograms/metadata/network/histograms.xml
@@ -1903,6 +1903,18 @@
   </summary>
 </histogram>
 
+<histogram name="Network.Shill.WiFi.CQMNotification"
+    enum="WiFiCQMNotificationType" expires_after="2022-09-01">
+  <owner>kuabhs@chromium.org</owner>
+  <owner>cros-network-metrics@google.com</owner>
+  <summary>
+    Chrome OS Wifi Connection Quality Monitor(CQM) Notifications metric. This is
+    emitted when any packet or beacon loss is observed for signal strength
+    greater than -80 dBm. This metric is rate-limited such that it is never
+    emitted more than once every 6 minutes.
+  </summary>
+</histogram>
+
 <histogram name="Network.Shill.WiFi.DarkResumeUnmatchedScanResultsReceived"
     enum="DarkResumeUnmatchedScanResultReceived" expires_after="2021-12-01">
   <owner>briannorris@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/scanning/histograms.xml b/tools/metrics/histograms/metadata/scanning/histograms.xml
index a5205c9..16871ae 100644
--- a/tools/metrics/histograms/metadata/scanning/histograms.xml
+++ b/tools/metrics/histograms/metadata/scanning/histograms.xml
@@ -49,6 +49,18 @@
   </summary>
 </histogram>
 
+<histogram name="Scanning.MultiPageScan.SessionDuration" units="ms"
+    expires_after="2022-09-03">
+  <owner>gavinwill@chromium.org</owner>
+  <owner>cros-peripherals@google.com</owner>
+  <summary>
+    Records the time between a user starting the first scan in a multi-page scan
+    session to the time the user clicks save to end the session. This does not
+    record when a multi-page scan session ends prematurely without the PDF being
+    saved.
+  </summary>
+</histogram>
+
 <histogram name="Scanning.MultiPageScan.ToolbarAction"
     enum="ScanMultiPageToolbarAction" expires_after="2022-09-03">
   <owner>gavinwill@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/uma/histograms.xml b/tools/metrics/histograms/metadata/uma/histograms.xml
index 3adcb10..212ce46b 100644
--- a/tools/metrics/histograms/metadata/uma/histograms.xml
+++ b/tools/metrics/histograms/metadata/uma/histograms.xml
@@ -226,6 +226,19 @@
   <summary>The source of the client id when its creation is forced.</summary>
 </histogram>
 
+<histogram name="UMA.DataValidation.LogNormal" units="random values"
+    expires_after="2021-11-14">
+  <owner>sweilun@chromium.org</owner>
+  <owner>src/base/metrics/OWNERS</owner>
+  <summary>
+    This is logged with a value of random value drawn from an artificial log
+    normal distribution in every log and used for data validation. The mean and
+    standard deviation parameters of the log normal distribution are controlled
+    by artificial A/B experiments so that we can assess the accuracy and power
+    of data from field trials.
+  </summary>
+</histogram>
+
 <histogram name="UMA.EnrollmentStatus" enum="EnrollmentStatus"
     expires_after="never">
 <!-- expires-never: used internally for filtering -->
diff --git a/tools/metrics/histograms/metadata/windows/histograms.xml b/tools/metrics/histograms/metadata/windows/histograms.xml
index 0fd3397..da7da31 100644
--- a/tools/metrics/histograms/metadata/windows/histograms.xml
+++ b/tools/metrics/histograms/metadata/windows/histograms.xml
@@ -381,6 +381,9 @@
 
 <histogram name="Windows.ServiceStatus.SSP" units="WindowsServiceStatus"
     expires_after="2021-12-12">
+  <obsolete>
+    Removed in M96.
+  </obsolete>
   <owner>wfh@chromium.org</owner>
   <owner>ajgo@chromium.org</owner>
   <summary>
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py
index 347cc6c4..237e8cc 100755
--- a/tools/perf/core/perf_data_generator.py
+++ b/tools/perf/core/perf_data_generator.py
@@ -358,36 +358,57 @@
                 'name': 'resource_sizes_monochrome_minimal_apks',
                 'isolate': 'resource_sizes_monochrome_minimal_apks',
                 'type': TEST_TYPES.GENERIC,
+                'resultdb': {
+                    'has_native_resultdb_integration': True,
+                },
             },
             {
                 'name': 'resource_sizes_monochrome_public_minimal_apks',
                 'isolate': 'resource_sizes_monochrome_public_minimal_apks',
                 'type': TEST_TYPES.GENERIC,
+                'resultdb': {
+                    'has_native_resultdb_integration': True,
+                },
             },
             {
                 'name': 'resource_sizes_chrome_modern_minimal_apks',
                 'isolate': 'resource_sizes_chrome_modern_minimal_apks',
                 'type': TEST_TYPES.GENERIC,
+                'resultdb': {
+                    'has_native_resultdb_integration': True,
+                },
             },
             {
                 'name': 'resource_sizes_chrome_modern_public_minimal_apks',
                 'isolate': 'resource_sizes_chrome_modern_public_minimal_apks',
                 'type': TEST_TYPES.GENERIC,
+                'resultdb': {
+                    'has_native_resultdb_integration': True,
+                },
             },
             {
                 'name': 'resource_sizes_trichrome_google',
                 'isolate': 'resource_sizes_trichrome_google',
                 'type': TEST_TYPES.GENERIC,
+                'resultdb': {
+                    'has_native_resultdb_integration': True,
+                },
             },
             {
                 'name': 'resource_sizes_system_webview_bundle',
                 'isolate': 'resource_sizes_system_webview_bundle',
                 'type': TEST_TYPES.GENERIC,
+                'resultdb': {
+                    'has_native_resultdb_integration': True,
+                },
             },
             {
                 'name': 'resource_sizes_system_webview_google_bundle',
                 'isolate': 'resource_sizes_system_webview_google_bundle',
                 'type': TEST_TYPES.GENERIC,
+                'resultdb': {
+                    'has_native_resultdb_integration': True,
+                },
             },
         ],
         'dimension': {
@@ -418,41 +439,65 @@
                 'name': 'resource_sizes_monochrome_minimal_apks',
                 'isolate': 'resource_sizes_monochrome_minimal_apks',
                 'type': TEST_TYPES.GENERIC,
+                'resultdb': {
+                    'has_native_resultdb_integration': True,
+                },
             },
             {
                 'name': 'resource_sizes_monochrome_public_minimal_apks',
                 'isolate': 'resource_sizes_monochrome_public_minimal_apks',
                 'type': TEST_TYPES.GENERIC,
+                'resultdb': {
+                    'has_native_resultdb_integration': True,
+                },
             },
             {
                 'name': 'resource_sizes_chrome_modern_minimal_apks',
                 'isolate': 'resource_sizes_chrome_modern_minimal_apks',
                 'type': TEST_TYPES.GENERIC,
+                'resultdb': {
+                    'has_native_resultdb_integration': True,
+                },
             },
             {
                 'name': 'resource_sizes_chrome_modern_public_minimal_apks',
                 'isolate': 'resource_sizes_chrome_modern_public_minimal_apks',
                 'type': TEST_TYPES.GENERIC,
+                'resultdb': {
+                    'has_native_resultdb_integration': True,
+                },
             },
             {
                 'name': 'resource_sizes_trichrome',
                 'isolate': 'resource_sizes_trichrome',
                 'type': TEST_TYPES.GENERIC,
+                'resultdb': {
+                    'has_native_resultdb_integration': True,
+                },
             },
             {
                 'name': 'resource_sizes_trichrome_google',
                 'isolate': 'resource_sizes_trichrome_google',
                 'type': TEST_TYPES.GENERIC,
+                'resultdb': {
+                    'has_native_resultdb_integration': True,
+                },
             },
             {
                 'name': 'resource_sizes_system_webview_bundle',
                 'isolate': 'resource_sizes_system_webview_bundle',
                 'type': TEST_TYPES.GENERIC,
+                'resultdb': {
+                    'has_native_resultdb_integration': True,
+                },
             },
             {
                 'name': 'resource_sizes_system_webview_google_bundle',
                 'isolate': 'resource_sizes_system_webview_google_bundle',
                 'type': TEST_TYPES.GENERIC,
+                'resultdb': {
+                    'has_native_resultdb_integration': True,
+                },
             },
         ],
         'dimension': {
@@ -969,6 +1014,9 @@
                 'name': 'resource_sizes_chromecast',
                 'isolate': 'resource_sizes_chromecast',
                 'type': TEST_TYPES.GENERIC,
+                'resultdb': {
+                    'has_native_resultdb_integration': True,
+                },
             },
         ],
         'dimension': {
@@ -986,6 +1034,9 @@
                 'name': 'resource_sizes_lacros_chrome',
                 'isolate': 'resource_sizes_lacros_chrome',
                 'type': TEST_TYPES.GENERIC,
+                'resultdb': {
+                    'has_native_resultdb_integration': True,
+                },
             },
         ],
         'dimension': {
diff --git a/ui/android/java/src/org/chromium/ui/modaldialog/ModalDialogProperties.java b/ui/android/java/src/org/chromium/ui/modaldialog/ModalDialogProperties.java
index 2406e74..d453d146 100644
--- a/ui/android/java/src/org/chromium/ui/modaldialog/ModalDialogProperties.java
+++ b/ui/android/java/src/org/chromium/ui/modaldialog/ModalDialogProperties.java
@@ -49,11 +49,13 @@
         void onDismiss(PropertyModel model, @DialogDismissalCause int dismissalCause);
     }
 
-    @IntDef({ModalDialogProperties.ButtonType.POSITIVE, ModalDialogProperties.ButtonType.NEGATIVE})
+    @IntDef({ModalDialogProperties.ButtonType.POSITIVE, ModalDialogProperties.ButtonType.NEGATIVE,
+            ModalDialogProperties.ButtonType.TITLE_ICON})
     @Retention(RetentionPolicy.SOURCE)
     public @interface ButtonType {
         int POSITIVE = 0;
         int NEGATIVE = 1;
+        int TITLE_ICON = 2;
     }
 
     /**
diff --git a/ui/base/dragdrop/os_exchange_data_provider_non_backed.cc b/ui/base/dragdrop/os_exchange_data_provider_non_backed.cc
index e803c765..3c10f2d 100644
--- a/ui/base/dragdrop/os_exchange_data_provider_non_backed.cc
+++ b/ui/base/dragdrop/os_exchange_data_provider_non_backed.cc
@@ -28,25 +28,7 @@
 std::unique_ptr<OSExchangeDataProvider> OSExchangeDataProviderNonBacked::Clone()
     const {
   auto clone = std::make_unique<OSExchangeDataProviderNonBacked>();
-
-  clone->formats_ = formats_;
-  clone->string_ = string_;
-  clone->url_ = url_;
-  clone->title_ = title_;
-  clone->filenames_ = filenames_;
-  clone->pickle_data_ = pickle_data_;
-  // We skip copying the drag images.
-  clone->file_contents_filename_ = file_contents_filename_;
-  clone->file_contents_ = file_contents_;
-  clone->html_ = html_;
-  clone->base_url_ = base_url_;
-  clone->source_ =
-      source_ ? std::make_unique<ui::DataTransferEndpoint>(*source_.get())
-              : nullptr;
-#if !BUILDFLAG(IS_CHROMEOS_ASH)
-  clone->originated_from_renderer_ = originated_from_renderer_;
-#endif
-
+  CopyData(clone.get());
   return clone;
 }
 
@@ -280,4 +262,25 @@
   return source_.get();
 }
 
+void OSExchangeDataProviderNonBacked::CopyData(
+    OSExchangeDataProviderNonBacked* provider) const {
+  DCHECK(provider);
+  provider->formats_ = formats_;
+  provider->string_ = string_;
+  provider->url_ = url_;
+  provider->title_ = title_;
+  provider->filenames_ = filenames_;
+  provider->pickle_data_ = pickle_data_;
+  provider->file_contents_filename_ = file_contents_filename_;
+  provider->file_contents_ = file_contents_;
+  provider->html_ = html_;
+  provider->base_url_ = base_url_;
+  provider->source_ =
+      source_ ? std::make_unique<DataTransferEndpoint>(*source_.get())
+              : nullptr;
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
+  provider->originated_from_renderer_ = originated_from_renderer_;
+#endif
+}
+
 }  // namespace ui
diff --git a/ui/base/dragdrop/os_exchange_data_provider_non_backed.h b/ui/base/dragdrop/os_exchange_data_provider_non_backed.h
index 3d3f8a98..3fcf989 100644
--- a/ui/base/dragdrop/os_exchange_data_provider_non_backed.h
+++ b/ui/base/dragdrop/os_exchange_data_provider_non_backed.h
@@ -79,6 +79,9 @@
   DataTransferEndpoint* GetSource() const override;
 
  protected:
+  // Copy internal data into |provider| object.
+  void CopyData(OSExchangeDataProviderNonBacked* provider) const;
+
   const std::map<ClipboardFormatType, base::Pickle>& pickle_data() const {
     return pickle_data_;
   }
diff --git a/ui/base/ime/ash/input_method_manager.h b/ui/base/ime/ash/input_method_manager.h
index e07b456..e24e4d3 100644
--- a/ui/base/ime/ash/input_method_manager.h
+++ b/ui/base/ime/ash/input_method_manager.h
@@ -119,7 +119,7 @@
 
     // Called when the IME menu is activated or deactivated.
     virtual void ImeMenuActivationChanged(bool is_active) = 0;
-    // Called when the current input method or the list of active input method
+    // Called when the current input method or the list of enabled input method
     // IDs is changed.
     virtual void ImeMenuListChanged() = 0;
     // Called when the input.ime.setMenuItems or input.ime.updateMenuItems API
@@ -146,9 +146,9 @@
     virtual void RemoveInputMethodExtension(
         const std::string& extension_id) = 0;
 
-    // Changes the current input method to |input_method_id|. If
-    // |input_method_id|
-    // is not active, switch to the first one in the active input method list.
+    // Changes the current (active) input method to |input_method_id|. If
+    // |input_method_id| is not enabled, switch to the first one in the enabled
+    // input method list.
     virtual void ChangeInputMethod(const std::string& input_method_id,
                                    bool show_message) = 0;
 
@@ -157,10 +157,10 @@
     virtual void ChangeInputMethodToJpIme() = 0;
     virtual void ToggleInputMethodForJpIme() = 0;
 
-    // Adds one entry to the list of active input method IDs, and then starts or
-    // stops the system input method framework as needed.
+    // Adds one entry to the list of enabled input method IDs, and then starts
+    // or stops the system input method framework as needed.
     virtual bool EnableInputMethod(
-        const std::string& new_active_input_method_id) = 0;
+        const std::string& new_enabled_input_method_id) = 0;
 
     // Enables "login" keyboard layouts (e.g. US Qwerty, US Dvorak, French
     // Azerty) that are necessary for the |language_code| and then switches to
@@ -180,19 +180,19 @@
     // Returns a list of descriptors for all Input Method Extensions.
     virtual void GetInputMethodExtensions(InputMethodDescriptors* result) = 0;
 
-    // Returns the list of input methods we can select (i.e. active) including
+    // Returns the list of input methods we can select (i.e. enabled) including
     // extension input methods.
-    virtual std::unique_ptr<InputMethodDescriptors> GetActiveInputMethods()
+    virtual std::unique_ptr<InputMethodDescriptors> GetEnabledInputMethods()
         const = 0;
 
-    // Returns the list of input methods we can select (i.e. active) including
-    // extension input methods.
-    // The same as GetActiveInputMethods but returns reference to internal list.
-    virtual const std::vector<std::string>& GetActiveInputMethodIds() const = 0;
+    // Returns the list of input method IDs we can select (i.e. enabled)
+    // including extension input methods.
+    virtual const std::vector<std::string>& GetEnabledInputMethodIds()
+        const = 0;
 
-    // Returns the number of active input methods including extension input
+    // Returns the number of enabled input methods including extension input
     // methods.
-    virtual size_t GetNumActiveInputMethods() const = 0;
+    virtual size_t GetNumEnabledInputMethods() const = 0;
 
     // Returns the input method descriptor from the given input method id
     // string.
@@ -222,10 +222,10 @@
     // Gets the descriptor of the input method which is currently selected.
     virtual InputMethodDescriptor GetCurrentInputMethod() const = 0;
 
-    // Updates the list of active input method IDs, and then starts or stops the
-    // system input method framework as needed.
+    // Updates the list of enabled input method IDs, and then starts or stops
+    // the system input method framework as needed.
     virtual bool ReplaceEnabledInputMethods(
-        const std::vector<std::string>& new_active_input_method_ids) = 0;
+        const std::vector<std::string>& new_enabled_input_method_ids) = 0;
 
     // Sets the currently allowed input methods (e.g. due to policy). Invalid
     // input method ids are ignored. Passing an empty vector means that all
@@ -242,12 +242,12 @@
     virtual const std::vector<std::string>& GetAllowedInputMethods() = 0;
 
     // Methods related to custom input view of the input method.
-    // Enables custom input view of the active input method.
+    // Enables custom input view of the current (active) input method.
     virtual void EnableInputView() = 0;
-    // Disables custom input view of the active input method.
+    // Disables custom input view of the current (active) input method.
     // The fallback system input view will be used.
     virtual void DisableInputView() = 0;
-    // Returns the URL of the input view of the active input method.
+    // Returns the URL of the input view of the current (active) input method.
     virtual const GURL& GetInputViewUrl() const = 0;
 
     // Get the current UI screen type (e.g. login screen, lock screen, etc.).
@@ -344,8 +344,8 @@
   // is different from previous.
   virtual void MaybeNotifyImeMenuActivationChanged() = 0;
 
-  // Overrides active keyset with the given keyset if the active IME supports
-  // the given keyset.
+  // Overrides active keyset with the given keyset if the current (active) IME
+  // supports the given keyset.
   virtual void OverrideKeyboardKeyset(ImeKeyset keyset) = 0;
 
   // Enables or disables some advanced features, e.g. handwiring, voices input.
diff --git a/ui/base/ime/ash/mock_input_method_manager.cc b/ui/base/ime/ash/mock_input_method_manager.cc
index 010e9d56..e84b0c5 100644
--- a/ui/base/ime/ash/mock_input_method_manager.cc
+++ b/ui/base/ime/ash/mock_input_method_manager.cc
@@ -35,7 +35,7 @@
 void MockInputMethodManager::State::ToggleInputMethodForJpIme() {}
 
 bool MockInputMethodManager::State::EnableInputMethod(
-    const std::string& new_active_input_method_id) {
+    const std::string& new_enabled_input_method_id) {
   return true;
 }
 
@@ -49,13 +49,13 @@
     InputMethodDescriptors* result) {}
 
 std::unique_ptr<InputMethodDescriptors>
-MockInputMethodManager::State::GetActiveInputMethods() const {
+MockInputMethodManager::State::GetEnabledInputMethods() const {
   return nullptr;
 }
 
 const std::vector<std::string>&
-MockInputMethodManager::State::GetActiveInputMethodIds() const {
-  return active_input_method_ids;
+MockInputMethodManager::State::GetEnabledInputMethodIds() const {
+  return enabled_input_method_ids;
 }
 
 const InputMethodDescriptor*
@@ -64,8 +64,8 @@
   return nullptr;
 }
 
-size_t MockInputMethodManager::State::GetNumActiveInputMethods() const {
-  return active_input_method_ids.size();
+size_t MockInputMethodManager::State::GetNumEnabledInputMethods() const {
+  return enabled_input_method_ids.size();
 }
 
 void MockInputMethodManager::State::SetEnabledExtensionImes(
@@ -88,7 +88,7 @@
 }
 
 bool MockInputMethodManager::State::ReplaceEnabledInputMethods(
-    const std::vector<std::string>& new_active_input_method_ids) {
+    const std::vector<std::string>& new_enabled_input_method_ids) {
   return true;
 }
 
diff --git a/ui/base/ime/ash/mock_input_method_manager.h b/ui/base/ime/ash/mock_input_method_manager.h
index 3072da2..c45aaca 100644
--- a/ui/base/ime/ash/mock_input_method_manager.h
+++ b/ui/base/ime/ash/mock_input_method_manager.h
@@ -38,18 +38,18 @@
     void ChangeInputMethodToJpIme() override;
     void ToggleInputMethodForJpIme() override;
     bool EnableInputMethod(
-        const std::string& new_active_input_method_id) override;
+        const std::string& new_enabled_input_method_id) override;
     void EnableLoginLayouts(
         const std::string& language_code,
         const std::vector<std::string>& initial_layouts) override;
     void EnableLockScreenLayouts() override;
     void GetInputMethodExtensions(InputMethodDescriptors* result) override;
-    std::unique_ptr<InputMethodDescriptors> GetActiveInputMethods()
+    std::unique_ptr<InputMethodDescriptors> GetEnabledInputMethods()
         const override;
-    const std::vector<std::string>& GetActiveInputMethodIds() const override;
+    const std::vector<std::string>& GetEnabledInputMethodIds() const override;
     const InputMethodDescriptor* GetInputMethodFromId(
         const std::string& input_method_id) const override;
-    size_t GetNumActiveInputMethods() const override;
+    size_t GetNumEnabledInputMethods() const override;
     void SetEnabledExtensionImes(std::vector<std::string>* ids) override;
     void SetInputMethodLoginDefault() override;
     void SetInputMethodLoginDefaultFromVPD(const std::string& locale,
@@ -58,7 +58,7 @@
     void SwitchToLastUsedInputMethod() override;
     InputMethodDescriptor GetCurrentInputMethod() const override;
     bool ReplaceEnabledInputMethods(
-        const std::vector<std::string>& new_active_input_method_ids) override;
+        const std::vector<std::string>& new_enabled_input_method_ids) override;
     bool SetAllowedInputMethods(
         const std::vector<std::string>& new_allowed_input_method_ids,
         bool enable_allowed_input_methods) override;
@@ -69,8 +69,8 @@
     InputMethodManager::UIStyle GetUIStyle() const override;
     void SetUIStyle(InputMethodManager::UIStyle ui_style) override;
 
-    // The active input method ids cache (actually default only)
-    std::vector<std::string> active_input_method_ids;
+    // The enabled input method ids cache (actually default only)
+    std::vector<std::string> enabled_input_method_ids;
 
    protected:
     friend base::RefCounted<InputMethodManager::State>;
diff --git a/ui/file_manager/file_manager/foreground/css/file_manager.css b/ui/file_manager/file_manager/foreground/css/file_manager.css
index b29054d..ecc2b88 100644
--- a/ui/file_manager/file_manager/foreground/css/file_manager.css
+++ b/ui/file_manager/file_manager/foreground/css/file_manager.css
@@ -2294,14 +2294,12 @@
 }
 
 #share-menu cr-menu-item,
-#share-sub-menu cr-menu-item,
 #tasks-menu cr-menu-item:not(.change-default) {
   background-position: left 10px center;
   padding-inline-start: 32px;
 }
 
 html[dir='rtl'] #share-menu cr-menu-item,
-html[dir='rtl'] #share-sub-menu cr-menu-item,
 html[dir='rtl'] #tasks-menu cr-menu-item:not(.change-default) {
   background-position: right 10px center;
 }
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
index 5eb3f219..d012ea5 100644
--- a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
+++ b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
@@ -1806,23 +1806,6 @@
 };
 
 /**
- * Displays any available (child) sub menu for current selection.
- */
-CommandHandler.COMMANDS_['show-submenu'] = new class extends FilesCommand {
-  execute(event, fileManager) {
-    fileManager.ui.shareMenuButton.showSubMenu();
-  }
-
-  /** @override */
-  canExecute(event, fileManager) {
-    const canExecute = fileManager.taskController.canExecuteShowOverflow();
-    event.canExecute = canExecute;
-    event.command.setHidden(!canExecute);
-  }
-};
-
-
-/**
  * Invoke Sharesheet.
  */
 CommandHandler.COMMANDS_['invoke-sharesheet'] = new class extends FilesCommand {
diff --git a/ui/file_manager/file_manager/foreground/js/file_tasks.js b/ui/file_manager/file_manager/foreground/js/file_tasks.js
index d888c4b..deddc47 100644
--- a/ui/file_manager/file_manager/foreground/js/file_tasks.js
+++ b/ui/file_manager/file_manager/foreground/js/file_tasks.js
@@ -1053,8 +1053,6 @@
         shareMenuButton.menu.querySelector('cr-menu-item[command="#share"]');
     const driveShareCommandSeparator =
         shareMenuButton.menu.querySelector('#drive-share-separator');
-    const moreActionsSeparator =
-        shareMenuButton.menu.querySelector('#more-actions-separator');
 
     // Update share command.
     driveShareCommand.command.canExecuteChange(
@@ -1062,23 +1060,12 @@
 
     // Hide share icon for New Folder creation.  See https://crbug.com/571355.
     shareMenuButton.hidden = true;
-    moreActionsSeparator.hidden = true;
 
     // Show the separator if Drive share command is enabled and there is at
     // least one other share actions.
     driveShareCommandSeparator.hidden =
         driveShareCommand.disabled || tasks.length == 0;
 
-    // Temporarily remove the more actions item while the rest of the menu
-    // items are being cleared out so we don't lose it and make it hidden for
-    // now
-    const moreActions = shareMenuButton.menu.querySelector(
-        'cr-menu-item[command="#show-submenu"]');
-    moreActions.remove();
-    moreActions.setAttribute('hidden', '');
-    // Remove the separator as well
-    moreActionsSeparator.remove();
-
     // Clear menu items except for drive share menu and a separator for it.
     // As querySelectorAll() returns live NodeList, we need to copy elements to
     // Array object to modify DOM in the for loop.
@@ -1087,36 +1074,6 @@
     for (const item of itemsToRemove) {
       item.parentNode.removeChild(item);
     }
-    // Clear menu items in the overflow sub-menu since we'll repopulate it
-    // with any relevant items below.
-    if (shareMenuButton.overflow !== null) {
-      while (shareMenuButton.overflow.firstChild !== null) {
-        shareMenuButton.overflow.removeChild(
-            shareMenuButton.overflow.firstChild);
-      }
-    }
-
-    // Add menu items for the new tasks.
-    const items = this.createItems_(tasks);
-    let menu = /** @type {!Menu} */ (shareMenuButton.menu);
-    for (let i = 0; i < items.length; i++) {
-      // If we have at least 10 entries, split off into a sub-menu
-      if (i == NUM_TOP_LEVEL_ENTRIES && MAX_NON_SPLIT_ENTRIES <= items.length) {
-        moreActions.removeAttribute('hidden');
-        moreActionsSeparator.hidden = false;
-        menu = shareMenuButton.overflow;
-      }
-      const menuitem = menu.addMenuItem(items[i]);
-      decorate(menuitem, FilesMenuItem);
-      menuitem.data = items[i];
-      if (items[i].iconType) {
-        menuitem.style.backgroundImage = '';
-        menuitem.setAttribute('file-type-icon', items[i].iconType);
-      }
-    }
-    // Replace the more actions menu item and separator
-    shareMenuButton.menu.appendChild(moreActionsSeparator);
-    shareMenuButton.menu.appendChild(moreActions);
   }
 
   /**
diff --git a/ui/file_manager/file_manager/foreground/js/task_controller.js b/ui/file_manager/file_manager/foreground/js/task_controller.js
index 2f0e8099..4897a05 100644
--- a/ui/file_manager/file_manager/foreground/js/task_controller.js
+++ b/ui/file_manager/file_manager/foreground/js/task_controller.js
@@ -123,11 +123,6 @@
     this.canExecuteOpenActions_ = false;
 
     /**
-     * @private {boolean}
-     */
-    this.canExecuteMoreActions_ = false;
-
-    /**
      * @private {!Command}
      * @const
      */
@@ -153,14 +148,6 @@
         assertInstanceof(document.querySelector('#more-actions'), Command);
 
     /**
-     * Show sub menu command that uses #show-submenu as selector.
-     * @private {!Command}
-     * @const
-     */
-    this.showSubMenuCommand_ =
-        assertInstanceof(document.querySelector('#show-submenu'), Command);
-
-    /**
      * @private {Promise<!FileTasks>}
      */
     this.tasks_ = null;
@@ -181,8 +168,6 @@
         'select', this.onTaskItemClicked_.bind(this));
     ui.shareMenuButton.menu.addEventListener(
         'activate', this.onTaskItemClicked_.bind(this));
-    ui.shareSubMenu.addEventListener(
-        'activate', this.onTaskItemClicked_.bind(this));
     this.selectionHandler_.addEventListener(
         FileSelectionHandler.EventType.CHANGE,
         this.onSelectionChanged_.bind(this));
@@ -463,23 +448,6 @@
   }
 
   /**
-   * Returns whether open with command can be executed or not.
-   * @return {boolean} True if open with command is executable.
-   */
-  canExecuteMoreActions() {
-    return this.canExecuteMoreActions_;
-  }
-
-  /**
-   * Returns whether show sub-menu command can be executed or not.
-   * @return {boolean} True if show-submenu command is executable.
-   */
-  canExecuteShowOverflow() {
-    // TODO (adanilo@) extend this for general sub-menu case
-    return this.ui_.shareMenuButton.overflow.firstChild !== null;
-  }
-
-  /**
    * Updates tasks menu item to match passed task items.
    *
    * @param {!Array<!chrome.fileManagerPrivate.FileTask>} openTasks List of OPEN
@@ -518,7 +486,6 @@
     this.canExecuteOpenActions_ = openTasks.length > 1;
     this.openWithCommand_.canExecuteChange(this.ui_.listContainer.element);
 
-    this.canExecuteMoreActions_ = nonOpenTasks.length >= 1;
     this.moreActionsCommand_.canExecuteChange(this.ui_.listContainer.element);
 
     this.ui_.tasksSeparator.hidden =
diff --git a/ui/file_manager/file_manager/foreground/js/task_controller_unittest.m.js b/ui/file_manager/file_manager/foreground/js/task_controller_unittest.m.js
index 5891b6c..6aed8fbd 100644
--- a/ui/file_manager/file_manager/foreground/js/task_controller_unittest.m.js
+++ b/ui/file_manager/file_manager/foreground/js/task_controller_unittest.m.js
@@ -79,7 +79,6 @@
     '<command id="default-task">',
     '<command id="open-with">',
     '<command id="more-actions">',
-    '<command id="show-submenu">',
   ].join('');
 
   // Initialize Command with the <command>s.
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js b/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js
index be06c38..07645bde 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js
@@ -349,13 +349,6 @@
     });
 
     /**
-     * @type {!Menu}
-     * @const
-     */
-    this.shareSubMenu = util.queryDecoratedElement('#share-sub-menu', Menu);
-    this.shareMenuButton.overflow = this.shareSubMenu;
-
-    /**
      * Banners in the file list.
      * @type {Banners|BannerController}
      */
diff --git a/ui/file_manager/file_manager/main.html b/ui/file_manager/file_manager/main.html
index 8677a27bc..5b8cf06 100644
--- a/ui/file_manager/file_manager/main.html
+++ b/ui/file_manager/file_manager/main.html
@@ -136,7 +136,6 @@
       <command id="default-task">
       <command id="open-with" label="$i18n{OPEN_WITH_BUTTON_LABEL}">
       <command id="more-actions" label="$i18n{MORE_ACTIONS_BUTTON_LABEL}">
-      <command id="show-submenu" label="$i18n{MORE_ACTIONS_BUTTON_LABEL}">
       <command id="invoke-sharesheet" label="$i18n{SHARESHEET_BUTTON_LABEL}">
       <command id="toggle-holding-space">
       <command id="go-to-file-location"
@@ -330,10 +329,6 @@
         <cr-menu-item command="#share-with-plugin-vm"></cr-menu-item>
         <cr-menu-item command="#manage-plugin-vm-sharing"></cr-menu-item>
         <hr id="drive-share-separator">
-        <hr id="more-actions-separator">
-        <cr-menu-item command="#show-submenu"
-                  visibleif="full-page" class="hide-on-toolbar"
-                  sub-menu="#share-sub-menu" hidden></cr-menu-item>
       </cr-menu>
 
       <cr-menu id="providers-menu"
@@ -350,8 +345,6 @@
         <cr-menu-item command="#delete">$i18n{DELETE_BUTTON_LABEL}</cr-menu-item>
       </cr-menu>
 
-      <cr-menu id="share-sub-menu" class="chrome-menu files-menu"
-               menu-item-selector="cr-menu-item">
       </cr-menu>
     </menus>
 
diff --git a/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc b/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc
index 385819c..a039b40 100644
--- a/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc
+++ b/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc
@@ -125,7 +125,7 @@
     return false;
   }
 
-  // Create new new data source and offers |data|.
+  // Create new data source and offers |data|.
   SetOfferedExchangeDataProvider(data);
   data_source_ = data_device_manager_->CreateSource(this);
   data_source_->Offer(GetOfferedExchangeDataProvider()->BuildMimeTypesList());
diff --git a/ui/ozone/platform/wayland/host/wayland_exchange_data_provider.cc b/ui/ozone/platform/wayland/host/wayland_exchange_data_provider.cc
index 592f730..51ef4e2 100644
--- a/ui/ozone/platform/wayland/host/wayland_exchange_data_provider.cc
+++ b/ui/ozone/platform/wayland/host/wayland_exchange_data_provider.cc
@@ -5,6 +5,7 @@
 #include "ui/ozone/platform/wayland/host/wayland_exchange_data_provider.h"
 
 #include <cstdint>
+#include <memory>
 #include <string>
 #include <vector>
 
@@ -46,6 +47,8 @@
     return OSExchangeData::HTML;
   if (base::StartsWith(mime_type, ui::kMimeTypeOctetStream))
     return OSExchangeData::FILE_CONTENTS;
+  if (mime_type == ui::kMimeTypeWebCustomData)
+    return OSExchangeData::PICKLED_DATA;
   return 0;
 }
 
@@ -157,6 +160,13 @@
 
 WaylandExchangeDataProvider::~WaylandExchangeDataProvider() = default;
 
+std::unique_ptr<OSExchangeDataProvider> WaylandExchangeDataProvider::Clone()
+    const {
+  auto clone = std::make_unique<WaylandExchangeDataProvider>();
+  CopyData(clone.get());
+  return clone;
+}
+
 std::vector<std::string> WaylandExchangeDataProvider::BuildMimeTypesList()
     const {
   // Drag'n'drop manuals usually suggest putting data in order so the more
@@ -251,6 +261,14 @@
     out_content->append(base::UTF16ToUTF8(data));
     return true;
   }
+  if (HasCustomFormat(ui::ClipboardFormatType::WebCustomDataType())) {
+    base::Pickle pickle;
+    GetPickledData(ui::ClipboardFormatType::WebCustomDataType(), &pickle);
+    *out_content = std::string(reinterpret_cast<const char*>(pickle.data()),
+                               pickle.size());
+    return true;
+  }
+
   return false;
 }
 
diff --git a/ui/ozone/platform/wayland/host/wayland_exchange_data_provider.h b/ui/ozone/platform/wayland/host/wayland_exchange_data_provider.h
index 1aaa7d6c..8bd659f 100644
--- a/ui/ozone/platform/wayland/host/wayland_exchange_data_provider.h
+++ b/ui/ozone/platform/wayland/host/wayland_exchange_data_provider.h
@@ -22,6 +22,9 @@
       delete;
   ~WaylandExchangeDataProvider() override;
 
+  // OSExchangeDataProvider:
+  std::unique_ptr<OSExchangeDataProvider> Clone() const override;
+
   // Builds up the mime types list corresponding to the data formats available
   // for this instance.
   std::vector<std::string> BuildMimeTypesList() const;
diff --git a/ui/ozone/platform/wayland/ozone_platform_wayland.cc b/ui/ozone/platform/wayland/ozone_platform_wayland.cc
index 64db5e8..bd5d34f 100644
--- a/ui/ozone/platform/wayland/ozone_platform_wayland.cc
+++ b/ui/ozone/platform/wayland/ozone_platform_wayland.cc
@@ -87,6 +87,8 @@
     // generated inside Chrome, and the flag is properly set.
     // See also WaylandEventSource.
     KeyEvent::SetSynthesizeKeyRepeatEnabled(false);
+
+    OSExchangeDataProviderFactoryOzone::SetInstance(this);
   }
 
   OzonePlatformWayland(const OzonePlatformWayland&) = delete;
diff --git a/weblayer/browser/content_browser_client_impl.cc b/weblayer/browser/content_browser_client_impl.cc
index befa64a..b7203d5 100644
--- a/weblayer/browser/content_browser_client_impl.cc
+++ b/weblayer/browser/content_browser_client_impl.cc
@@ -641,9 +641,10 @@
   }
 }
 
-bool ContentBrowserClientImpl::ShouldDisableSiteIsolation() {
+bool ContentBrowserClientImpl::ShouldDisableSiteIsolation(
+    content::SiteIsolationMode site_isolation_mode) {
   return site_isolation::SiteIsolationPolicy::
-      ShouldDisableSiteIsolationDueToMemoryThreshold();
+      ShouldDisableSiteIsolationDueToMemoryThreshold(site_isolation_mode);
 }
 
 std::vector<std::string>
diff --git a/weblayer/browser/content_browser_client_impl.h b/weblayer/browser/content_browser_client_impl.h
index abf9d5d..f092448 100644
--- a/weblayer/browser/content_browser_client_impl.h
+++ b/weblayer/browser/content_browser_client_impl.h
@@ -119,7 +119,8 @@
   void OverridePageVisibilityState(
       content::RenderFrameHost* render_frame_host,
       content::PageVisibilityState* visibility_state) override;
-  bool ShouldDisableSiteIsolation() override;
+  bool ShouldDisableSiteIsolation(
+      content::SiteIsolationMode site_isolation_mode) override;
   std::vector<std::string> GetAdditionalSiteIsolationModes() override;
   void PersistIsolatedOrigin(
       content::BrowserContext* context,
diff --git a/weblayer/browser/site_isolation_browsertest.cc b/weblayer/browser/site_isolation_browsertest.cc
index 1e1040f9..8f9c3d28 100644
--- a/weblayer/browser/site_isolation_browsertest.cc
+++ b/weblayer/browser/site_isolation_browsertest.cc
@@ -34,9 +34,9 @@
  public:
   SiteIsolationBrowserTest() {
     feature_list_.InitWithFeaturesAndParameters(
-        {{site_isolation::features::kSitePerProcessOnlyForHighMemoryClients,
+        {{site_isolation::features::kSiteIsolationMemoryThresholds,
           {{site_isolation::features::
-                kSitePerProcessOnlyForHighMemoryClientsParamName,
+                kPartialSiteIsolationMemoryThresholdParamName,
             "128"}}},
          {site_isolation::features::kSiteIsolationForPasswordSites, {}}},
         {});
diff --git a/weblayer/browser/site_isolation_policy_unittest.cc b/weblayer/browser/site_isolation_policy_unittest.cc
index 20f8fe00..6d462557 100644
--- a/weblayer/browser/site_isolation_policy_unittest.cc
+++ b/weblayer/browser/site_isolation_policy_unittest.cc
@@ -55,11 +55,18 @@
     EXPECT_EQ(512, base::SysInfo::AmountOfPhysicalMemoryMB());
   }
 
+  // Sets the same memory threshold for both strict site isolation and partial
+  // site isolation modes, since these tests care about both. For example,
+  // UseDedicatedProcessesForAllSites() depends on the former, while preloaded
+  // isolated origins use the latter.
   void SetMemoryThreshold(const std::string& threshold) {
     threshold_feature_.InitAndEnableFeatureWithParameters(
-        site_isolation::features::kSitePerProcessOnlyForHighMemoryClients,
+        site_isolation::features::kSiteIsolationMemoryThresholds,
         {{site_isolation::features::
-              kSitePerProcessOnlyForHighMemoryClientsParamName,
+              kStrictSiteIsolationMemoryThresholdParamName,
+          threshold},
+         {site_isolation::features::
+              kPartialSiteIsolationMemoryThresholdParamName,
           threshold}});
   }